Skip to Content

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" --follow

The 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 install

Then, 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-space

The 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.

FlagMeaning
--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.
--insecureSkip 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, --helpShow 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.

FlagMeaning
--server <url>The Marshal server to log in to. Marshal saves it. The first time you log in, you must pass it.
--deviceSign 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.
--browserOpen a browser on this machine, even when no display is detected.
--passwordLog 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 --password

In 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.codes

With 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.

FlagMeaning
--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.

FlagMeaning
--checkOnly 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.

CommandWhat it does
marshal spaces listList your spaces.
marshal spaces newCreate 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:

CommandFlagMeaning
spaces new--manifest <id>The manifest to use.
spaces new--name <name>Space name. Marshal makes one if you omit it.
spaces new-d, --detachCreate the space, print its name, and exit without connecting.
spaces new--mountMount the shared folder (/home/agent/shared) locally. It unmounts when you disconnect.
spaces connect--mountMount the shared folder (/home/agent/shared) locally. It unmounts when you disconnect.
spaces resume--connectConnect 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, --detachCreate the space, print its name, and exit.
spaces fork--mountMount the new space’s shared folder (/home/agent/shared) locally.
spaces delete-y, --yesSkip 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.png

spaces 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.

CommandWhat 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 space

SSH 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.

CommandWhat it does
marshal ssh-config installTurn it on: create a key pair, add an Include line to ~/.ssh/config, and write the entries.
marshal ssh-config refreshRewrite ~/.marshal/ssh_config now instead of waiting for the next poll.
marshal ssh-config statusShow paths, the key fingerprint, the entry count, and the last write.
marshal ssh-config uninstallRemove the Include line, the managed file, and the Marshal key pair.

Runs

Runs are headless agent tasks.

marshal run

Start a headless run.

FlagMeaning
--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.
--followStream the transcript until the run ends. A run that parks is followed until it finishes.
--jsonPrint the run as one JSON object on stdout. Progress and the transcript go to stderr.
--verboseWith --follow, also print the agent runtime’s diagnostic lines.
--keep-on-failureIf 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" --follow

When 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.

FieldValue
idThe run’s ID.
statusThe run’s status, for example succeeded, failed, timed_out or canceled.
stop_reasonWhy the run stopped, or null.
outputThe run’s output as JSON, or null.
errorThe error text, or null.
timeout_secsThe time budget the run started with, in seconds. Time added later is not included.
urlThe run’s page in the web app.
continues_run_idThe 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

CommandWhat it does
marshal runs listList 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:

FlagMeaning
--add <duration>Add time, for example 15m or 1h. The least you can add is 1m.
--pausePause the timeout clock. The run keeps working.
--resumeResume a paused timeout.

A run can never run longer than 24 hours in total, pauses included.

marshal runs continue flags:

FlagMeaning
--message <text>What the agent should do next. Required. It plays the role --task plays for marshal run.
--followStream the new run until it ends. The exit code is non-zero unless it succeeded.
--jsonPrint the new run as one JSON object, with the same fields as marshal run --json.
--verboseWith --follow, also print the agent runtime’s diagnostic lines.
marshal runs continue <run-id> --message "Now run the tests and fix what fails" --follow

marshal 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.

CommandWhat it does
marshal deputies listList 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:

FlagMeaning
--mission <slug>The mission to launch. Required.
--input key=valueA 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.
--followStream the transcript until the run ends.
--verboseWith --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/api

When 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

CommandWhat it does
marshal manifests listList manifests. The alias for manifests is manifest.
marshal manifests get <id>Show a manifest. Accepts a name or an ID prefix.
marshal credentials listList your credentials with their display name, type, owner, and status.
marshal credentials addConnect an installed package: paste a value, or sign in. marshal credentials set does the same.
marshal connectionsList 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.
FlagMeaning
--type <package>.<method>The credential type. Marshal lists the valid types if you pass one it does not know.
--field key=valueA 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.
--yesFor a code sign-in: save without asking you to confirm who signed in.
--no-browserPrint 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 --yes

Organizations, members, invitations, and API keys

marshal org has the aliases orgs and organization.

CommandWhat it doesWho can run it
marshal org listList the organizations you belong to.Anyone
marshal org currentPrint 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 updateChange the name or slug.Owner
marshal org deleteDelete the active organization. Members lose access at once.Owner
CommandFlagMeaning
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.

CommandWhat it doesWho can run it
marshal member listList 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.

CommandWhat it doesWho can run it
marshal invite createCreate a single-use invitation link.Admin or owner
marshal invite listList active invitations.Admin or owner
marshal invite revoke <invitation-id>Revoke an invitation. An 8-character ID prefix works.Admin or owner
CommandFlagMeaning
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.

CommandWhat it doesWho can run it
marshal api-key create <name>Create an organization API key.Admin or owner
marshal api-key listList active keys.Admin or owner
marshal api-key revoke <key-id>Revoke a key. An 8-character ID prefix works.Admin or owner
CommandFlagMeaning
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 admin

For 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.

CommandWhat it does
marshal daemon installInstall the daemon as a login item that starts when you log in.
marshal daemon uninstallRemove the login item.
marshal daemon startStart the daemon in the background.
marshal daemon stopStop the daemon.
marshal daemon restartStop the daemon, wait for it to release its resources, and start it again.
marshal daemon statusShow the daemon status, tunnels, and mounts.
marshal daemon logsShow the daemon logs.
CommandFlagMeaning
daemon install--auto-startStart the daemon right after install. On by default.
daemon install--forceStop a running daemon before you install. Use this after you upgrade the binary.
daemon install--no-ssh-configSkip the SSH config writer.
daemon status-v, --verboseShow empty sections too.
daemon logs-f, --followFollow the log output.

Settings and shell completion

CommandWhat it does
marshal config viewPrint the effective configuration. The token is hidden. The alias for view is show.
marshal config setSave 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 setupAdd completions to your shell’s rc file.
CommandFlagMeaning
config set--api-url <url>The API address (http:// or https://).
config set--insecureSkip 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-restartDo not restart a running daemon after writing.
completions setup--shell <name>Choose the shell instead of detecting it.
completions setup--dry-runPrint what would happen without writing files.