Skip to content

Agent SDK CLI ​

The Agent SDK is published as @grok/agent-sdk with the agent-sdk CLI.

text
agent-sdk <command>

The command catalog below documents the agent-sdk binary from @grok/agent-sdk. Run it with Node 22.13 or newer; Bun is not supported. Commands exit nonzero when validation or a synchronous request fails; asynchronous commands can exit 0 once work is accepted. Project paths use the Agent SDK project layout.

Install @grok/agent-sdk to obtain the binary. Bare agent-sdk prints the command index. agent-sdk <command> --help prints one command's help, agent-sdk help --all prints every command, and agent-sdk help <command> --json prints one command's arguments and flags as JSON.

The bdk command remains available.

Commands are named agent-sdk <resource> <verb>, such as agent-sdk deployment list, except for a few workflow verbs (init, dev, run, eval, deploy, and others). Older names, such as agent-sdk deployments or agent-sdk secrets set, still run for now. Each one prints the new form on stderr.

Command catalog ​

Development commands ​

CommandContract
help, --help, -hPrint the command index, or one command's help
serveServe one or more agents over HTTP
devServe agents with local-development behavior
docsServe the documentation bundled with @grok/agent-sdk
initScaffold an Agent SDK project, or convert an Automation
migrateMove an early-alpha project to architecture v2 through a pull request
skills listList the bundled coding-agent skills and their installed versions
skills installRefresh the bundled coding-agent skills
infoPrint the discovered project surface or its deployment manifest
validateCheck project diagnostics and set the exit status
versionPrint the installed package version
updateUpgrade the installed CLI
loginSign the host in to Cursor
logoutRemove the stored Cursor credential
whoamiShow the active Cursor credential

Session and eval commands ​

CommandContract
chatTalk to a running agent, or reattach a session
runRun turns on a local or running agent
tool callCall a server tool without a model turn
logsFollow or dump agent logs
session listList sessions, or their costs
session getInspect a session or a saved trace, or open it in the playground
session createStart or continue a hosted session
evalRun evals, or list, get, and cancel remote eval batches

Managed hosting commands ​

CommandContract
deployDeploy one or more agents
deployment listList deployments
deployment getInspect one deployment
deployment stopStop a deployment
deployment startStart a stopped deployment
deployment killStop a deployment, cancel its runs, and lock deploys
deployment unlockLet a killed deployment deploy again
deployment cancel-runsCancel active runs and reminder wakes
deployment updateReplace a deployment's event repositories
deployment upgradeMove a deployment to a release
deployment rollbackMove a deployment to an earlier release
deployment deleteDelete a deployment
deployment rotate-tokenReplace a deployment's alias token
secretSet, list, or delete deployment secrets
imagePush, list, or delete container images for persistent agents

Connection and channel commands ​

CommandContract
mcp serveProxy an agent's MCP endpoint over stdio
mcp installAdd the agent to an MCP client config
mcp oauthAuthorize an MCP connection
slackProvision and check Slack channel apps
githubForward, replay, and inspect GitHub webhooks
gitlabReplay and inspect GitLab webhooks
bitbucketReplay and inspect Bitbucket webhooks
pagerdutyReplay and inspect PagerDuty webhooks

Targets ​

Commands that send requests support these targets:

TargetSelectionCommands
Ephemeral local serverOmit --url and --prodrun, tool call, eval
Running serverPass --url <baseUrl>chat, run, tool call, eval, logs, session list, session get, mcp serve
Default local serverOmit --url and --prod; uses http://127.0.0.1:3000chat, logs, session list, session get
Hosted deploymentPass --prodsession list, session get, logs; session create is always hosted

An explicit --url must include the slug for a multi-agent server, such as http://127.0.0.1:3000/pr-approver. --slug never changes an explicit URL. --url and --prod are mutually exclusive.

OptionContract
--dir <path>Select the project root. The default is the current directory.
--url <baseUrl>Use a running agent instead of local project discovery.
--prodUse the hosted deployment. session list, session get, and logs accept it; chat, run, tool call, mcp serve, and eval exit with a usage error.
--slug <slug>Select an agent from a multi-agent project or a hosted deployment. Under --prod, the default is the --dir basename.
--team <id>Select a Cursor team. The signed-in account's team is the default.
--api-key <key>Override the Cursor credential for commands that authenticate with Cursor.
--bearer-token <token>Authenticate to a running server with a bearer token.
--state-root <path>Select local state for serve and ephemeral run, tool call, and eval targets. Running and --prod targets ignore it.
--jsonPrint one JSON document on stdout, errors included ({"error":{"code","message","hint"}}). Without it, output is text, also when piped. agent-sdk help lists the exit codes.

Local servers ​

Serve agents ​

serve mounts every project discovered under --dir:

text
agent-sdk serve [--dir <path>] [--port <n>] [--host <host>]
  [--mode multi|single] [--dev] [--api-key <key>]
  [--state-root <path>]
  [--bearer-token <secret> | --allow-anonymous]
  [--allow-anonymous-cursor-github]
  [--allow-anonymous-cursor-account-mcp]
  [--public-url <url>]
  [--peers-url <url>]
  [--no-schedules] [--no-playground] [--no-docs]
  [--cursor-events --repo <owner/name>]...
