app-dev Node it owns a checkout or worktree. On an app-prod Node it owns a Unix user and a production home with releases. The Project type decides whether it gets a Route.
Applications walks through the lifecycle. Production release layout, Instance setup and teardown, Instance cloning, Instance transfer, Instance removal, and Database connections own the contracts behind these commands.
Commands
Instance JSON includes nullableseed_path and seed_commit. On default, these name its checkout and the last commit that deployed there. Read them before creating a linked worktree for instance:register; use that commit rather than a newer origin/main. Human tables keep their existing columns.
Every command accepts --json. Machine output never supplies consent. Human list commands use tables, with labeled records when the terminal is too narrow; detail commands show a tree and slow requests show progress. instance:deploy and instance:rollback return newline-delimited JSON (NDJSON) instead of one document.
Placement commands create, adopt, inspect, and remove an Instance on one Node.
Release commands prepare and operate a production Instance.
Attachment commands write a registered Database connection into stored Instance configuration.
Analytics commands publish the tracking hosts that send visits to the analytics role.
Dependency commands read and update the root packages of an Instance. Instance dependencies owns the inventory and refresh rules.
orbit instance:create
Create a development Instance on a Node with the activeapp-dev role. A Node with the active app-prod role returns instance.candidate_required, including a repeat for an existing production Instance. Create a production Instance with instance:clone.
Development placement and branch selection follow the requested name.
default_branch when required returns instance.branch_resolution_failed, not a different fallback branch. An invalid Git branch name returns validation.failed before source changes.
A create that fails before activation removes its owned resources and Instance row without teardown. The response keeps the original error code. Once cleanup completes, a new create can select a different branch. If an interruption or incomplete cleanup leaves a pre-activation Instance, an identical retry resumes it; a retry that changes the root or --branch returns instance.placement_conflict. Incomplete cleanup reports details.cleanup = "incomplete" and a recovery command. An identical retry finishes a started cleanup first, without --force, and then creates the Instance. instance:destroy accepts reserved, checkout_prepared, and source_resolved for pre-activation removal.
The Instance becomes active once Orbit has prepared the source, PHP runtime, Laravel URL, and Route. Setup runs after that. A successful create response also means every setup step succeeded; an empty list counts as success. The application can still fail for other reasons.
instance.setup_step_unavailable with outcome: missing, naming the step, Node, and exit 127 or 126. That classification and diagnostic survive rollback, including an incomplete or unconfirmed cleanup annotation. Other command failures return instance.setup_step_failed. See Instance setup and teardown.
orbit instance:rename
Record a Git branch that is already checked out, change the Instance’s Route domain, or do both. Only an active development checkout is eligible. This command does not rename the Instance, move its directory, change its starting commit, or run Git commands that alter the checkout.
Supply at least one of
--branch and --domain. Supplied values must be nonempty strings. The command needs no --yes or --force: it records intent and converges the Route without discarding source. In a terminal, an omitted Instance selector uses the shared Instance selection prompt; in noninteractive or JSON mode it returns instance.id_invalid. There is no implicit branch or domain selection.
Rename the branch locally before recording it. Orbit checks the managed checkout’s identity and the supplied branch locally on the Node, with no origin access. A dirty or unpublished branch can be recorded. Normal removal still requires clean, published source.
selected_branch and branch_override. Recording the already recorded branch is a no-op that preserves its existing override. A domain-only request does not change either branch field. The domain follows Route replacement; Laravel’s stored APP_URL, .env, and cached configuration follow it. Generated provenance stays generated, so a later Project slug or effective-TLD change can recompute the domain.
All supplied fields, checkout identity, the supplied branch, and domain availability are checked before mutation. A combined request with a branch mismatch or domain conflict changes nothing. A changed branch is recorded only after any requested domain convergence succeeds. An identical retry after a completed rename returns the Instance without creating an additional Route, including when the caller lost the success response. An incomplete Route replacement follows the existing recovery rules. If a full rollback before cutover deleted the failed replacement, an identical retry can reserve a fresh replacement; the changed branch is still recorded only after domain convergence succeeds. A different domain while replacement recovery is incomplete is refused. See recorded branch behavior and Route recovery.
Human output
The command shows truthful waiting feedback during the synchronous request, then the shared Instance detail tree. Project and Node labels use their slug and name. It does not show a Process selector or invent remote progress stages. The following abbreviated example shows the fields affected by a combined rename; the full tree also has the usual ID, placement, root, and Vite-port fields:instance.branch_not_checked_out tells the caller to check out the requested branch first. Success exits with status 0; a refusal or failed convergence exits with status 1.
JSON and API output
The API isPOST /api/v1/instances/{instance}/rename with optional branch and domain, for example {"branch":"t3code/login-redirect","domain":"login-redirect.acme.test"}. At least one field is required; null, empty, and wrong-type values are invalid. The MCP tool is instance-rename, with instance_id and the same optional fields.
Success returns the full Instance shape used by GET /api/v1/instances/{instance} and instance:show --json, including Project and Node identities, source and placement fields, route, domain, url, removal and transfer state, deploy steps, and request_id. It has no rename-specific envelope. This abbreviated JSON example selects fields from that response, not a separate response schema:
error.code, the message under error.message, and the request correlation ID under error.request_id. JSON output contains no human tree, prompt, or animation.
Refusal codes
Authentication, access and missing-record errors, and more specific Route projection errors retain the shared API error contract. A preflight refusal changes nothing. Infrastructure failure during convergence follows Route rollback before cutover and forward recovery after cutover; it is not a promise of atomic rollback across the Node and Gateway.
orbit instance:register
Adopt the current Git checkout or worktree as a managed Instance of an existing Project. Run it on the app-dev Node that holds the source.
The CLI refuses a directory outside Git and an origin with credentials before it sends a request. The Gateway finds the Project by repository identity, checks the source on the caller’s Node, moves it into its managed path, and provisions it as
instance:create does. See Register an existing checkout.
Registration never creates a Project. When no Project owns the repository, it fails with instance.project_missing. Run project:create first.
In a terminal, the CLI asks for default-No consent that names the source. JSON and noninteractive calls need --yes. Cancellation leaves the source unchanged.
orbit instance:list
List Instances with their Project, Node, status, Route domain,vite_port, and removal progress. JSON also includes annotator_port and annotator_url; both are null when no annotator port is assigned, and the URL is null without a Route. JSON includes the assigned SSR port as ssr_port, which is null when none is assigned.
orbit instance:show
Show one Instance. When theannotator Process has an assigned port, human output includes Annotator port and Annotator URL. The URL uses the Instance’s Route, for example https://commander.test/__orbit/annotator; without a Route, the display is an em dash. JSON keeps the annotator_port and annotator_url fields even when they are null. See Annotator Process. Human output shows the assigned SSR port as SSR port beside Vite port, and JSON has ssr_port. Both are empty when no SSR port is assigned.
Production output includes the recorded user, home, selected branch, and deploy steps in phase and placement order.
Human output lists the Instance’s Routes with their domain, web root, and status. JSON has them under routes; route stays the Instance’s own Route. See Serve several web roots.
orbit instance:logs
Return the end of the Instance’s application log,storage/logs/laravel.log or the newest laravel-*.log, or follow new lines as they are written. Stored environment values and credential-shaped data are redacted. Instance logs describes the file and the redaction.
--follow works as it does for process:logs: the CLI opens a live log stream, and it polls the one-shot read every 5 seconds when the Gateway cannot open one. A production Instance log is always read over SSH: the CLI prints Following over SSH; polling every 5 seconds. and polls from the start. The JSON output has the same shapes, with reason ssh_only in the notice. Without --follow, --json returns { id, name, lines, logs, request_id }.
orbit instance:destroy
Remove an Instance with its Route, Processes, Schedules, and runtime. A development removal runs the teardown steps first and deletes the checkout. See Instance removal.
Interactive removal defaults to No.
--force does not supply consent.
Normal removal refuses dirty source, a HEAD that no origin branch or tag contains, and a checkout with registered linked worktrees. --force waives only those three refusals. The source identity checks apply in both modes.
orbit instance:setup
Run the Project setup steps for one development Instance. The command runs every step from the start of the list. A failed step leaves the Instance in place.orbit instance:setup-step:create
Record one named setup step on a Project. The step is a command string. Orbit stores the row and does not write a file into a checkout.orbit instance:setup-step:list
List a Project’s setup steps in order.orbit instance:setup-step:update
Change the command, timeout, or position of one setup step.--rebalance=NAME=SECONDS sets other steps’ timeouts in the same write, as for create.
orbit instance:setup-step:destroy
Remove one setup step. Interactive confirmation defaults to No. JSON and noninteractive calls require--yes.
orbit instance:teardown-step:create
Record one named teardown step on a Project. The arguments matchinstance:setup-step:create.
orbit instance:teardown-step:list
List a Project’s teardown steps in order.orbit instance:teardown-step:update
Change the command, timeout, or position of one teardown step.orbit instance:teardown-step:destroy
Remove one teardown step. Interactive confirmation defaults to No. JSON and noninteractive calls require--yes.
orbit instance:clone
Clone a candidate into a prepared production Instance. The candidate supplies source, stored environment values, and an optional SQLite snapshot. The Project supplies production Process and Schedule definitions.
Give the production Node a TLD with
node:add --tld first: shop.com on a Node with TLD prod.orbit becomes the preview shop.com.prod.orbit. The candidate must be clean, and its commit must be in the Project repository.
instance:deploy. See Instance cloning.
orbit instance:update
Change the deployment branch of a production Instance. The Gateway stores the branch and does not change deploy steps or start a deployment. The human result shows the accepted deployment branch and the currently selected source branch. JSON returns the existing Instance response; itsselected_branch describes the source, not the newly stored deployment setting.
The Gateway refuses a development Instance with a bounded conflict before it stores a branch.
orbit instance:deploy-step:create
Record one named deploy step on a production Instance. The Gateway stores it at the end of its phase unless you place it.orbit instance:deploy-step:list
List deploy steps in phase and placement order.--json returns the steps and the request_id as one object.
orbit instance:deploy-step:update
Change one named deploy step. Options you omit stay unchanged.orbit instance:deploy-step:destroy
Remove one named deploy step. Remaining steps keep their relative order. Confirm the named target at a default-No prompt, or pass--yes. JSON and noninteractive calls require --yes.
orbit instance:deploy
Deploy a production Instance or an app-devdefault Instance. For production, the Gateway creates a fresh release, fetches the configured branch, synchronizes stored environment values, runs the before_activation steps, atomically replaces current, refreshes the PHP runtime cache, and runs the after_activation steps. For a development default, it fetches the Project’s default branch, checks out its newest commit in the default’s checkout, and runs the Project’s development deploy steps there. It refuses a checkout with uncommitted changes to tracked files. A failed required step leaves the new commit checked out, and the next scheduled tick retries. A best-effort failure reports a warning and the deployment continues. See Instance releases.
Human output shows a progress tree. The deploy phases the Gateway always sends appear up front; named deploy steps and the PHP cache refresh phase reveal only when their phase starts. Glyphs and color show waiting, running, success, failure, and not-reached states, and active indicators alternate while work is in progress. Standard output and standard error from application commands appear labeled and escaped, and print above the tree without redrawing it, while their step runs.
On failure the tree marks the last reached step as failed, with the error code shown under it, even when the Gateway’s failed boundary has no step of its own (an activation or cache-refresh failure during a rollback, for example). Every later step shows orange with a dim “Not reached.” label under it, and the footer turns red. The final lines add the failed boundary, the error code, the selected release when available, and the request ID.
--json writes the same events as NDJSON, one event per line, without prompts or prose.
Pressing Ctrl-C closes the connection at once, including during a step with no output yet: the CLI does not wait for the Gateway to finish that step first. The tree marks the current step failed and shows a red “Operation interrupted.” footer; JSON mode ends the stream with no result line. Either way the CLI submits no second request.
Every event carries
type, a monotonically increasing sequence, and the request_id. A failed result stays a result event; the CLI uses the one-line error envelope only when the Gateway refuses the command before the stream opens or when the stream is malformed or truncated.
before_activation step leaves the prior current selected. A failure during the PHP cache refresh or an after_activation step leaves the fresh release selected. Deployment, rollback, deploy-step changes, environment changes, and removal share one operation owner per Instance, so a competing request waits or returns a busy refusal.
Only
default can be deployed on an app-dev Node. Other development Instances still return deployment_config.unavailable. Releases, rollback, and per-Instance deploy-step operations remain production-only; instance:release:list shows none for a development default.orbit instance:release:list
List retained release names and the current selection. A production home keeps at most 3 releases, as Retained releases describes. Seeinstance:deployment:list for the recorded run history behind those releases.
orbit instance:rollback
Select one retained release throughcurrent. A successful deployment keeps the previous selection and one other release, so these are the rollback targets. Rollback does not fetch Git, synchronize environment values, run deploy steps, or change database files.
The command streams the same
phase, output, and result events as instance:deploy, with the rollback phase, and uses the same exit status table.
orbit instance:deployment:list
List the deployment history the Gateway recorded for a production Instance, newest first. The Gateway writes one row wheninstance:deploy or instance:rollback starts and fills it in when the run finishes, and keeps the last 50 rows per Instance.
The table shows Started, Release, Branch, Commit, By, Duration, and Status.
By is the calling Node’s name, since the Gateway authorizes every command as a Node. A row still running when read shows running and an empty Finished, Duration, and Release until the run completes.
orbit instance:deployment:show
Show one recorded deployment: a detail tree of its identity and outcome, then the phases and steps it went through as a table, then its log.
The detail tree shows the Instance ID, release, branch, commit, started and finished times, duration, status, failed step, error code, selected release, and who triggered it. The phases table repeats the
phase and step_name values the run streamed. The log reproduces the run’s standard output and standard error lines in order.
orbit instance:database:add
Add a registered Database connection on an Instance and write prefixed keys into its stored environment configuration.
For mysql and pgsql the Gateway writes
DB_CONNECTION, DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, and DB_PASSWORD. For sqlite it writes DB_CONNECTION=sqlite and DB_DATABASE as the absolute path, plus username and password only when stored. The Gateway writes the connection’s stored host and port, also when the Instance runs on the connection’s Node.
orbit env:sync --instance=SELECTOR to install it in the workload .env.
orbit instance:database:remove
Remove a Database connection from an Instance and clear the prefixed stored keys. Other stored keys stay in place.database.attachment_missing.
orbit instance:analytics:enable
Publish the tracking hosts that send an Instance’s visits to the analytics role./js/* and /api/event, served wherever the Instance’s own domain is served; the Analytics role page owns that contract.
Human output lists each host with its Route and status, the DNS record to create for it, and the script tag to add to the Project. JSON returns instance_id, enabled, domain, dashboard_url, hosts, and snippet. You still create the site in Plausible yourself.
orbit instance:analytics:show
Show the tracking hosts of an Instance.instance:analytics:enable. An Instance without tracking hosts reports tracking as disabled, with no hosts and no script tag.
orbit instance:analytics:disable
Remove every tracking host of an Instance.
Plausible stops receiving visits for the Instance as soon as the hosts are gone. The data already in Plausible stays. Running the command again for an Instance without hosts succeeds and changes nothing.
orbit instance:transfer
Move an active development Instance to anotherapp-dev Node. Both Nodes must belong to active Clusters. The transfer stops the source, copies it into an independent checkout, moves or replaces its Route, and deletes the old placement. See Instance transfer.
Without
--force, an interactive call asks for default-No consent naming the source, destination and effect. JSON and noninteractive calls without --force return instance.confirmation_required before mutation.
orbit instance:dependencies:scan
Read the root manifests and lockfiles of an Instance and record its package inventory. The Gateway changes no file.
The exit status is zero only when every scanned ecosystem succeeds. See Scan for the output and errors.
orbit instance:dependencies:update
Update the Composer and JavaScript packages of one development Instance within their declared constraints, then scan it again. A production Instance returnsdependencies.production_update_forbidden.
See Update a development Instance for the steps it runs.
Related
projectowns the repository and source defaults that an Instance inherits.routeshows and changes the domain of an Instance.envimports, updates, and synchronizes the stored environment that deployments render.processandschedulerun services and timers on an Instance.databaseregisters the connections thatinstance:database:addattaches.analyticspins the Plausible version that the tracking hosts send visits to.