Skip to content

Agent SDK CLI ​

The CLI needs Node 22.13 or newer. Run agent-sdk <command> --help to see every flag for that command.

text
agent-sdk <command>

agent-sdk help --all prints every command, and agent-sdk help <command> --json prints one command's flags as JSON.

Commands are named agent-sdk <resource> <verb>, such as agent-sdk deployment list, apart from workflow verbs such as init, dev, and deploy. Older names, such as agent-sdk deployments or agent-sdk secrets set, still run and print the new form on stderr. The bdk command remains available.

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 bundled documentation
initScaffold a project, or convert an Automation
migrateOpen a pull request that migrates an early-alpha project
skills list, skills installList or refresh the bundled coding-agent skills
infoPrint a project's discovered parts or deployment manifest
validateCheck project diagnostics and set the exit status
versionPrint the installed package version
updateUpgrade the installed CLI
login, logout, whoamiStore, remove, or show the 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
session createStart or continue a hosted session
evalRun evals, or list, get, and cancel remote eval batches

Managed hosting commands ​

CommandContract
deployDeploy an agent
deployment list, deployment getList deployments, or inspect one
deployment stop, start, kill, unlock, cancel-runs, upgrade, rollback, delete, rotate-tokenChange a deployment's state, release, or alias token
deployment updateReplace a deployment's event repositories
secretSet, list, or delete deployment secrets

Connection and channel commands ​

CommandContract
mcp serve, mcp installConnect an MCP client to an agent
mcp oauthAuthorize an MCP connection
slackProvision and check Slack channel apps
githubForward, replay, and inspect GitHub webhooks
gitlab, bitbucket, pagerdutyReplay and inspect GitLab, Bitbucket, or PagerDuty webhooks

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 to use http://127.0.0.1:3000chat, logs, session list, session get
Hosted deploymentPass --prodsession list, session get, logs. session create is always hosted.

A hosted deployment supports only the commands in its row. chat, run, tool call, eval, mcp serve, and mcp install exit with a usage error when you pass --prod. To test a hosted agent, start a turn with session create and inspect it with session get.

--url and --prod are mutually exclusive. An explicit --url must include the slug for a multi-agent server, such as http://127.0.0.1:3000/pr-approver. Otherwise --slug picks the agent, and under --prod it defaults to the --dir basename. --json prints one JSON document on stdout, including errors. Without it, output is text, even when piped.

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