OptionContract
--port <n>Listen on this port. The default is 3000; 0 selects an available port. When an omitted default is occupied, the CLI selects the next port. An occupied explicit port fails with a next-port hint.
--host <host>Bind this host. The default is loopback-only 127.0.0.1.
--mode multiMount projects at /<slug>/v1/* and /<slug>/playground, with an index at /. This is the default.
--mode singleMount one project at /v1/* and /playground. Declared peers are omitted with a warning unless --peers-url is set.
--devDisable automatic schedule and reminder firing, admit unsigned loopback GitHub deliveries, and enable local playground access.
--state-root <path>Store local sessions, streams, workspaces, and channel state here. Keep durable state outside a repository whose rules shouldn't reach agent workspaces.
--bearer-token <secret>Require this token on routes without authored authentication. Mutually exclusive with --allow-anonymous.
--allow-anonymousAdmit callers as one anonymous principal. Use it only behind a trusted network boundary.
--allow-anonymous-cursor-githubLet anonymous callers use sessions with a Cursor account's repository-scoped GitHub credential. Requires an authenticating proxy.
--allow-anonymous-cursor-account-mcpLet anonymous callers use Cursor account MCP connections. Requires an authenticating proxy.
--public-url <url>Set the externally reachable base URL that turns running off the serve host use for peer MCP and host bridges. It does not expose the server; configure the listener or proxy separately. Local-runtime peers use loopback.
--peers-url <url>Resolve declared peers for a single-agent serve through a hosting-provided peer service. Cursor-managed hosting sets this option automatically; a multi-agent serve rejects it.
--no-schedulesDisable schedule firing outside dev mode.
--no-playgroundSkip the playground.
--no-docsSkip the documentation site at /docs.
--cursor-eventsReceive SCM events through Cursor. Requires sign-in and one or more repeatable --repo owner/name values.

Multi-agent slugs start with a letter or digit and contain only letters, digits, _, or -. The reserved slugs are v1, playground, and docs.

Develop locally ​

dev is serve --dev with an optional positional project path:

text
agent-sdk dev
agent-sdk dev ./agent-sdk-pr-reviewer --port 3000

It accepts every serve option. Pass at most one positional path, and don't combine it with a different --dir.

Serve the docs ​

text
agent-sdk docs [--port <n>] [--host 127.0.0.1] [--print]

docs serves the bundled documentation without an agent project. It uses an available loopback port by default and stays open until Ctrl-C. --print prints the URL without opening a browser.

Sessions and turns ​

Chat with an agent ​

chat connects to a running server and never starts an ephemeral one:

text
agent-sdk chat [--url <baseUrl>] [--message <text>]
  [--session <id> | --resume] [--continuation-token <token>]
  [--slug <slug>] [--json] [--text] [--no-color]
Input modeBehavior
TTY without --messageOpen an interactive REPL.
TTY with --messageSend the message, then keep the REPL open.
Non-TTY with --messageSend one turn and exit.
Non-TTY without --messageRead newline-delimited messages until EOF.
--json --message <text>Send one turn and print { ok, sessionId, continuationToken, trajectory }.
--json --text --message <text>Print a compact trajectory instead of JSON.

Use --session <id> to reattach a stored session and replay its transcript. If you omit --continuation-token, the CLI looks it up from the target's session list. --resume selects the most recently updated session with a continuation token. An explicit session ID takes precedence.

Run turns ​

run sends messages to an ephemeral local server or a running server:

text
agent-sdk run [--dir <path>] [--message <text>]...
  [--messages-file <path>] [--url <baseUrl>]
  [--session <id>] [--continuation-token <token>]
  [--trace <file> | --no-trace] [--json]
  [--timeout-ms <n>] [--no-stream] [--slug <slug>] [--dry-run]
OptionContract
--message <text>Send a user message. Repeat it for a multi-turn run.
--messages-file <path>Read a JSON array of strings. File messages run before repeated --message values.
--session <id>Continue a session on the target.
--continuation-token <token>Continue the session selected by --session on a running server.
--trace <file>Write the raw NDJSON stream to this path.
--no-traceSkip the NDJSON trace.
--jsonPrint the JSON result instead of the compact trajectory.
--timeout-ms <n>Stop waiting after a positive number of milliseconds. There is no default timeout.
--no-streamHide live tool and reply progress on stderr.
--dry-runSend nothing. Print the request the run would send. A local run starts no server.

Text output is the compact trajectory, with the session ID and trace path on stderr. --json output contains ok, sessionId, continuationToken, trace, playgroundUrl, visualize, and trajectory. The trace value gives the saved path when trace output is enabled.

For the hosted deployment, use session create.

Call a tool ​

tool call invokes a server tool without a model turn:

text
agent-sdk tool call <tool> [--input <json>]
  [--dir <path> | --url <baseUrl>]
  [--session <id>] [--slug <slug>] [--json]

--input accepts JSON and defaults to {}. --session uses the session workspace and records the call on its event stream. The command prints the tool result (a string as is, anything else as JSON). --json prints the server's full JSON response. The command succeeds only when the HTTP response succeeds with ok: true.

Hosted deployments don't support tool call. Start a model turn with session create and check it with session get.

See Tools for validation, busy-session behavior, and error codes.

List sessions ​

text
agent-sdk session list [--url <baseUrl> | --prod] [--since <duration|instant>]
  [--view sessions|cost] [--slug <slug>] [--team <id>]
  [--bearer-token <token>] [--limit <n>] [--page-token <token>] [--json]

Text output shows the session ID, channel, mode, turn count, running status, and update time. --json prints { items, nextPageToken }, including continuation tokens. --limit (default 20, at most 100) sets the page size, and --page-token reads the next page.

With --prod, session list lists the hosted deployment's most recently active sessions; --since 24h (or an ISO-8601 date or instant) reads back to that cutoff, up to --limit sessions. Check one with session get <sessionId> --prod.

--view cost prints token usage per session and a total from a running server. Turns saved before cost tracking appear as unpriced. --json prints { sessions }. --prod doesn't support this view.

Inspect a session ​

text
agent-sdk session get <sessionId> [--url <baseUrl> | --prod]
  [--slug <slug>] [--team <id>]
  [--view trajectory|events|cost] [--json [--fields <a,b.c>]]
  [--trace <file.ndjson>] [--web [--print]]

agent-sdk session get --file <file.ndjson> [--json]
OptionContract
No optionPrint a compact trajectory.
--jsonPrint the trajectory object.
--view eventsPrint { sessionId, events } with the raw event list. With --prod, each tool call is an actions.requested or action.result event. The tool name is toolName.
--view costPrint per-turn token usage and estimated cost from a running server. --prod doesn't support it.
--trace <file.ndjson>Write the raw NDJSON trace instead of printing it. Not available with --prod.
--file <file.ndjson>Read a saved trace (for example from run --trace) instead of a server, and print its trajectory.
--webOpen the session in the playground, or the Deployed Agents playground with --prod. --print prints the URL only. A running target with credentials that a browser can't send starts a loopback proxy and stays open until Ctrl-C.

Use chat --session to continue a conversational session on a local or running server.

With --prod, the command prints the session's hosted executions: one line per run with its status, duration, and time, followed by that run's log lines. When the deployment stored process output, a Process output: section prints that output next. --json prints { sessionId, executions, startLog, ... }. startLog is the process output, or null when none is stored. --view events prints { sessionId, events }. --trace isn't available. While a turn is running, text output also reports the event count and latest event type and prints Turn running; runs may lag behind events. A run can show running with no logs until the turn ends, so a growing event count is the progress signal.

Start a hosted session ​

text
agent-sdk session create --message <text> [--session <ses_...>]
  [--slug <slug>] [--team <id>] [--wait [--timeout-ms <n>]]
  [--read-only] [--as-of <instant>] [--component <key>] [--dry-run] [--json]
OptionContract
--message <text>The message to send. Exactly one.
--session <ses_...>Continue a hosted session that session create started. Slack, SCM, and custom-route sessions can't be continued this way.
--waitPoll the delivery until it names the session, then print it. Exit 3 (pending) when --timeout-ms (default 120000) passes first. A skipped or failed delivery exits 1.
--read-onlyRun read tools and stub write tools.
--as-of <instant>Freeze the session's clock at an ISO-8601 instant with a timezone, such as 2026-08-31T12:00:00Z.
--component <key>Wake a named component instead of the deployment's default. A continued session must belong to that component.
--dry-runSend nothing. Print the request it would send.

Without --wait, the command returns as soon as the deployment accepts the turn and exits 0 before the turn outcome is known. It prints the delivery ID, the session ID when known, and the session mode. --json prints deliveryId, workflowId, sessionMode, and sessionId when known, plus dryRun and asOf when set. A fresh start has no sessionId until the turn starts; a continuation echoes the --session value. See Verify a hosted turn.

Follow logs ​

text
agent-sdk logs [sessionId] [--url <baseUrl> | --prod]
  [--session <sessionId>] [--slug <slug>] [--team <id>] [--once] [--json]

The command follows logs until Ctrl-C. --once prints the current buffer and exits; --json emits newline-delimited JSON events. With --prod, it follows the output of the hosted deployment's most recent sessions on every channel and prints a ==> <sessionId> (<channel>) <== header each time the output switches sessions. A persistent deployment also prints a ==> process-output <== block. That block is the process log that Deployed Agents shows for the deployment. Pass a session ID, as an argument or with --session, to follow only that session; a session ID requires --prod. The session view starts with Process output: for the deployment process log and Session process output: for that session's own process output, and a tool <name> line for each tool call. Hosted log events carry sessionId and line rather than index and at.

Evals ​

Run evals ​

eval discovers evals/**/*.eval.{ts,js} and runs selected cases:

text
agent-sdk eval [--dir <path>] [evalId...]
  [--list] [--tag <tag>]... [--json] [--verbose]
  [--timeout-ms <n>] [--strict] [--max-concurrency <n>]
  [--junit <path>] [--artifacts <dir> | --no-artifacts]
  [--skip-report] [--out <file.json>] [--no-stream]
  [--url <baseUrl>] [--no-wait] [--slug <slug>]

Select an exact case such as weather/nyc, a file prefix such as weather, several IDs, or no IDs for every case. Repeat --tag for OR matching. To run an eval whose ID is a subcommand word (list, get, cancel), put it after --, as in agent-sdk eval -- list. Projects must provide evals/evals.config.{ts,js} with maxConcurrency between 1 and 200.

OptionContract
--listList matching cases without running them. --list --json prints an array.
--tag <tag>Select a tag. Repeat the option for OR matching.
--jsonPrint { ok, passed, failed, scored, skipped, strict, results }.
--verboseStream t.log lines and reply snippets.
--no-streamHide live progress on stderr.
--strictTreat a scored case below its soft threshold as a failure.
--max-concurrency <n>Override maxConcurrency from the eval config for an ephemeral local run.
--timeout-ms <n>Override the per-case timeout. A case timeout takes precedence, followed by this option, the config timeout, and the 180-second default.
--junit <path>Write JUnit XML for an ephemeral local run.
--artifacts <dir>Select the artifact directory for an ephemeral local run. The default is a timestamped directory under the project's state directory.
--no-artifactsSkip artifacts for an ephemeral local run.
--skip-reportIgnore reporters from eval files and the eval config during an ephemeral local run.
--out <file.json>Also write the full result JSON.
--no-waitReturn after a running server accepts the batch.

