CLI reference
Drive Marshal from your terminal. With marshal you open a space and work in it from your own shell, script headless agent runs, connect VS Code or Cursor to a space over SSH, and reach a dev server in a space as if it ran on your laptop. This page lists every command and flag. Run marshal <command> --help for the same information in your terminal.
Run and deputy commands are available when your administrator enables runs and deputies.
Quickstart
Install the CLI, log in, and open your first space:
curl -fsSL https://marshal.codes/downloads/install.sh | sh
marshal login --server https://<your-marshal-host>
marshal spaces new --manifest <manifest-name>The last command creates a space and drops you into its terminal. Run marshal manifests list to see the manifests you can use. For more on installing, see Install the CLI.
Recipes
Run an agent from a script
marshal run --follow streams the transcript and exits non-zero when the run ends in any status other than succeeded. A script or CI step can use the exit code as a pass or fail. When the run parks to wait for an answer, --follow keeps waiting, then streams the run that picks the work up again. The exit code is the result of that final run.
marshal run --manifest reviewer --task "Review the open changes and write a summary to output.json" --followThe run uses your saved login. It gets your org’s default time budget, or 15 minutes when the org has none. To set the budget yourself, add --timeout 30m.
To read the result in a script, add --json. The command prints one JSON object on stdout, and everything meant for a person goes to stderr:
marshal run --manifest reviewer --task "Summarize the open changes" \
--output-mode transcript --follow --json 2>/dev/null | jq '.output'Open a space in VS Code
Let VS Code Remote-SSH, Cursor or Windsurf reach your spaces:
marshal daemon install
marshal ssh-config installThen, in VS Code, choose Remote-SSH: Connect to Host and pick <space-slug>.<org-slug>.marshal. The space’s stack needs the allow-list package for your editor, such as egress-vscode.
Reach a dev server in a space
marshal ports auto-forward my-spaceThe command watches the space and forwards each new port to your machine, so http://localhost:3000 opens the app the agent started. It picks a free local port when the same port is in use. Press Ctrl+C to stop.
Global flags
These flags work on every command.
| Flag | Meaning |
|---|---|
--api-url <url> | Use this API address instead of the saved one, for this command only (marshal login and marshal register save it). Your saved login is only used with the server it was made on, so pair a different server with --token. |
--token <token> | Use this authentication token instead of the saved login, for this command only. |
--insecure | Skip TLS certificate checks for this command only, like curl -k. Use it only against a server you trust. marshal login --insecure does not keep it on for later commands; run marshal config set --insecure for that. |
-h, --help | Show help. |
The CLI saves its settings in ~/.marshal/config.json. The global flags are never written there; use marshal login or marshal config set to change what is saved. A <id> argument for a space accepts the space ID, its name, or an ID prefix. Most commands need a login first and print not logged in if you have none.
Sign in
marshal login
Log in to Marshal. On a machine with a display, this opens your browser. On a machine without one, such as an SSH session or a Linux server, it switches to device login: the CLI prints a link and a code, and you approve the sign-in from any device where you are signed in to Marshal.
| Flag | Meaning |
|---|---|
--server <url> | The Marshal server to log in to. Marshal saves it. The first time you log in, you must pass it. |
--device | Sign in by approving a code on another device. The CLI prints a link and a code and never opens a browser. The request is valid for 10 minutes. |
--browser | Open a browser on this machine, even when no display is detected. |
--password | Log in with email and password instead of the browser. |
--device, --browser and --password cannot be combined.
Plain marshal login picks device login for you when there is no display: an SSH session without a forwarded display, or a Linux machine with neither DISPLAY nor WAYLAND_DISPLAY set. It prints a one-line notice when it does. On macOS and Windows it uses the browser unless you are connected over SSH.
marshal login --server https://app.marshal.codes
marshal login --device
marshal login --browser
marshal login --passwordIn a script, --password reads the email and the password from stdin, one per line:
printf '%s\n%s\n' "$MARSHAL_EMAIL" "$MARSHAL_PASSWORD" | marshal login --password --server https://app.marshal.codesWith device login, the CLI signs in to the organization that was active on the approval page. See Sign in on a remote server.
marshal register
Create a new Marshal account. Your install decides who can register. See Signing in and access.
| Flag | Meaning |
|---|---|
--invite <link or token> | Join the organization that invited you. Paste the invite link (https://<your-marshal>/accept-invite/<token>) or just the token. |
marshal register --invite https://app.marshal.codes/accept-invite/<token>When your install accepts new accounts by invitation only, --invite is how you register from the CLI. Without it, the CLI tells you to ask an admin for an invite link.
marshal logout
Forget the saved login on this machine.
marshal version
Print the versions of the CLI, the local daemon, and the API server. It does not fail when the daemon or the server is unreachable.
marshal upgrade
Update the CLI to the latest compatible version.
| Flag | Meaning |
|---|---|
--check | Only report whether an update is available. |
Spaces
marshal spaces has the alias marshal space. The commands stop, resume, and fork also exist at the top level with the same behavior.
| Command | What it does |
|---|---|
marshal spaces list | List your spaces. |
marshal spaces new | Create a space and connect to it. |
marshal spaces connect <id> | Connect to an existing space. |
marshal spaces stop <id> | Stop a space. Also marshal stop <id>. |
marshal spaces resume <id> | Start a stopped space on fresh compute and restore the workspace. Also marshal resume <id>. |
marshal spaces fork <id> | Create a new space from a clone of an existing space’s workspace. Also marshal fork <id>. |
marshal spaces archive <id> | Archive a space: free its disk and keep a backup of the workspace. It stops first if it is running. |
marshal spaces restore <id> | Bring an archived space back to the stopped state. Resume it afterward. |
marshal spaces delete <id> | Delete a space and its workspace for good. |
marshal spaces exec <id> -- <command>... | Run a command in the space. |
marshal spaces push <id> <local-path> [remote-path] | Upload a file into the space. |
marshal spaces pull <id> <remote-path> [local-path] | Download a file from the space. |
marshal spaces mount <id> [local-path] | Mount the space’s shared folder (/home/agent/shared) as a local folder. Needs sshfs. |
Flags:
| Command | Flag | Meaning |
|---|---|---|
spaces new | --manifest <id> | The manifest to use. |
spaces new | --name <name> | Space name. Marshal makes one if you omit it. |
spaces new | -d, --detach | Create the space, print its name, and exit without connecting. |
spaces new | --mount | Mount the shared folder (/home/agent/shared) locally. It unmounts when you disconnect. |
spaces connect | --mount | Mount the shared folder (/home/agent/shared) locally. It unmounts when you disconnect. |
spaces resume | --connect | Connect once the space is ready. |
spaces fork | --manifest <id> | The manifest for the new space. |
spaces fork | --name <name> | Name of the new space. |
spaces fork | -d, --detach | Create the space, print its name, and exit. |
spaces fork | --mount | Mount the new space’s shared folder (/home/agent/shared) locally. |
spaces delete | -y, --yes | Skip the confirmation question. |
marshal spaces new --manifest claude-code
NAME=$(marshal spaces new --manifest claude-code --detach)
marshal spaces exec my-space -- git status
marshal spaces push my-space ./diagram.png /home/agent/shared/diagram.pngspaces connect, spaces new, spaces fork, spaces resume --connect and deputies engage open an interactive shell, so they run in a terminal. In a script or a CI job, create the space with --detach and work in it with marshal spaces exec. Started without a terminal, these commands stop before they change anything and print the command to use instead.
Ports
marshal ports moves network traffic between your machine and a space. Each command takes the space as its first argument.
| Command | What it does |
|---|---|
marshal ports list <space> | Show the ports that listen inside the space. |
marshal ports forward <space> [local-port:]remote-port ... | Forward space ports to your machine. The local port defaults to the remote port. |
marshal ports auto-forward <space> | Watch the space and forward new ports automatically. It picks free local ports when needed. |
marshal ports expose <space> [host:]<local-port>[:<pod-port>] ... | Make a local service reachable from inside the space. The local side comes first, then the pod port, the same order as ports forward. The host defaults to localhost and the pod port defaults to the local port. |
marshal ports forward my-space 8080:3000
marshal ports expose my-space 5432:15432 # localhost:5432 at port 15432 in the spaceSSH config
marshal ssh-config lets VS Code Remote-SSH, Cursor, Windsurf, and plain ssh reach your spaces. Each space appears as <slug>.<org-slug>.marshal. The local daemon owns the file.
| Command | What it does |
|---|---|
marshal ssh-config install | Turn it on: create a key pair, add an Include line to ~/.ssh/config, and write the entries. |
marshal ssh-config refresh | Rewrite ~/.marshal/ssh_config now instead of waiting for the next poll. |
marshal ssh-config status | Show paths, the key fingerprint, the entry count, and the last write. |
marshal ssh-config uninstall | Remove the Include line, the managed file, and the Marshal key pair. |
Runs
Runs are headless agent tasks.
marshal run
Start a headless run.
| Flag | Meaning |
|---|---|
--manifest <id or name> | The manifest to run in. Required. |
--task <text> | The task or prompt for the run. Required. |
--runtime <name> | The agent runtime. The default is claude-code. |
--timeout <duration> | The hard time limit, for example 30m. Without it, the run gets your org’s default time budget, or 15m when the org has none. |
--compute-class <size> | The compute size, by name (such as medium) or ID. Optional. |
--title <text> | A short name shown in the Runs list. Marshal derives one from the task if you omit it. |
--output-mode <mode> | Where the run’s output comes from: file (the agent writes /workspace/output.json) or transcript (the agent’s final message). The default is file. |
--permission-mode <mode> | How the run answers the agent’s permission requests: auto approves every request, deny refuses every request and needs --driver-mode acp. The default is auto. |
--driver-mode <mode> | How the agent is driven: acp, print or exec. The default is the runtime’s preferred mode. |
--follow | Stream the transcript until the run ends. A run that parks is followed until it finishes. |
--json | Print the run as one JSON object on stdout. Progress and the transcript go to stderr. |
--verbose | With --follow, also print the agent runtime’s diagnostic lines. |
--keep-on-failure | If the run fails, leave the space up for 24 hours so you can attach to it. |
marshal run --manifest my-stack --task "review the repo" --followWhen the run starts, the command prints the run’s time budget, for example timeout 2h. If the budget ends the run, the command says so and names the two ways to give a run more time: --timeout for the next run, and marshal runs timeout --add for a live one.
JSON output
With --json, marshal run, marshal runs continue and marshal runs get print one JSON object on stdout and nothing else. Without --follow, it describes the run as created. With --follow, it describes the final run, which is the last run of a chain when the work parked and resumed. The exit code does not change: it is non-zero unless the run succeeded.
| Field | Value |
|---|---|
id | The run’s ID. |
status | The run’s status, for example succeeded, failed, timed_out or canceled. |
stop_reason | Why the run stopped, or null. |
output | The run’s output as JSON, or null. |
error | The error text, or null. |
timeout_secs | The time budget the run started with, in seconds. Time added later is not included. |
url | The run’s page in the web app. |
continues_run_id | The ID of the run this one continues, or null. |
Every field is always present, with null when there is no value. If the run cannot be started, nothing is printed on stdout, the error goes to stderr, and the exit code is non-zero.
marshal runs
| Command | What it does |
|---|---|
marshal runs list | List runs, with their titles, and launches that are waiting to start. Add --json for one JSON array. |
marshal runs get <run-id> | Show a run’s status and result. Add --json for one JSON object. |
marshal runs continue <run-id> | Continue a finished run with a follow-up --message. |
marshal runs logs <run-id> | Stream a run’s transcript until it ends, through any park and resume. Add --verbose to see the agent runtime’s diagnostic lines. |
marshal runs cancel <run-id or queued-launch-id> | Cancel a run, or a launch that is still waiting. An id that starts with ql_ is a waiting launch. |
marshal runs timeout <run-id> | Change a live run’s timeout. |
marshal runs timeout flags:
| Flag | Meaning |
|---|---|
--add <duration> | Add time, for example 15m or 1h. The least you can add is 1m. |
--pause | Pause the timeout clock. The run keeps working. |
--resume | Resume a paused timeout. |
A run can never run longer than 24 hours in total, pauses included.
marshal runs continue flags:
| Flag | Meaning |
|---|---|
--message <text> | What the agent should do next. Required. It plays the role --task plays for marshal run. |
--follow | Stream the new run until it ends. The exit code is non-zero unless it succeeded. |
--json | Print the new run as one JSON object, with the same fields as marshal run --json. |
--verbose | With --follow, also print the agent runtime’s diagnostic lines. |
marshal runs continue <run-id> --message "Now run the tests and fix what fails" --followmarshal runs list --json prints one array with an element for each row of the text list. A run has the fields above. A launch that is waiting to start has an id that starts with ql_, its queue state as status, and the fields kind, deputy and reason. Its run-only fields are null.
Deputies
marshal deputies has the alias marshal deputy.
| Command | What it does |
|---|---|
marshal deputies list | List the deputies you can see. |
marshal deputies missions <deputy-slug> | List a deputy’s missions. The first column is the mission slug. |
marshal deputies launch <deputy-slug> | Launch one of the deputy’s missions. |
marshal deputies message <run-id> <text> | Send a note to a run that is still in progress. The message is queued for the agent’s next turn: it reads the note when the turn it is working on ends. Add --interrupt to stop the current turn so the agent reads it now. Marshal refuses it if the run already finished. |
marshal deputies engage <engagement-id> | Take over a deputy’s pod to answer a question in person. |
marshal deputies launch flags:
| Flag | Meaning |
|---|---|
--mission <slug> | The mission to launch. Required. |
--input key=value | A template input. Repeat the flag for each input. |
--notes <text> | Extra instructions for this launch only. Marshal adds them to the mission prompt. They change no mission and are not remembered. |
--follow | Stream the transcript until the run ends. |
--verbose | With --follow, also print the agent runtime’s diagnostic lines. |
The run uses the deputy’s identity, environment, and manifest, not yours. This is different from marshal run, which starts a run with no deputy.
marshal deputies launch pr-sweeper --mission nightly-triage --input repo=acme/apiWhen the mission is already running as many times as its limit allows, the launch waits in a queue. The CLI prints the launch ID (it starts with ql_) and its place in the queue. Cancel it with marshal runs cancel ql_<id>. With --follow, the CLI waits for the launch to start and then streams its run.
Manifests, credentials, and connections
| Command | What it does |
|---|---|
marshal manifests list | List manifests. The alias for manifests is manifest. |
marshal manifests get <id> | Show a manifest. Accepts a name or an ID prefix. |
marshal credentials list | List your credentials with their display name, type, owner, and status. |
marshal credentials add | Connect an installed package: paste a value, or sign in. marshal credentials set does the same. |
marshal connections | List the connections you can use and the state of each: connected, needs reconnect, or disconnected. |
Add a credential
marshal credentials add follows the same rules as the Connect dialog on the Connections page. Every credential has a type of the form <package>.<method>, for example github.pat or aws.sso. Run the command with no flags and Marshal lists the installed packages and their methods for you to pick from. Then it asks for exactly what that method needs:
- A pasted value, such as a token or a connection string. Marshal asks for each field of the method and hides secret ones as you type.
- A browser sign-in (OAuth), such as
github.oauth. Marshal opens the provider’s approval page in your browser and finishes as soon as you approve. - A sign-in with a code, such as
aws.sso. Marshal shows a short code and opens the sign-in page. After you approve, you pick the account and the role, check who signed in, and save.
| Flag | Meaning |
|---|---|
--type <package>.<method> | The credential type. Marshal lists the valid types if you pass one it does not know. |
--field key=value | A value for one field of the method. Repeat the flag for each field. |
--file <path> | Read the value from a file, for example ~/.kube/config. Use - to read standard input. For a method with several fields, the file holds a JSON object of the fields. |
--name <text> | The display name. It tells several credentials of one package apart. Marshal suggests one when you leave it out. |
--owner <owner> | Who owns the credential: me (the default), team:<name> for a team you lead, or org if you are an admin or owner of the organization. A sign-in acts as you, so a browser sign-in is always yours, and a code sign-in belongs to you or a team. |
--account <id> | For a code sign-in: the account to use, by ID or name. |
--role <name> | For a code sign-in: the role to use. |
--yes | For a code sign-in: save without asking you to confirm who signed in. |
--no-browser | Print the sign-in link instead of opening a browser. |
With --type, Marshal skips the pickers and asks only for the method’s values. Pass those as flags too and the command runs with no prompts, so it works in scripts:
marshal credentials add --type github.pat --name "GitHub work" # asks for the token
marshal credentials add --type k8s.kubeconfig --file ~/.kube/config --owner team:platform
marshal credentials add --type aws.sso \
--field start_url=https://acme.awsapps.com/start --field region=us-east-1 \
--account 123456789012 --role ReadOnly --yesOrganizations, members, invitations, and API keys
marshal org has the aliases orgs and organization.
| Command | What it does | Who can run it |
|---|---|---|
marshal org list | List the organizations you belong to. | Anyone |
marshal org current | Print the active organization’s slug. | Anyone |
marshal org show [slug] | Show the active organization, or the one you name. | Anyone |
marshal org switch <slug> | Switch the active organization. | Anyone |
marshal org create <name> | Create an organization. You become its owner. | Anyone (see below) |
marshal org update | Change the name or slug. | Owner |
marshal org delete | Delete the active organization. Members lose access at once. | Owner |
| Command | Flag | Meaning |
|---|---|---|
org create | --slug <slug> | Set the slug. Marshal derives one from the name if you omit it. |
org update | --name <name> | New display name. |
org update | --slug <slug> | New slug. |
org delete | --confirm <slug> | Type the organization slug to confirm. |
Once your install has its first organization, creating more is off unless your operator turns it on (auth.disableOrgCreation: false, see Configuration). While it is off, marshal org create returns org_creation_disabled.
marshal member has the alias members.
| Command | What it does | Who can run it |
|---|---|---|
marshal member list | List members. | Anyone |
marshal member role <email-or-user-id> <role> | Change a member’s role. | Owner |
To remove a member, use Organization settings > Members in the web app, where you also pick new owners for what they share. See Remove a member or leave an organization.
marshal invite has the aliases invites, invitation, and invitations.
| Command | What it does | Who can run it |
|---|---|---|
marshal invite create | Create a single-use invitation link. | Admin or owner |
marshal invite list | List active invitations. | Admin or owner |
marshal invite revoke <invitation-id> | Revoke an invitation. An 8-character ID prefix works. | Admin or owner |
| Command | Flag | Meaning |
|---|---|---|
invite create | --role <role> | The role to grant, admin or member. The default is member. |
invite create | --email <address> | Optional. If email is set up for the organization, Marshal sends the invitation there. |
marshal api-key has the aliases api-keys and apikey.
| Command | What it does | Who can run it |
|---|---|---|
marshal api-key create <name> | Create an organization API key. | Admin or owner |
marshal api-key list | List active keys. | Admin or owner |
marshal api-key revoke <key-id> | Revoke a key. An 8-character ID prefix works. | Admin or owner |
| Command | Flag | Meaning |
|---|---|---|
api-key create | --role <role> | The role in the key, admin or member. The default is member. |
api-key create | --mcp-scopes <list> | The MCP permissions the key holds, separated by commas: read, launch, answer, manage, admin. The default is read,launch,answer. admin needs --role=admin. |
marshal invite create --role=member --email=alice@example.com
marshal api-key create ci-deploy --role=member
marshal api-key create agent --role=admin --mcp-scopes read,launch,answer,manage
marshal member role alice@example.com adminFor what each role can do, see Roles and permissions.
Local daemon
The daemon runs on your machine. It runs the port forwards and mounts you open from the Ports and Mounts tabs of a space in the web app, and it manages the SSH config. The CLI’s own marshal ports forward and --mount run inside the CLI and need no daemon.
| Command | What it does |
|---|---|
marshal daemon install | Install the daemon as a login item that starts when you log in. |
marshal daemon uninstall | Remove the login item. |
marshal daemon start | Start the daemon in the background. |
marshal daemon stop | Stop the daemon. |
marshal daemon restart | Stop the daemon, wait for it to release its resources, and start it again. |
marshal daemon status | Show the daemon status, tunnels, and mounts. |
marshal daemon logs | Show the daemon logs. |
| Command | Flag | Meaning |
|---|---|---|
daemon install | --auto-start | Start the daemon right after install. On by default. |
daemon install | --force | Stop a running daemon before you install. Use this after you upgrade the binary. |
daemon install | --no-ssh-config | Skip the SSH config writer. |
daemon status | -v, --verbose | Show empty sections too. |
daemon logs | -f, --follow | Follow the log output. |
Settings and shell completion
| Command | What it does |
|---|---|
marshal config view | Print the effective configuration. The token is hidden. The alias for view is show. |
marshal config set | Save settings to ~/.marshal/config.json and restart the daemon. |
marshal completions generate [shell] | Print a completion script for zsh, bash, fish, or powershell. Marshal detects the shell from $SHELL if you omit it. |
marshal completions setup | Add completions to your shell’s rc file. |
| Command | Flag | Meaning |
|---|---|---|
config set | --api-url <url> | The API address (http:// or https://). |
config set | --insecure | Skip TLS certificate checks for every future request, like curl -k. Use --insecure=false to turn it off. |
config set | --gateway-url <url> | The gateway WebSocket address (ws:// or wss://). |
config set | --web-origins <list> | Extra browser origins the daemon allows, separated by commas. An empty string clears the list. |
config set | --no-restart | Do not restart a running daemon after writing. |
completions setup | --shell <name> | Choose the shell instead of detecting it. |
completions setup | --dry-run | Print what would happen without writing files. |