serve listens on 127.0.0.1:3000, or the next free port when that one is taken. --mode multi, the default, mounts each project at /<slug>/v1/*, and --mode single mounts one project at /v1/*. --dev turns off schedule and reminder firing and admits unsigned loopback GitHub deliveries.

--bearer-token requires a token on routes that don't declare their own authentication. --allow-anonymous admits every caller as one principal, so use it only behind a trusted network boundary. The slugs v1, playground, and docs are reserved.

Develop locally ​

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

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

It accepts every serve option. Don't combine the path with a different --dir.

Serve the docs ​

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

docs serves the bundled documentation on a loopback port until you press Ctrl-C. --print prints the URL without opening a browser.

Sessions and turns ​

Chat with an agent ​

text
agent-sdk chat [--url <baseUrl>] [--message <text>]
  [--session <id> | --resume] [--continuation-token <token>]
  [--slug <slug>] [--json] [--text] [--no-color]

On a TTY, chat opens a REPL and sends any --message first. Without a TTY, it sends --message as one turn, or reads newline-delimited messages until EOF. --session <id> reattaches a stored session, and --resume picks the most recent one.

Run turns ​

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]

Repeat --message for a multi-turn run. run prints the compact trajectory, writes an NDJSON trace unless you pass --no-trace, and exits 1 when the trajectory fails. It has no default timeout.

Call a tool ​

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

--input takes JSON and defaults to {}. --session runs the tool in that session's workspace and records the call. The command exits 1 unless the response has ok: true. See Tools for 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]

--limit sets the page size, 20 by default and at most 100. With --prod, it lists the most recently active hosted sessions, and --since reads back to a cutoff such as 24h or an ISO-8601 instant. --view cost works only against a running server.

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]

session get prints a compact trajectory, or raw events with --view events. --view cost and --trace work only locally. --file reads a saved trace and exits 1 when that trajectory failed, and --web opens the session in the playground. For a hosted deployment:

bash
agent-sdk session list --prod
agent-sdk session get <sessionId> --prod --slug <slug> --view events

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]

session create sends one --message to the hosted deployment. Without --wait, it exits 0 once the deployment accepts the turn, before a new session has an ID. --wait polls until the session starts. It exits 3 when --timeout-ms passes first and 1 when the delivery is skipped or fails.

--session continues a session that session create started. --read-only stubs write tools, and --as-of freezes the session's clock at an ISO-8601 instant. See Verify a hosted turn.

Follow logs ​

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

logs follows output until Ctrl-C, and --once prints the current buffer and exits. With --prod, it follows the hosted deployment's recent sessions and prints a ==> <sessionId> (<channel>) <== header when the output switches sessions. A session ID follows one hosted session and requires --prod.

Evals ​

Run evals ​

eval discovers evals/**/*.eval.{ts,js} and runs the 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] [--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 none for every case. Put an ID that is also a subcommand word after --, as in agent-sdk eval -- list. The project needs an eval configuration.

--strict fails a scored case below its soft threshold. The command exits 1 for failed cases and 2 for invalid options or no matching cases. A running server prints an Eval ID when it accepts the batch, and --no-wait returns at that point. These commands require --url:

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

eval get exits 3 while the batch runs and 1 when it failed or was cancelled.

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. With one, it adds missing scaffold files, installs dependencies, and tries to put agent-sdk on PATH. On a TTY, it also asks the template's questions and starts login when needed.

--template takes 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=value answers a template question without a prompt. --dry-run lists the files without writing them.

Convert an Automation ​

--from automation: takes a Cursor Automation dashboard URL or UUID and writes to ./<automation-name> unless you name a directory. Generated files don't overwrite existing paths, but the npm install that follows can run lifecycle scripts from an existing package.json. See Convert a Cursor Automation.

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 that deployed with architecture: "v1" during the early alpha. It starts a Cursor cloud agent on a pushed Git ref with the bundled bdk-migrate-v2 skill, and the agent opens a pull request with the source changes. The command never deploys or changes secrets.

With nothing to change, it prints Nothing to migrate. and exits 0, and it exits 1 if the run ends without a pull request. deploy refuses a project that sets architecture: "v1" and points to migrate. See Migrate an early-alpha project.

Install and list coding-agent skills ​

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

Package installation copies the bundled skills, skills install replaces the installed copies and removes stale ones, and skills list prints each skill's bundled and installed versions. The bdk-cli skill teaches agents to run agent-sdk safely.

Inspect a project ​

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

Text output lists what discovery found, such as tools, channels, and diagnostics. --view manifest summarizes one project's deployment metadata without a network request.

Validate a project ​

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

validate prints every discovered project's diagnostics and exits 1 when any diagnostic has error severity. validate fails when an SCM webhook secret or GitHub credential is a literal or a getter, and the error message shows the { secretName } form to use. A project that still sets architecture: "v1" gets the same finding as a warning.

Credentials and versions ​

Manage credentials ​

text
agent-sdk login [--api-key <key>] [--key-name <name>]
agent-sdk whoami [--json]
agent-sdk logout

login stores a supplied API key, or opens browser sign-in and stores the key it creates. whoami shows the active credential and its source. logout removes the stored credential but doesn't revoke the key, so revoke it in the Cursor dashboard.

Print the version ​

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

Update the CLI ​

text
agent-sdk update

update upgrades a recognized global or project install to npm's latest tag, or prints a manual upgrade command. Published installs check for updates daily unless an update-check variable is set.

Managed hosting ​

Every command here that changes a deployment takes --dry-run, which runs the reads, stops at the first change, prints that request with secrets redacted, and exits 0.

secret delete, image delete, slack destroy, and the deployment commands marked No in the lifecycle table can't be undone. On a terminal they ask you to type the slug or name, and a mismatch exits 1. Without a terminal, 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]

Deploying needs a team with agent hosting turned on, and a team service-account key with agent access can deploy. The CLI infers --repo, --ref, and --path from the current checkout, and the repository must use HTTPS.

deploy deploys one agent. On a folder of several agents, pass --slug to pick one. --all, or picking several agents, prints one agent-sdk deploy --dir command per agent and exits 1.

--cursor-events-repo sets the repositories whose Cursor events the deployment receives. Write owner/name for GitHub, gitlab.com/<group>/<project> for GitLab, or bitbucket.org/<workspace>/<repo> for Bitbucket. A GitLab path can include subgroups. Repeat the flag once per repository. Each deploy replaces the whole list. Without the flag, the deployment watches its GitHub source repository.

deploy waits until the deployment runs and exits nonzero if it fails, unless you pass --no-wait. The first deploy of a slug can print an alias token once. Slugs use lowercase letters, digits, _, and -, start with a letter or digit, and have at most 64 characters. See Deployment for egress hosts and the alias token.

Inspect deployments ​

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

deployment list shows each deployment's slug, status, and update time, and deployment get adds the release, watched repositories, routes, secret names, and latest error. --web opens the deployment in Deployed Agents, and an early-alpha deployment shows the steps to migrate it.

Change a deployment ​

text
agent-sdk deployment <command> <slug> [--team <id>] [--json] [--dry-run]
CommandWhat it doesUndoable?
stopStop the deployment. --cancel-runs also cancels active runs and reminder wakes.Yes
startResume a stopped deployment. A kill lock stays.Yes
killLock deploys, stop the deployment, and cancel its runs and reminder wakes. To recover, run unlock and then start.No
unlockRemove the kill lock so deploys, upgrades, and rollbacks work again. Traffic stays stopped.Yes
cancel-runsCancel active runs and reminder wakes.No
updateReplace the event repositories.Yes
upgradeMove to a ready release, the newest unless you pass --release.Yes
rollbackMove to an earlier ready release, the previous one unless you pass --release.Yes
deleteRemove the deployment and free its slug.No
rotate-tokenReplace the alias token. The old one stops working at once.No

Replace event repositories ​

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

The repositories you pass replace the deployment's whole event repository list, and --no-event-repos clears it.

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]