A running server prints its Eval ID when it accepts the batch. Use these commands to inspect or cancel it:

text
agent-sdk eval list --url <baseUrl> [--limit <n>] [--page-token <token>]
agent-sdk eval get <evalId> --url <baseUrl> [--out <file.json>]
agent-sdk eval cancel <evalId> --url <baseUrl>

eval list lists recent remote runs. eval get exits 3 (pending) while the batch still runs. All three require --url.

Projects ​

Scaffold a project ​

text
agent-sdk init [directory] [--template <name>] [--var id=value]... [--json] [--dry-run]
agent-sdk init [directory] --from automation:<url-or-uuid> [--dry-run] [--json]

Without a directory, init prints the setup guide and changes no files. With a directory, it preserves existing scaffold files, adds missing files, installs dependencies, and tries to put agent-sdk on PATH.

OptionContract
--template <name>Use a bundled template: agentic-owners, agents-md, code-wiki, demo, security-help, security-reviewer, thermo-quality-review, thermo-review, triage-jira, or triage-linear. triage selects triage-linear.
--var id=valueAnswer a template question without a prompt. Repeat for multiple answers.
--jsonSkip interactive login and skill prompts, then print { ok, directory, template, created, skipped, installed, installError, cliOnPath, cliLinkError, next }. ok reflects dependency installation.
--dry-runList the files init would create. Write and install nothing.

On a TTY, templates with questions run their interview before writing files. init also offers to refresh the bundled coding-agent skills and starts login when the host has no Cursor credential.

--from grokbot:<recipe.json> and --from-grokbot <recipe.json> exit with Grok Bot import was removed.

Convert an Automation ​

text
agent-sdk init [directory] --from automation:<url-or-uuid> [--dry-run] [--json]

The input can be a Cursor Automation dashboard URL or its UUID. The output directory defaults to ./<automation-name>; a positional directory overrides it. Generated files don't overwrite existing paths, and missing scaffold files are added. The following npm install can update lockfiles and run lifecycle scripts from an existing package.json.

--json prints { ok, directory, files, warnings, setupSteps, installed, installError, mcpConnections }. Conversion warnings and dependency-install failures remain visible in this output without failing a completed file conversion. Invalid input, authentication, export, and file-write failures exit nonzero.

See Convert a Cursor Automation for the generated project and features that need manual review.

Migrate an early-alpha project ​

text
agent-sdk migrate [--dir <path>] [--repo <https-url>] [--ref <git-ref>]
  [--path <agent-path>] [--no-wait] [--json] [--api-key <key>]

migrate applies only to projects deployed on architecture v1 during the Agent SDK early alpha. It reads a pushed Git ref, starts a Cursor cloud agent with the bundled bdk-migrate-v2 skill, and opens a pull request with the source changes. The command waits for the pull request by default and never deploys the project or changes deployment secrets. When it starts an agent, it prints a checklist for the steps after the first deploy: deploy each agent folder, create the prod Slack app, unset peer URL secrets, and set secrets a new slug still needs.

The command prints Nothing to migrate. and exits 0 only when --dir shows no migration work. That check looks for a legacy early-alpha package dependency, architecture: "v1", bot/storage.ts or agent/storage.ts, runtime: "grokbot", a literal SCM credential, a /v1 continuation selector, an anonymous reminder, and a *_MCP_URL peer connection. When any of those is present, or a project file cannot be read, the command starts the agent. It does not read the hosted deployment.

OptionContract
--dir <path>Select the local Agent SDK project. The default is the current directory.
--repo <https-url>Select the source repository. The CLI infers the current checkout's origin when possible.
--ref <git-ref>Select the pushed ref for the cloud agent. The CLI infers the current branch when possible.
--path <agent-path>Select the project path relative to the repository root. The CLI infers it from --dir when possible.
--no-waitPrint the cloud agent URL and return after the agent starts.
--jsonPrint a report with ok, status, agentId, and the cloud agent url. A completed migration adds prUrl and checklist. A run with nothing to migrate uses status: "current" and message (no agent started) or summary (the agent reported it). A blocked or failed migration adds its explanation.
--api-key <key>Override the Cursor credential.

Credential resolution follows the normal order: --api-key, CURSOR_API_KEY, CURSOR_API_KEY_FILE, CURSOR_SERVICE_ACCOUNT_KEY, then the stored agent-sdk login credential. See Migrate an early-alpha project for detection, pull request review, and deployment cutover.

Install and list coding-agent skills ​

text
agent-sdk skills install [--dry-run] [--json]

The command replaces the installed Agent SDK skills with the package copy and removes stale bundled skills. --dry-run previews the change. --json prints { ok, dryRun, directory, firstInstall, skills, removed }.

Package installation performs this copy. Run agent-sdk skills install when you need to refresh it.

Each installed SKILL.md records the package release in metadata.version.

text
agent-sdk skills list [--json [--fields <a,b.c>]] [--limit <n>] [--page-token <token>]

skills list prints each bundled skill and the version of its installed copy. --json prints { items, nextPageToken }. Each item has name, description, version, installedVersion, and path. installedVersion is null when the skill is not installed, and "unknown" when the installed copy has no metadata.version. When installedVersion differs from version, run agent-sdk skills install.

The bdk-cli skill holds the rules for agents that run agent-sdk: --json, exit codes, --fields, --dry-run, --yes, secrets, and untrusted output.

Inspect a project ​

text
agent-sdk info [--dir <path>] [--view info|manifest] [--json [--fields <a,b.c>]]

