feat(cli): remote-dev commands — sandbox + projectless connectors - #547
Merged
Conversation
Contributor
🚀 Package Preview Available!Install this PR's preview build with npm: npm i @base44-preview/cli@0.0.56-pr.547.db4783dPrefer not to change any import paths? Install using npm alias so your code still imports npm i "base44@npm:@base44-preview/cli@0.0.56-pr.547.db4783d"Or add it to your {
"dependencies": {
"base44": "npm:@base44-preview/cli@0.0.56-pr.547.db4783d"
}
}
Preview published to npm registry — try new features instantly! |
Rebased onto main and aligned with the projectless app-id mechanism added in #541: --app-id is a global program option (bound to BASE44_APP_ID), and requireAppContext commands resolve it through the lifecycle (ensureAppContext -> initAppContext), so commands no longer need a bespoke resolver. Dropped the parallel cli/utils/app-id.ts and the per-command --app-id options from the earlier iteration. Sandbox (new `base44 sandbox <tool>`, wraps apper #11608 sandbox-bridge): - getSandboxClient(appId) + core/resources/sandbox {schema,api} - list-directory/read-file/write-file/edit-file/grep/run-command/release, JSON-first stdout; write/edit payloads via flag or stdin (verbatim) - commands use the default app-context lifecycle and read getAppContext().id Connectors: - new `connectors initiate --integration-type <type> [--scopes <s...>]`: initializes the connector and starts its OAuth flow; prints the URL (agent/non-interactive friendly), opens browser + polls when interactive - pull/push work projectless: when the app context has no projectRoot (explicit --app-id/BASE44_APP_ID) they use ./connectors (--dir override); otherwise the linked project's connectors dir - list-available already works projectless via the lifecycle (unchanged) Tests: sandbox.spec.ts (9), connectors_initiate.spec.ts (6), projectless cases for connectors pull/list-available. README updated. typecheck/lint/ knip clean. Pre-existing dev/exec spec failures are environment-dependent (deno/network) and reproduce on clean main. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
carmelc
force-pushed
the
feat/sandbox-remote-dev-commands
branch
from
June 17, 2026 14:47
accfe99 to
18a591d
Compare
Align the backend-function test fixtures and specs with the canonical entry.ts convention (matching base44/skills#121): rename the config-based fixtures' index.ts entry files to entry.ts, update their function.jsonc "entry" fields, and update all specs that referenced index.ts as a function entry/path (project, function-config, function-schema, functions deploy/ list/pull, logs). The CLI's own docs (docs/resources.md) and source already use entry.ts; this removes the stale index.ts examples from fixtures. Config-based discovery still supports an arbitrary entry filename — when we document/support that explicitly we'll add a dedicated index.ts example + test back. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The sandbox-bridge mutating tools (write/edit/run-command) require the sandbox:write OAuth scope, which is deliberately kept out of the backend's DEFAULT_SCOPE so shell access is never granted silently. Request it explicitly in the device-code flow alongside apps:read/apps:write so `base44 sandbox ...` works after login. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A token issued before sandbox support (or without the sandbox:write scope) gets a 403 from the sandbox-bridge endpoints. Augment forbidden responses from sandbox commands with a hint to run 'base44 login' again to grant sandbox access, while preserving the server's original error/hints. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The previous blanket 403 hint was wrong: the HTTP sandbox-bridge endpoints
the CLI calls authorize via the platform JWT + app-admin and do NOT enforce
sandbox:write (that check is MCP-only). Their 403s — feature-flag-off,
blocked app, view-only, wrong app type — are generic and not fixed by
re-login.
Detect the scope rejection specifically by matching the response wording
("sandbox:write" / "granting sandbox access", as emitted by the scope check)
instead of any 403, so the re-login hint only appears when it would actually
help. Added a test asserting a generic 403 (view-only) does NOT get the hint.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add `--json` as a global program option (like --app-id) instead of a per-command flag. The lifecycle centralizes the behavior: - index.ts forces non-interactive wiring when --json is present, so the clack spinner and logs go to stderr. - CLIContext gains `jsonMode`; Base44Command skips the clack framing and routes the status line to stderr, keeping stdout a pure JSON document. Any command that sets RunCommandResult.stdout now yields clean JSON under --json. Wired structured JSON output into the connectors commands (list-available, initiate, pull, push); the sandbox commands already emit JSON and now produce it pure. Pre-existing `logs --json` benefits too. Tests: pure-JSON stdout assertions for sandbox + connectors list-available + initiate. typecheck/lint/knip clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make --json a universal contract in Base44Command so every command emits
valid JSON on stdout, even ones that don't build a machine payload:
- success: a command that sets result.stdout gets it verbatim (native JSON,
status to stderr); otherwise the human status line is wrapped as
{ "output": "<text>" } (ANSI stripped).
- failure: any command emits a JSON error envelope on stdout —
{ "error", "code"?, "details"?, "hints"? } from the CLIError fields.
So `base44 whoami --json` -> {"output":"Logged in as: ..."} and a failing
`base44 sandbox list-directory --json` (no app id) -> {"error":"No Base44
app ID found.","code":"...","hints":[...]} instead of empty stdout.
Native/structured output (sandbox, connectors) is kept — it's richer than
the wrapped-status fallback (e.g. initiate still exposes redirectUrl /
connectionId as fields).
Tests: whoami --json (fallback wrap) and sandbox --json error envelope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- README: add a "Global flags" section covering --app-id and --json, with the contract (pure JSON stdout, silent mode, JSON error envelope, universal) and sandbox/jq examples. - AGENTS.md/CLAUDE.md: note that --json forces silent mode in the @clack/prompts rule, and add a rule so new commands keep stdout machine-parseable (return RunCommandResult.stdout, status via outroMessage/log, emit JSON when ctx.jsonMode). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The sandbox namespace already supplies the file/shell context, so the redundant nouns on each subcommand can be dropped to match the CLI's one-word-where-possible naming convention: list-directory -> ls read-file -> read write-file -> write edit-file -> edit run-command -> run grep and release are already concise and unchanged. The scope itself stays `sandbox` to keep the CLI aligned with the platform vocabulary (the sandbox:write OAuth scope, backend, and error hints). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ew3Z6LjEgToj2bZyQHMQb
The sandbox release command is no longer needed. Removes the command, its API client function, response schema, test, and README entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H5MJy3X1QEiXo2NFTD5Hpx
Adds `base44 sandbox checkpoint` to create a restore-point checkpoint of an app's remote sandbox via the create_checkpoint sandbox-bridge tool. Takes an optional --name (message/title; defaults to an auto-generated title) and returns the checkpoint id, name, and git commit hash. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H5MJy3X1QEiXo2NFTD5Hpx
carmelc
force-pushed
the
feat/sandbox-remote-dev-commands
branch
from
June 25, 2026 09:07
06f1f26 to
d08c0ad
Compare
carmelc
added a commit
to base44/skills
that referenced
this pull request
Jun 25, 2026
Add the `base44 sandbox checkpoint` CLI command (base44/cli#547) and the `create_checkpoint` MCP tool (base44-dev/apper#11608) to the base44-remote-dev and base44-sandbox skills, including the sandbox:write scope, the CLI/MCP name mapping, and the COMMIT_FLUSH_PENDING error code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dor-chaouat
approved these changes
Jun 25, 2026
ImriKochWix
added a commit
that referenced
this pull request
Jun 28, 2026
#547 introduced a global --json (ctx.jsonMode) with silent mode, but the logs command still declared its own local --json and read options.json. The global captured --json, leaving options.json undefined, so `logs --json` emitted text instead of JSON (the test fails on main too). Drop the local option and read ctx.jsonMode, matching the sandbox/connectors commands and CLAUDE.md rule 10. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ImriKochWix
added a commit
that referenced
this pull request
Jun 29, 2026
* feat(logs): add --env preview|prod flag Routes the logs request to preview (draft) or prod (published) via the backend's ?env= param. Defaults to preview; --env prod shows a published-app hint when empty. --env all is handled client-side by the caller (two requests). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(logs): honor the global --json flag instead of a local option #547 introduced a global --json (ctx.jsonMode) with silent mode, but the logs command still declared its own local --json and read options.json. The global captured --json, leaving options.json undefined, so `logs --json` emitted text instead of JSON (the test fails on main too). Drop the local option and read ctx.jsonMode, matching the sandbox/connectors commands and CLAUDE.md rule 10. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(logs): use LogEnvSchema zod enum for the env type Replace the repeated "preview" | "prod" literal union with a single LogEnvSchema (z.enum) + LogEnv type in the function schema, mirroring LogLevelSchema. The --env choices derive from LogEnvSchema.options. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
carmelc
added a commit
to base44/skills
that referenced
this pull request
Jun 30, 2026
* feat(base44-sandbox): add cloud-sandbox remote-dev skill flavor Add a focused, separately-installable "sandbox flavor" for developing a Base44 app inside Base44's cloud sandbox (PR base44-dev/apper#11608), where the implementation is remote and writing a backend-function file is what ships it — no local checkout and no Base44 CLI. - skills/base44-sandbox: new hand-authored skill. Backend functions and frontend code are supported; entities, connectors, and agents are marked not-supported-yet; no automations. Concise inline guidance with a pointer to base44-cli's functions-create reference (no duplicated copies). - skills/base44-remote-dev: vendored connection skill (MCP / HTTP bridge, tools, edit→preview→verify loop) from the upstream PR. - New base44-sandbox plugin across channels: second entry in the Claude and Codex marketplaces + plugins/base44-sandbox/ bundle (its own .claude/.codex/ .cursor manifests + skills/assets symlinks). Bundles base44-remote-dev, base44-sandbox, base44-sdk, base44-troubleshooter; excludes deploy-oriented base44-cli. npx skills --skill documented in the README. - validate-template.mjs now discovers and validates all .cursor-plugin manifests (repo root + plugins/*/). - sync-cli-skill flags base44-sandbox for manual review when function authoring conventions change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(base44-sandbox): support connectors via MCP tools and projectless CLI Connectors are now usable in remote-dev (apper#11608 MCP connector tools + cli#547 projectless connectors), so flip them from "not supported" to a documented connect flow: - list_connectors (apps:read) / initiate_connector_connection (apps:write) over MCP, and base44 connectors list-available/initiate/pull over the CLI with --app-id (no local project / config.jsonc). - Document the declarative/replace scope semantics (read current scopes first, pass the complete set) and the human-consent authorization-URL step. - Note the connector CLI is the one allowed CLI use in remote-dev; it targets a remote app by id with no deploy step (not a contradiction of the no-CLI rule, which is about local-project/deploy commands). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(base44-remote-dev): document the connector MCP tools Upstream's base44-remote-dev SKILL.md doesn't yet list the connector tools shipped in apper#11608, so add a "Connectors (OAuth integrations)" section covering list_connectors (apps:read) and initiate_connector_connection (apps:write) — declarative/replace scope semantics and the human-consent redirect-URL step — plus the projectless base44 connectors CLI equivalent. Marked as a local addition (HTML comment) to reconcile when upstream documents these tools. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(base44-remote-dev): drop local-addition note from connectors section The connectors section will align with upstream by merge time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs): use entry.ts as the backend-function entry file The function entry file (and the function.jsonc "entry" value) is entry.ts, not index.ts. Update all function examples across base44-sandbox, base44-sdk, and base44-cli docs (functions-create, automations, project-structure trees). Invocation already uses base44.functions.invoke('name', data) everywhere; no change needed there. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(base44-sandbox): connector token usage, complete README, reference-first - Add "Using a connected connector in code": fetch the OAuth token via base44.asServiceRole.connectors.getConnection(type) inside a backend function, with a link to base44-sdk's connectors reference. - Add a "Reference order & the complete README" section: prefer this skill and its siblings over web search, and point to the public app-specific onboarding README endpoint. - Surface the reference-first note near the top too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(base44-sdk): clarify functions.invoke() returns the raw axios response invoke() resolves to the raw axios response, so the function's JSON is on .data (not the top-level object), and it throws on non-2xx with the error body at err.response.data. Update the invoke method doc and every frontend example to read res.data, and add the warning in SKILL.md + QUICK_REFERENCE. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(base44-sandbox): note invoke() returns raw axios response (.data) Add a small frontend-calling clarification so agents read the function's JSON off res.data and handle the non-2xx throw; link to base44-sdk for detail. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(base44-sandbox): support entities and agents (filesystem-only) Entities and agents are now authorable in the sandbox — writing the .jsonc file auto-syncs, no entities/agents push or deploy. Flip both from "not supported" to supported, broaden the mental model to "writing a resource file is the deploy", and add Entities and Agents authoring sections (file naming, schema, links to base44-cli references with their push/deploy sections flagged as not applicable). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(base44-sandbox): add base44-cli reference to the Agents section Match the functions/entities pattern: link the Agents section to the base44-cli Agent Schema and make clear to ignore agents push/pull/deploy commands (sandbox auto-syncs the file). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(sandbox): drop HTTP bridge surface, document base44 sandbox CLI names Remove the HTTP REST sandbox-bridge option (POST /api/apps/<id>/sandbox-bridge/<tool>) from base44-remote-dev and base44-sandbox; local agents use MCP or the `base44 sandbox` CLI instead. Clarify CLI naming throughout: add the MCP-tool -> CLI-command mapping (list_directory->sandbox ls, read_file->sandbox read, write_file->sandbox write, edit_file->sandbox edit, run_command->sandbox run; grep/release unchanged) and annotate inline tool references with their CLI command names. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01842h6eP9hLWHnoRrERmbLo * docs(sandbox): drop the sandbox release command/tool The release command is no longer supported, so remove it from the base44 sandbox CLI mapping table. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01842h6eP9hLWHnoRrERmbLo * docs(sandbox): document checkpoint command and create_checkpoint tool Add the `base44 sandbox checkpoint` CLI command (base44/cli#547) and the `create_checkpoint` MCP tool (base44-dev/apper#11608) to the base44-remote-dev and base44-sandbox skills, including the sandbox:write scope, the CLI/MCP name mapping, and the COMMIT_FLUSH_PENDING error code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(sandbox): functions need only entry.ts, no function.jsonc In the sandbox the function is inferred from the directory, so authors only create entry.ts under base44/functions/<name>/; the function.jsonc config is not required and is ignored in this mode. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(sandbox): note function.jsonc guidance in cli ref doesn't apply Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
Description
Adds a
base44 sandboxcommand group for developing an app remotely through its server-side sandbox (list, read, write, edit, grep, run, and checkpoint), plus a projectlessconnectors initiatecommand that starts a connector's OAuth flow against any--app-idwithout a local project. It also introduces a global--jsonflag that turns stdout into a single machine-readable JSON document (with silent mode and a JSON error envelope) so the CLI can be driven by scripts and agents. To support the sandbox, the device-login flow now requests thesandbox:writescope and surfaces a re-login hint when that scope is missing.Related Issue
None
Type of Change
Changes Made
sandboxcommand group — new remote-development commands:sandbox ls,read,write,edit,grep,run, andcheckpoint, backed by a newcore/resources/sandboxAPI + Zod schemas and agetSandboxClient(appId)HTTP client scoped to/sandbox-bridge/. Operates on a remote app via--app-idwith no local project required.connectors initiatecommand — initializes a connector and starts its OAuth flow projectlessly; surfaces the authorize URL and polls until authorized (interactive) or prints the link (non-interactive/--json).--jsonflag — exposed asctx.jsonMode; forces non-interactive wiring, routes status/logs to stderr, and emits a single JSON document on stdout.Base44Commandprovides a generic{ "output": "<status>" }fallback and a JSON error envelope ({ error, code, details, hints }) so every command stays parseable.sandbox:write; sandbox API errors add a "runbase44 loginagain" hint only on a genuine missing-scope401/403.readStdin— added anoptions.trimflag to preserve file bodies/trailing newlines verbatim (used bysandbox write/edit).README.md(command table, Global flags,--jsonsection) anddocs/AGENTS.md(rules for--jsonand silent mode).index.tstoentry.ts.Testing
npm test)Checklist
docs/(AGENTS.md) if I made architectural changesAdditional Notes
New tests cover the sandbox commands (
tests/cli/sandbox.spec.ts) andconnectors initiate(tests/cli/connectors_initiate.spec.ts); existing connector/function/logs/whoami specs were updated for the--jsonlifecycle and theentry.tsfixture rename.🤖 Generated by Claude | 2026-06-25 09:08 UTC | db4783d