MachineDocs
Reference

CLI reference

Every machine command, the project-scoped token model, env vars, and exit codes.

The machine CLI drives everything the dashboard can, from a terminal — laptop, coding agent, or session sandbox. For common workflows, see Using the CLI.

Always available inside a session sandbox, no setup:

  • Binary on PATH (/usr/local/bin/machine).
  • MACHINE_CLI_TOKEN pre-injected — the project-scoped token the CLI authenticates with. (MACHINE_TOKEN is also present, but it's the sandbox service key, not a CLI token.)
  • MACHINE_API_URL points at the platform you're running against.

Quickstart inside a session

machine whoami                       # confirms what project + account this token has
machine projects info                # the project you're running inside
machine secrets ls                   # encrypted env vars + manifest [env] spec
machine sessions ls                  # every session on this project (incl. you)
machine cr ls                        # open change requests
machine cr open --title "..."        # propose merging your branch into main

The sandbox token is project-scoped: read+write anything on this project (secrets, sessions, triggers, change requests, apps), but it can't list other projects or touch account-level resources. See Token scope.

On your laptop

curl -fsSL https://machine.com/install | bash
machine login                        # opens browser, you click Authorize

The local CLI uses a user-scoped token at ~/.config/machine/config.json (mode 0600), which sees every project on every account you're a member of.

Command surface

Auth

CommandEffect
machine login [--token <pat>] [--host <name>] [--api <url>]Default: opens browser → click Authorize → token written. --token is the headless fallback. --host logs into a named host slot.
machine logout [--host <name>]Remove the token for the active host (or named one).
machine whoami [--host <name>]Print the user + active account on the chosen host.

Hosts

A host is one Machine API endpoint. The built-ins cloud (Machine Cloud), selfhost (your machine self-host stack), local-dev (a local pnpm dev server), and machine-internal-dev are always available, and you can add more endpoints. One host is active at a time; the CLI prints the active host before operational commands so Cloud/local actions are harder to mix up.

CommandEffect
machine hosts lsList configured hosts ( marks active).
machine hosts use [<name>]Switch active host. No name → arrow-key picker.
machine hosts add <name> --url <url> [--login]Register a new host. --login runs the browser flow right after.
machine hosts rm <name>Remove a host (confirms when it's the last one).
machine hosts info [<name>]Detailed view of one host.
machine hosts currentPrint the active host name (script-friendly).

--host <name> overrides the active host for one invocation: machine projects ls --host local.

Self-host

machine self-host start creates and starts a production-style local Machine stack using Docker Compose. On first interactive setup it only asks for the product integrations you may need: Vercel for app deployments, a GitHub App or PAT for repo access, and Pipedream for app connectors. Local ports, Supabase, generated secrets, and Docker defaults are handled automatically.

CommandEffect
machine self-host startCreate config if needed, start the local stack, and register the selfhost host.
machine self-host configureRe-run the Vercel, GitHub, and Pipedream credential wizard.
machine self-host env lsShow persistent self-host env values, masking populated secrets.
machine self-host env set KEY=VALUE …Update advanced persistent env values before the next start.
machine self-host logs [service]Tail Docker Compose logs.
machine self-host stopStop the stack.

Projects

CommandEffect
machine projects lsEvery project on the active account.
machine projects info [<id-or-slug>]Show one project (defaults to the linked one).
machine projects link [<id>]Bind cwd to a remote project. Writes .machine/link.json with project_id, account_id, host, host_url. No arg → arrow-key picker.
machine projects unlinkDrop .machine/link.json.
machine projects open [<id>]Open the dashboard URL for a project in your browser.

How a command finds "the project"

In strict order:

  1. --project <id> flag.
  2. MACHINE_PROJECT_ID env var.
  3. .machine/link.json in cwd (or any ancestor — git-style).
  4. Inside a session sandbox: the sandbox's own MACHINE_PROJECT_ID.

If none resolve, the command errors pointing to projects link.

How a command finds "the host"

  1. --host <name> flag.
  2. host field in .machine/link.json (so a repo always hits its home Machine instance).
  3. The globally-active host.

Secrets

Encrypted env vars stored on the project, injected as plain env into every session sandbox at boot.

CommandEffect
machine secrets lsList secret names + manifest [env] spec; marks required-but-missing.
machine secrets set NAME=VALUE …Upsert one or more. NAME=- reads VALUE from stdin (so values never appear in shell history).
machine secrets unset NAME …Remove.

Env — dotenv ↔ secrets

CommandEffect
machine env pull [--out .env] [--force]Write a .env skeleton (names only — plaintext can't leave the cloud).
machine env push --from <path>Upload every NAME=VALUE from a dotenv file as a secret. Supports quoted values, export NAME=…, comment lines.

Sessions

Each session is an isolated sandbox VM on its own ephemeral branch.

CommandEffect
machine sessions lsAll sessions on the project.
machine sessions info <id>Detail view: status, branch, base ref, agent, sandbox URL, errors.
machine sessions new [--prompt "<text>"]Start a new session, optionally with an initial prompt.
machine sessions restart <id>Re-provision a session in place.
machine sessions rm <id>Stop + delete.
machine sessions open <id>Open the dashboard URL for a session.
machine sessions chat [<id>] [--prompt "<text>"] [--new]Talk to a session's agent — interactive REPL, or one-shot with --prompt. Alias: talk.
machine sessions preview <id> [port]Print a clickable preview URL for a port in the session's sandbox (default 3000).

Inside a sandbox, MACHINE_SESSION_ID is your session; machine sessions info $MACHINE_SESSION_ID is the live view of yourself.

Triggers

Round-trip through machine.toml's [[triggers]]; the dashboard sees the same state.

CommandEffect
machine triggers lsList triggers + runtime state (last_fired_at).
machine triggers info <slug>Show one trigger in full.
machine triggers fire <slug>Manually fire a trigger now.
machine triggers enable <slug>Set enabled = true.
machine triggers disable <slug>Set enabled = false.

Change requests (cr)

Machine-native PR layer for session work landing on main — merges one branch (head_ref) into another (base_ref) on any git host, no per-host integration. The only sanctioned way for an agent to land session-branch work on main. See Change requests.

CommandEffect
machine cr ls [--status open|merged|closed|all] [--project <id>]List CRs on the project. Default: --status open.
machine cr show <cr> [--project <id>]Show one CR's metadata. Alias: machine cr info. Includes the merge-preview (clean / fast-forward / conflicts) for open CRs.
machine cr diff <cr> [--no-color] [--project <id>]Unified diff of the CR. Three-dot diff for open / closed CRs; for merged CRs it uses the SHAs captured at merge time.
machine cr open --title "<text>" [--description "<text>"] [--head <ref>] [--base <ref>] [--session <id>] [--project <id>]Open a new CR. Aliases: machine cr new, machine cr create. Inside a sandbox, --head defaults to $MACHINE_BRANCH_NAME and --session defaults to $MACHINE_SESSION_ID. --base defaults to the project's default branch (usually main). --title is required. Aliases: --from (--head), --into (--base), --body (--description).
machine cr merge <cr> [--message "<text>"] [--project <id>]Merge an open CR into its base_ref. Fast-forward when possible, three-way merge otherwise. Default message Merge CR #<n>: <title>. Fails with 409 if the CR is not open or there are conflicts.
machine cr close <cr> [--project <id>]Close an open CR without merging. Cannot close a merged CR.
machine cr reopen <cr> [--project <id>]Reopen a closed CR only — merged CRs are terminal.

<cr> accepts the short per-project number (3, #3) or the full UUID cr_id. Numbers are unique per project, monotonically increasing.

Inside a sandbox — the typical agent flow

# 1. Commit on the session branch
git add .
git commit -m "Add release-notes skill"

# 2. Push the branch (MACHINE_BRANCH_NAME)
git push origin HEAD

# 3. Open the CR — head and session are auto-detected
machine cr open \
  --title  "Add release-notes skill" \
  --description "Drafts release notes from merged commits. Tested against the last 5 tags."

# 4. Confirm it's listed
machine cr ls

# 5. (Optional) show the diff one more time
machine cr diff 3

The agent does not merge its own CR — that's the user's call, in the dashboard or via machine cr merge <n>.

Install / update / uninstall

CommandEffect
machine updateRe-runs the install script to pull the latest binary.
machine uninstallRemoves the machine binary and its /usr/local/bin shim, the ~/.machine home dir, and the stored auth token. --keep-home preserves ~/.machine; --keep-auth preserves the token.
machine versionPrint the CLI version.

Project scaffold

CommandEffect
machine initScaffold a Machine project in the current directory. Writes machine.toml, .machine/Dockerfile, and the OpenCode config dir (default agent + the machine-system skill + tools), and wires the Machine skill into any local coding agents it finds (.opencode/, .claude/, AGENTS.md, .cursor/). It does not write .machine/link.json — that's created later by projects link or ship.
machine <project-name>Same as init but scaffolds into a new directory next to cwd.

Other commands: ship (alias deploy) pushes your local commits to the project's cloud repo, provisioning a managed repo on first run — despite the alias, it's a git push, not app deployment. channels connects Slack to a project. Run machine help for the full list.

Token scope

Two token types, both with the machine_pat_… prefix, distinguished by an internal project_id column on the token row.

TypeScopeIssued byTypical use
User tokenAll projects on accounts the user belongs to + account-level routes (/v1/accounts/me, billing, etc.)machine login browser flow → minted via POST /v1/accounts/tokensThe CLI on your laptop
Project tokenRead + write everything on one project — secrets, sessions, triggers, change requests, apps. Cannot list other projects or hit account-level routes.Auto-minted at session create; surfaced via POST /v1/projects/:id/cli-tokenThe CLI inside a sandbox

Enforcement: every project route checks the token's project_id against the URL's :projectId. Mismatch → 403. Account routes (/v1/accounts/*) reject any project-scoped token outright.

Inside a sandbox

The session bootstrap injects (among other runtime vars):

MACHINE_CLI_TOKEN=          # project-scoped PAT — the CLI authenticates with this
MACHINE_TOKEN=              # sandbox service key (daemon control surface) — NOT a CLI token
MACHINE_API_URL=https://machineapi.myapps.ai
MACHINE_PROJECT_ID=<uuid>
MACHINE_SESSION_ID=<uuid>

The CLI reads MACHINE_CLI_TOKEN automatically (falling back to MACHINE_EXECUTOR_TOKEN, the same value) and uses MACHINE_API_URL as the host base. No config file needed. Don't reach for MACHINE_TOKEN — it's the daemon's service key, and the project-scoped API routes the CLI hits reject it.

Rotating

A sandbox's project token is minted at session create and lives for that sandbox. Restarting re-provisions and issues a fresh token; an existing sandbox keeps its token until it restarts.

Common workflows

Spin up a fresh session with custom env

machine secrets set OPENAI_API_KEY=sk-… ANTHROPIC_API_KEY=sk-…
machine sessions new --prompt "Audit the auth module and propose a fix"

Inside a session: trigger another session

machine sessions new --prompt "Verify migration 0048 by running pnpm test + opening a CR if anything fails"

Run a trigger by hand for debugging

machine triggers ls                      # confirm the slug + status
machine triggers fire daily-digest       # one-shot manual fire
machine sessions ls | head -3            # the new session that the trigger spawned

Pull current secrets into a local .env for development

machine env pull                         # names only, values left blank
$EDITOR .env                            # fill in values locally
# (don't push — local-only file)

Bulk-upload local .env to the cloud project

machine env push --from .env
machine secrets ls                       # confirm

Land session work on main (the CR flow)

The agent opens the CR; the user reviews and merges. No other path to main from inside a session.

# inside a session sandbox, on branch session-<id>
git add .
git commit -m "Add release-notes skill"
git push origin HEAD

machine cr open \
  --title       "Add release-notes skill" \
  --description "Drafts release notes from merged commits. Tested against the last 5 tags."

machine cr ls                            # confirm

The user then runs machine cr show 3, machine cr diff 3, and machine cr merge 3 (or machine cr close 3).

Environment variables the CLI reads

VariablePurpose
MACHINE_CLI_TOKENThe project-scoped PAT the CLI authenticates with in a sandbox (pre-injected). The primary token name the CLI reads.
MACHINE_EXECUTOR_TOKENSame value as MACHINE_CLI_TOKEN; the CLI falls back to it if the former is unset.
MACHINE_API_URLOverride the API base URL (default: https://machineapi.myapps.ai).
MACHINE_PROJECT_IDOverride the linked project for one command.
MACHINE_CONFIG_FILEOverride ~/.config/machine/config.json location (useful for tests).
MACHINE_DASHBOARD_URLOverride the dashboard URL the login flow opens (default: derived from API URL).

The MACHINE_* prefix is reserved for platform-injected values. Don't declare project secrets with it — the secrets-manager API rejects them and the manifest validator warns.

Exit codes

CodeMeaning
0Success.
1Operation failed (API error, missing project, etc.). Diagnostics printed to stderr.
2Bad flag, unknown subcommand, missing required arg.

What the CLI is not

  • Not a separate runtime. Use machine self-host start to run your own local Machine Cloud stack, then switch between Cloud and local APIs with machine hosts use.
  • Not a git replacement. machine cr composes with git rather than wrapping it.
  • Not the runtime. OpenCode executes the agent in the sandbox; the CLI is the control plane. See Machine vs OpenCode config.
CLI reference | Machine Docs | Machine OS