Text output lists the model, instructions, tools, skills, extensions, connections, subagents, channels, schedules, hooks, hosting settings, and diagnostics. For one unslugged project, --json prints its project info object. For slugged or multi-agent discovery, it prints { agents }.

--view manifest validates one project and prints a summary of its deployment metadata without a network request. --json then prints the full manifest JSON.

Validate a project ​

text
agent-sdk validate [--dir <path>]

validate prints every discovered project's diagnostics and exits nonzero when any diagnostic has error severity. Use it instead of info --json when a script needs validation status.

Hosting checks run here too. On architecture v2 (the default), a githubChannel credential or a GitLab or Bitbucket webhookSecret written as a literal or a () => process.env.NAME getter is an error whose message quotes the { secretName: "NAME" } form to use instead. A project that still sets architecture: "v1" gets the same finding as a warning, so run validate before removing the pin to list what the migration must rename.

Credentials and versions ​

Manage credentials ​

text
agent-sdk login [--api-key <key>] [--key-name <name>]
agent-sdk whoami [--json]
agent-sdk logout
CommandContract
loginUse a supplied API key, or open browser sign-in and store the resulting dashboard-revocable key in the CLI config directory. --key-name labels a browser-created key.
whoamiShow the active credential and its source. --json returns the same identity as JSON.
logoutRemove the stored credential file. It doesn't revoke the API key; revoke the key in the Cursor dashboard.

Print the version ​

text
agent-sdk version [--json]
agent-sdk --version
agent-sdk -V

Text output is the version number. --json prints { name, version }.

Update the CLI ​

text
agent-sdk update

update checks npm's latest tag and upgrades a recognized global or project install with its package manager. If it can't identify an installed copy, it prints a manual upgrade command instead.

Published installs check for updates at most once every 24 hours. Set AGENT_SERVE_NO_UPDATE_CHECK, NO_UPDATE_NOTIFIER, or CI to disable the automatic warning.

Managed hosting ​

Every command here that changes a deployment takes --dry-run. It runs the reads (sign-in, team, and deployment checks), then stops at the first request that would change state and prints that request, with secret values redacted. Nothing is sent, and the command exits 0.

deployment kill, deployment cancel-runs, deployment delete, deployment rotate-token, secret delete, image delete, and slack destroy cannot be undone. On a terminal they ask you to type the slug or name. Without a terminal, as when an agent runs them, they exit 2 unless you pass --yes.

Deploy agents ​

text
agent-sdk deploy [--dir <path>] [--slug <slug> | --all] [--team <id>]
  [--repo <https-url>] [--ref <git-ref>] [--path <agent-path>]
  [--cursor-events-repo <repo>]... [--no-wait] [--json]

Managed hosting requires a team with agent hosting enabled. A team service-account API key with agent access can deploy.

OptionContract
--slug <slug>Select one project and set its deployment slug. Under a folder of several agents, this deploys that one agent.
--allDeploy every child under a folder of several agents. For a folder of v2 agents, print one deploy command for each agent.
--team <id>Select the Cursor team.
--repo <https-url>Set the source repository. The CLI infers it from the current checkout when possible. HTTPS is required.
--ref <git-ref>Set the source Git ref. The CLI infers the current branch when possible.
--path <agent-path>Set the project path relative to the repository root.
--cursor-events-repo <repo>Watch a repository's Cursor events. Write owner/name for GitHub and Origin, gitlab.com/<group>/<project> for GitLab (subgroups allowed), or bitbucket.org/<workspace>/<repo> for Bitbucket. Repeat the flag for each repository; the repositories you pass replace the previous list. Without the flag, the deployment watches its GitHub source repository.
--no-waitReturn after the deployment request is accepted.
--jsonPrint one object for one target or an array for multiple targets.

Deployment slugs contain lowercase letters, digits, _, or -, start with a letter or digit, and have at most 64 characters. Egress entries are lowercase hostnames with an alphabetic top-level domain; one leading *. wildcard is allowed, or a trailing :port for a protocol that is not HTTPS, with at most 64 entries.

By default, deploy waits until the deployment is running and exits nonzero if it reaches a failed state. A first deployment can return an alias token once. Store it as a secret and send it as X-Agent-Alias-Token when calling the stable alias URL.

When the team egress policy blocks a host, deploy exits nonzero and prints Error: agent-sdk deploy blocked. The message names each blocked host, the team egress mode, and two fixes: add the hosts to the team egress list, or remove them from hosting.egressDomains and deploy again. The running bot does not change.

An agent that sets architecture: "v1" does not deploy: deploy exits nonzero and tells you to run migrate first.

List deployments ​

text
agent-sdk deployment list [--team <id>] [--limit <n>] [--page-token <token>]
  [--json [--fields <a,b.c>]]

Text output shows slug, status, and update time. --json prints { items, nextPageToken }. --limit (default 20, at most 100) sets the page size, and --page-token reads the next page. An empty list succeeds.

Inspect a deployment ​

text
agent-sdk deployment get <slug> [--team <id>] [--json [--fields <a,b.c>]] [--web]

Text output includes status, release, watched repositories, routes, secret names, and the latest error. --web opens the deployment's page in Deployed Agents. A deployment still on architecture v1 shows its status with architecture: v1 and the migrate steps; deployment stop and deployment delete also still accept it.

Stop a deployment ​

text
agent-sdk deployment stop <slug> [--team <id>] [--no-wait] [--cancel-runs] [--json]

The command waits for stopped by default. --no-wait returns after the request is accepted. --cancel-runs also requests cancellation of active runs and reminder wakes.

Start a deployment ​