On a TTY, secret set prompts for each hidden value. With one name, redirected stdin is the whole value minus one trailing newline, so a PEM key keeps its line breaks:

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

With several names, give one line per name. set rejects NAME=VALUE arguments unless you pass --from-argv, because shell history keeps them. Names use UPPER_SNAKE_CASE, and the CURSOR_ prefix is reserved. secret list returns names, never values.

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]

mcp serve proxies newline-delimited JSON-RPC from stdin to the agent's MCP endpoint and reserves stdout for MCP messages. mcp install adds the agent to ~/.cursor/mcp.json. An entry made with --bearer-token contains that token, so treat every printed or written copy as a credential.

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/. A url connection with oauth: true opens a browser PKCE flow and saves tokens bound to that URL, so authorize again after you change it. A cursorAccount connection exits nonzero and points to the cursor.com dashboard. See Host MCP OAuth.

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]

slack create opens the Deployed Agents wizard, writes the token pair to .env.local, and runs doctor, which checks both tokens and Socket Mode. It makes the development app unless you pass --env prod. The token prefix defaults to the project directory name in upper snake case. --channel-posts adds the message events that engagement.channelPosts needs. See Slack for 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]

forward sends live deliveries to discovered channels through gh webhook forward. It needs repository admin access, or organization owner access for --org, and it uses the GitHub CLI's own login, so unset GITHUB_TOKEN and GH_TOKEN first. doctor checks the GitHub CLI and its webhook extension.

replay reads a pull request with read access, builds webhook payloads, and posts them to matching channels. Its events are pull_request, the default, issue_comment, pull_request_review_comment, check_run, check_suite, workflow_run, and status. --dry-run prints the payloads without posting, and --fixtures-dir also writes them as fixtures. See GitHub for channel setup.

Test GitLab, Bitbucket, and PagerDuty webhooks ​

text
agent-sdk gitlab replay <mr-url-or-group/project!N> [replay flags]
agent-sdk bitbucket replay <pr-url-or-workspace/repo#N> [replay flags]
agent-sdk pagerduty replay [incident-id] [replay flags]
agent-sdk <gitlab|bitbucket|pagerduty> events [--dir <path>] [--json]
agent-sdk <gitlab|bitbucket> forward [--dir <path>]

Replay takes the same flags as github replay, including --fixtures-dir. events lists the discovered channels, and forward prints the webhook and tunnel recipe for live deliveries.

CommandReplay eventsDefault eventRead credential--secret default
gitlab replaymerge_request, note, pipeline, pushmerge_requestGITLAB_TOKENGITLAB_WEBHOOK_SECRET
bitbucket replaypullrequest:created, pullrequest:updated, pullrequest:comment_created, repo:push, in Cloud or Data Center formatpullrequest:createdBITBUCKET_TOKENBITBUCKET_WEBHOOK_SECRET
pagerduty replayincident.triggered, .acknowledged, .annotated, .escalated, .resolved, .reopenedincident.triggeredNonePAGERDUTY_WEBHOOK_SECRET

PagerDuty replay's incident ID defaults to PREPLAY1, and --comment is the note body for annotated. Without a secret, its deliveries are unsigned, and agent-sdk dev admits them from loopback. See GitLab, Bitbucket, and PagerDuty for channel setup.

Environment variables ​

The CLI tries --api-key, CURSOR_API_KEY, CURSOR_API_KEY_FILE, CURSOR_SERVICE_ACCOUNT_KEY, then the stored agent-sdk login credential, in that order.

VariableContract
CURSOR_API_KEYCursor credential.
CURSOR_API_KEY_FILEPath to a Cursor credential file.
CURSOR_SERVICE_ACCOUNT_KEYTeam service-account credential.
CURSOR_API_BASE_URLBackend for login, account, deployment, and event commands.
CURSOR_BACKEND_URLBackend for agent turns. Set it with CURSOR_API_BASE_URL for a non-default backend.
AGENT_SERVE_CONFIG_DIRCLI config directory for stored credentials and update state.
AGENT_SERVE_NO_UPDATE_CHECK, NO_UPDATE_NOTIFIER, CITurn off update checks when set to a value other than 0.
GITHUB_WEBHOOK_SECRETDefault 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_TOKENTokens for outbound GitHub calls.
GITLAB_TOKEN, GITLAB_WEBHOOK_SECRETGitLab API token and default webhook token.
GITLAB_API_BASE_URLGitLab REST base URL for self-managed hosts.
BITBUCKET_TOKEN, BITBUCKET_WEBHOOK_SECRETBitbucket API token and default signing secret.
BITBUCKET_API_BASE_URLBitbucket Data Center REST base URL.
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 these exit codes, and agent-sdk help --json lists them as exitCodes.

CodeMeaning
0ok
1failed, aborted, invalid_argument, rate_limited, or unavailable
2usage, for a bad command, flag, or argument
3pending, while the work still runs
4not_found
5unauthenticated or permission_denied
6conflict or failed_precondition