Skip to main content
An Instance is one copy of a Project on one Node. On an 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 nullable seed_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 active app-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.
A requested origin branch keeps its existing selection behavior. Orbit does not reset an existing local branch to the default commit. A missing fetched 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.
A failed setup step removes the new Instance after the teardown steps run. A missing or non-executable setup command returns 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.
A changed branch updates 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:
A refusal shows the stable error code and a useful message, with no success tree. For example, 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 is POST /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:
Failures use the existing error shape, with the stable code under 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 the annotator 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.
Production removal keeps releases/, .env, database.sqlite, and the local PHP-FPM tuning. Repeat the same command to resume an interrupted removal. A failed teardown step keeps the Instance, and the next instance:destroy runs the teardown list again.

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.
Instance setup and teardown owns the field limits, order, and execution contract. List, update, and destroy use the same Project selector and step name.

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 match instance: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.
Cloning ends with an active Instance and no release. Update its environment, record deploy steps, then run 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; its selected_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.
The Gateway refuses a duplicate name, a placement that names an unknown step or a step in another phase, a thirty-third step, a timeout over 900 seconds, or a step-timeout sum over 3,600 seconds.

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-dev default 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.
A failure during release fetch, environment synchronization, or a 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. See instance:deployment:list for the recorded run history behind those releases.

orbit instance:rollback

Select one retained release through current. 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 selects the older code only. You own any data or application recovery that the switch needs.

orbit instance:deployment:list

List the deployment history the Gateway recorded for a production Instance, newest first. The Gateway writes one row when instance: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.
Add changes stored configuration only. Run 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.
An unknown attachment returns database.attachment_missing.

orbit instance:analytics:enable

Publish the tracking hosts that send an Instance’s visits to the analytics role.
The command sets the exact host set: the Gateway publishes each named host that is missing and removes each tracking host of the Instance that you did not name. Naming the hosts that already exist changes nothing. Each host is a Route that answers only /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.
The output has the same shape as 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 another app-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.
Use these options to select the destination and confirm downtime. 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 returns dependencies.production_update_forbidden.
See Update a development Instance for the steps it runs.
  • project owns the repository and source defaults that an Instance inherits.
  • route shows and changes the domain of an Instance.
  • env imports, updates, and synchronizes the stored environment that deployments render.
  • process and schedule run services and timers on an Instance.
  • database registers the connections that instance:database:add attaches.
  • analytics pins the Plausible version that the tracking hosts send visits to.