text
agent-sdk deployment start <slug> [--team <id>] [--json]

deployment start resumes a stopped deployment. It doesn't remove the deploy lock that deployment kill sets.

Kill a deployment ​

text
agent-sdk deployment kill <slug> [--team <id>] [--yes] [--dry-run] [--json]

Use deployment kill in an emergency. It locks deploys of the slug, stops the deployment, and requests cancellation of its active runs and reminder wakes. To bring the deployment back, run deployment unlock and then deployment start.

Unlock deploys ​

text
agent-sdk deployment unlock <slug> [--team <id>] [--json]

deployment unlock removes the lock that deployment kill sets, so deploy, deployment upgrade, and deployment rollback work for the slug again. It doesn't resume traffic; run deployment start for that.

Cancel active runs ​

text
agent-sdk deployment cancel-runs <slug> [--team <id>] [--yes] [--dry-run] [--json]

The command requests cancellation for a deployment's active runs and reminder wakes. It exits nonzero if any cancellation request fails to start.

Replace event repositories ​

text
agent-sdk deployment update <slug> (--event-repo <owner/name>... | --no-event-repos)
  [--team <id>] [--dry-run] [--json]

The supplied repositories replace the deployment's complete event repository list; they aren't merged with the previous list. --no-event-repos clears the list.

Upgrade a deployment ​

text
agent-sdk deployment upgrade <slug> [--release <id-or-version>]
  [--team <id>] [--json]

--release accepts a release ID or version. Omit it to select the newest ready release. --json prints { releaseId }.

Roll back a deployment ​

text
agent-sdk deployment rollback <slug> [--release <id-or-version>]
  [--team <id>] [--json]

deployment rollback moves the deployment to an earlier ready release without building a new one. Omit --release to select the release before the current one. --json prints { releaseId }.

Delete a deployment ​

text
agent-sdk deployment delete <slug> [--team <id>] [--no-wait] [--yes] [--dry-run] [--json]

deployment delete removes the deployment and frees its slug. It waits until the deployment is gone unless --no-wait is set.

Rotate an alias token ​

text
agent-sdk deployment rotate-token <slug> [--team <id>] [--yes] [--dry-run] [--json]

The old token stops working immediately. The replacement appears once; --json prints { aliasToken }.

Manage deployment secrets ​

text
agent-sdk secret set <slug> NAME [NAME2 ...]
  [--team <id>] [--from-argv] [--json]
agent-sdk secret list <slug> [--team <id>] [--limit <n>] [--page-token <token>] [--json]
agent-sdk secret delete <slug> NAME [--team <id>] [--yes] [--dry-run] [--json]

Pass secret names to set. On a TTY, the CLI prompts for a hidden value and ends that value at the first newline. With one name, redirected stdin is the whole value and one trailing newline is removed, so a PEM private key keeps its line breaks:

bash
agent-sdk secret set my-bot GITHUB_APP_PRIVATE_KEY < ./app.private-key.pem

With several names, provide one line per name. set rejects NAME=VALUE on the command line unless --from-argv is set, because those values can enter shell history and captured terminals.

Names use UPPER_SNAKE_CASE, start with a letter, and contain at most 64 characters. Names beginning with CURSOR_ are reserved. Values contain at most 4096 bytes, and each deployment holds at most 32 secrets.

list returns names and creation times, never values. JSON output is { secretNames } for set, { items, nextPageToken } for list, and { removed } for delete. Changes are available to subsequent hosted work.

Manage container images ​

text
agent-sdk image push <local-image> --name <name> [--team <id>] [--json]
agent-sdk image list [--team <id>] [--limit <n>] [--page-token <token>] [--json]
agent-sdk image delete <name> [--team <id>] [--yes] [--dry-run] [--json]

A persistent agent can run inside a container image that your team pushes and names in hosting.image. push needs Docker on your machine. It checks the local image first: the image must be linux/amd64 and have bash, git, node 22.13 or newer, and npm on PATH. The command then compresses the image and uploads it under --name.

list shows the team's images and how many the team can keep (--json: { items, nextPageToken, teamImageLimit }), and delete deletes one image. A deploy pins the image it uses, so after you push a new image under the same name, deploy again to pick it up.

MCP connections ​

Connect an MCP client ​

text
agent-sdk mcp serve --url <baseUrl> [--bearer-token <token>]

agent-sdk mcp install --url <baseUrl> [--bearer-token <token>]
  [--name <server-name>] [--dry-run] [--json]
CommandContract
mcp serveRead newline-delimited JSON-RPC from stdin and proxy it to the selected agent's MCP endpoint. stdout is reserved for MCP messages. A target is required.
mcp installAdd the selected agent to ~/.cursor/mcp.json. The entry runs agent-sdk mcp, which older CLI versions also understand. --name sets the server name, --dry-run previews the entry, and --json prints a machine-readable result. A --url entry with --bearer-token contains that token; handle printed and written copies as credentials.

Hosted deployments don't support mcp serve or mcp install; both exit with a usage error when you pass --prod.

Authorize MCP OAuth ​

text
agent-sdk mcp oauth <connection> [--dir <path>]
  [--slug <slug>] [--team <id>]

<connection> is the basename under bot/mcp-connections/ or bot/host-connections/.

ConnectionResult
defineConnection({ url, oauth: true })Open a browser PKCE flow and save tokens in mcp-auth.json under the CLI config directory.
defineConnection({ cursorAccount: true })Exits nonzero and points at the cursor.com dashboard, where you authorize the deployment's connectors.

URL-connection tokens are bound to the resource URL; authorize again after changing it.

See Host MCP OAuth for the full setup flow.

Channel helpers ​

Configure Slack ​

text
agent-sdk slack setup
agent-sdk slack create [--dir <path>] [--name <name>] [--env prod]
  [--slack-team <id>] [--team <id>] [--icon <url-or-file>]
  [--prefix <prefix> | --no-prefix] [--channel-posts] [--json]
agent-sdk slack destroy [--dir <path>] [--env prod] [--yes] [--dry-run]
  [--slack-team <id>] [--team <id>] [--json]
agent-sdk slack icon <url-or-file> [--dir <path>] [--env prod]
  [--slack-team <id>] [--team <id>] [--json]
agent-sdk slack init --manual [--dir <path>] [--name <name>]
  [--prefix <prefix> | --no-prefix] [--channel-posts]
  [--install | --no-install] [--slack-team <id>] [--env dev|prod]
agent-sdk slack manifest [--dir <path>] [--name <name>]
  [--env dev|prod|both] [--channel-posts] [--dry-run]
agent-sdk slack doctor [--dir <path>]
  [--prefix <prefix> | --no-prefix] [--channel <id>]... [--json]
SubcommandContract
setupPrint the setup choices without changing files.
createOpen the signed-in Deployed Agents wizard, write the resulting token pair to .env.local, and run doctor. The development app is the default; --env prod selects production. A second create overwrites the live app manifest.
destroyDelete the provisioned app. Existing local token entries remain but stop working.
iconSet an HTTPS or local PNG, JPG, or GIF icon of at most 512 KB.
init --manualWrite the channel, manifests, Slack CLI project, and setup files for a manually managed app.
manifestGenerate Slack manifests. --env defaults to both; with --dry-run, select one environment when you need one JSON document.
doctorCheck both tokens, Socket Mode connectivity, Slack authentication, and any repeatable --channel values.

The default token prefix is the project directory name normalized to upper snake case. --no-prefix uses SLACK_BOT_TOKEN and SLACK_APP_TOKEN. Channel-post subscriptions are off by default; --channel-posts adds message events for public and private channels as required by engagement.channelPosts. Multi-agent servers need one token pair per agent.

See Slack for app consent and manual setup.

Test GitHub webhooks ​

text
agent-sdk github forward [--dir <path>] [--slug <slug>] [--channel <id>]
  [--repo owner/repo | --org <org>] [--events a,b,c]
  [--url <url>] [--host <host>] [--port <n>]
  [--secret <secret>] [--install]
agent-sdk github replay <pr-url-or-owner/repo#N>
  [--events a,b,c | '*'] [--action <action>] [--conclusion <result>]
  [--comment <body>] [--context <name>] [--dir <path>]
  [--slug <slug>] [--channel <id>] [--url <url>]
  [--secret <secret>] [--dry-run] [--fixtures-dir <dir>] [--json]
agent-sdk github events [--dir <path>] [--host <host>] [--port <n>] [--json]
agent-sdk github doctor [--install] [--json]
SubcommandContract
forwardForward live deliveries with gh webhook forward. The CLI derives URLs and events from discovered channels and can fan out to several matches.
replayRead a pull request, synthesize selected webhook payloads, and post them to matching channels. The default event is pull_request; '*' selects the channel's supported declared events.
eventsList discovered channel URLs and event sets. No channels is a successful empty result.
doctorCheck the GitHub CLI, its login, and the pinned webhook extension. --install installs or repairs the extension.

Replay supports pull_request, issue_comment, pull_request_review_comment, check_run, check_suite, workflow_run, and status. --dry-run prints without posting. --fixtures-dir writes fixtures and still posts unless combined with --dry-run.

Forwarding requires repository admin access, or organization owner access for --org. It uses the GitHub CLI's stored login; unset GITHUB_TOKEN and GH_TOKEN before forwarding. Replay needs only pull-request read access.

See GitHub for channel setup and live delivery.

Test GitLab webhooks ​

text
agent-sdk gitlab replay <mr-url-or-group/project!N>
  [--events a,b,c | '*'] [--action <action>]
  [--conclusion <status>] [--comment <body>]
  [--dir <path>] [--slug <slug>] [--channel <id>]
  [--url <url>] [--host <host>] [--port <n>]
  [--secret <secret>] [--dry-run] [--fixtures-dir <dir>] [--json]
agent-sdk gitlab events [--dir <path>] [--host <host>] [--port <n>] [--json]
agent-sdk gitlab forward [--dir <path>] [--host <host>] [--port <n>]
SubcommandContract
replayRead a merge request, synthesize selected webhook payloads, and post them to matching channels. The default event is merge_request; '*' selects the channel's declared events.
eventsList discovered GitLab channel URLs and object kinds.
forwardPrint the public-hook and tunnel recipe for live deliveries.

Replay supports merge_request, note, pipeline, and push. It requires GITLAB_TOKEN with project read access. --secret defaults to GITLAB_WEBHOOK_SECRET; --dry-run and --fixtures-dir follow the GitHub replay contract.

See GitLab for channel setup and self-managed hosts.

Test Bitbucket webhooks ​

text
agent-sdk bitbucket replay <pr-url-or-workspace/repo#N>
  [--events a,b,c | '*'] [--comment <body>]
  [--dir <path>] [--slug <slug>] [--channel <id>]
  [--url <url>] [--host <host>] [--port <n>]
  [--secret <secret>] [--dry-run] [--fixtures-dir <dir>] [--json]
agent-sdk bitbucket events [--dir <path>] [--host <host>] [--port <n>] [--json]
agent-sdk bitbucket forward [--dir <path>] [--host <host>] [--port <n>]
SubcommandContract
replayRead a pull request, synthesize webhook payloads in the host's Cloud or Data Center format, and post them to matching channels.
eventsList discovered Bitbucket channel URLs and event keys.
forwardPrint the repository-hook and tunnel recipe for live deliveries.

Replay supports pullrequest:created, pullrequest:updated, pullrequest:comment_created, and repo:push, along with their supported Data Center forms. It requires BITBUCKET_TOKEN with pull-request read access. --secret defaults to BITBUCKET_WEBHOOK_SECRET; --dry-run and --out follow the GitHub replay contract.

See Bitbucket for Cloud and Data Center setup.

Test PagerDuty webhooks ​

text
agent-sdk pagerduty replay [incident-id]
  [--events a,b,c | '*'] [--comment <body>]
  [--dir <path>] [--slug <slug>] [--channel <id>]
  [--url <url>] [--host <host>] [--port <n>]
  [--secret <secret>] [--dry-run] [--fixtures-dir <dir>] [--json]
agent-sdk pagerduty events [--dir <path>] [--host <host>] [--port <n>] [--json]
SubcommandContract
replaySynthesize v3 webhook bodies for one incident and post them, in order, to matching channels. The default event is incident.triggered; '*' selects every declared event replay supports.
eventsList discovered PagerDuty channel URLs and event types.

Replay supports incident.triggered, .acknowledged, .annotated, .escalated, .resolved, and .reopened, by full name or by action alone (resolved). It needs no PagerDuty account. The incident id defaults to PREPLAY1, and --comment is the note body for annotated. --secret defaults to PAGERDUTY_WEBHOOK_SECRET, signing with its first line when it lists several; without either the deliveries are unsigned, which agent-sdk dev admits from loopback. --dry-run and --out follow the GitHub replay contract.

See PagerDuty for channel setup.

Environment variables ​

Credential resolution follows this order: --api-key, CURSOR_API_KEY, CURSOR_API_KEY_FILE, CURSOR_SERVICE_ACCOUNT_KEY, then the stored login.

VariableContract
CURSOR_API_KEYCursor credential.
CURSOR_API_KEY_FILEPath to a Cursor credential file.
CURSOR_SERVICE_ACCOUNT_KEYTeam service-account credential used after the API key and key-file sources.
CURSOR_API_BASE_URLBackend for login, account, deployment, and event commands.
CURSOR_BACKEND_URLBackend for Agent SDK turns. Set it with CURSOR_API_BASE_URL when using a non-default backend.
AGENT_SERVE_CONFIG_DIROverride the CLI config directory for stored credentials and update state.
AGENT_SERVE_NO_UPDATE_CHECK, NO_UPDATE_NOTIFIER, CIDisable published-version checks when set to a non-empty value other than 0.
GITHUB_WEBHOOK_SECRETDefault signature secret for GitHub forwarding and replay.
GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY, GITHUB_APP_INSTALLATION_IDGitHub App credentials for outbound API calls.
GITHUB_TOKEN, GH_TOKENToken credentials for outbound GitHub calls. Unset both for github forward.
GITLAB_TOKENToken for GitLab API reads and direct channel calls.
GITLAB_API_BASE_URLOverride the GitLab REST base URL for self-managed hosts.
GITLAB_WEBHOOK_SECRETDefault GitLab webhook token for replay and channel verification.
BITBUCKET_TOKENToken for Bitbucket API reads and direct channel calls.
BITBUCKET_API_BASE_URLOverride the Bitbucket Data Center REST base URL.
BITBUCKET_WEBHOOK_SECRETDefault Bitbucket signing secret for replay and channel verification.
SLACK_BOT_TOKEN, SLACK_APP_TOKENSlack tokens for one agent. Multi-agent servers use <PREFIX>_SLACK_BOT_TOKEN and <PREFIX>_SLACK_APP_TOKEN.

Exit status ​

Every command uses one exit code table. agent-sdk help prints it, and agent-sdk help --json includes it as exitCodes.

CodeMeaning
0ok
1failed (also aborted, invalid_argument, rate_limited, unavailable)
2usage: bad command, flag, or argument
3pending: the work is still running
4not_found
5unauthenticated or permission_denied
6conflict or failed_precondition
CommandNonzero contract
No commandPrint the command index and exit 0. An unknown command exits 2.
runFor local and running-server trajectories, exit 1 when the trajectory fails.
tool callExit 1 unless the response succeeds with ok: true.
session get --fileExit 1 when the reconstructed trajectory failed.
session create --waitExit 3 when the delivery names no session before --timeout-ms, and 1 when it was skipped or failed.
evalExit 1 for failed cases, or scored cases below threshold with --strict; exit 2 for invalid eval options or an execution with no matching cases. An empty --list succeeds.
eval getExit 3 while the batch runs, 1 when it failed or was cancelled, and 2 for invalid usage.
chat, session getExit 2 for documented option conflicts or missing required input.
validateExit 1 when any project diagnostic has error severity.
Commands that cannot be undoneExit 2 without --yes when there is no terminal to ask on. Exit 1 (aborted) when the typed confirmation does not match.
Any command with --dry-runExit 0 after printing what it would do, unless a check before the first change fails.
init --from automation:…Exit 1 for invalid input, authentication, export, or file-write failure. Warnings and dependency-install failure don't change a successful conversion exit.
migrateExit 0 when nothing needs a migration, after starting with --no-wait, or after the agent opens a pull request. Exit 1 for invalid input, authentication or agent failure, or a completed run without a pull request.
Other commandsExit nonzero when validation, authentication, a request, or the requested operation fails.