Agent SDK CLI
The CLI needs Node 22.13 or newer. Run agent-sdk <command> --help to see
every flag for that command.
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
| Command | Contract |
|---|---|
help, --help, -h | Print the command index, or one command's help |
serve | Serve one or more agents over HTTP |
dev | Serve agents with local-development behavior |
docs | Serve the bundled documentation |
init | Scaffold a project, or convert an Automation |
migrate | Open a pull request that migrates an early-alpha project |
skills list, skills install | List or refresh the bundled coding-agent skills |
info | Print a project's discovered parts or deployment manifest |
validate | Check project diagnostics and set the exit status |
version | Print the installed package version |
update | Upgrade the installed CLI |
login, logout, whoami | Store, remove, or show the Cursor credential |
Session and eval commands
| Command | Contract |
|---|---|
chat | Talk to a running agent, or reattach a session |
run | Run turns on a local or running agent |
tool call | Call a server tool without a model turn |
logs | Follow or dump agent logs |
session list | List sessions, or their costs |
session get | Inspect a session or a saved trace |
session create | Start or continue a hosted session |
eval | Run evals, or list, get, and cancel remote eval batches |
Managed hosting commands
| Command | Contract |
|---|---|
deploy | Deploy an agent |
deployment list, deployment get | List deployments, or inspect one |
deployment stop, start, kill, unlock, cancel-runs, upgrade, rollback, delete, rotate-token | Change a deployment's state, release, or alias token |
deployment update | Replace a deployment's event repositories |
secret | Set, list, or delete deployment secrets |
Connection and channel commands
| Command | Contract |
|---|---|
mcp serve, mcp install | Connect an MCP client to an agent |
mcp oauth | Authorize an MCP connection |
slack | Provision and check Slack channel apps |
github | Forward, replay, and inspect GitHub webhooks |
gitlab, bitbucket, pagerduty | Replay and inspect GitLab, Bitbucket, or PagerDuty webhooks |
Targets
| Target | Selection | Commands |
|---|---|---|
| Ephemeral local server | Omit --url and --prod | run, tool call, eval |
| Running server | Pass --url <baseUrl> | chat, run, tool call, eval, logs, session list, session get, mcp serve |
| Default local server | Omit --url and --prod to use http://127.0.0.1:3000 | chat, logs, session list, session get |
| Hosted deployment | Pass --prod | session 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:
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:
agent-sdk devagent-sdk dev ./agent-sdk-pr-reviewer --port 3000It accepts every serve option. Don't combine the path with a different
--dir.
Serve the docs
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
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
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
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
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
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:
agent-sdk session list --prodagent-sdk session get <sessionId> --prod --slug <slug> --view eventsStart a hosted session
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
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:
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:
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
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
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
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
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
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
agent-sdk login [--api-key <key>] [--key-name <name>]agent-sdk whoami [--json]agent-sdk logoutlogin 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
agent-sdk version [--json]agent-sdk --versionUpdate the CLI
agent-sdk updateupdate 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
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
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
agent-sdk deployment <command> <slug> [--team <id>] [--json] [--dry-run]| Command | What it does | Undoable? |
|---|---|---|
stop | Stop the deployment. --cancel-runs also cancels active runs and reminder wakes. | Yes |
start | Resume a stopped deployment. A kill lock stays. | Yes |
kill | Lock deploys, stop the deployment, and cancel its runs and reminder wakes. To recover, run unlock and then start. | No |
unlock | Remove the kill lock so deploys, upgrades, and rollbacks work again. Traffic stays stopped. | Yes |
cancel-runs | Cancel active runs and reminder wakes. | No |
update | Replace the event repositories. | Yes |
upgrade | Move to a ready release, the newest unless you pass --release. | Yes |
rollback | Move to an earlier ready release, the previous one unless you pass --release. | Yes |
delete | Remove the deployment and free its slug. | No |
rotate-token | Replace the alias token. The old one stops working at once. | No |
Replace event repositories
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
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:
agent-sdk secret set my-bot GITHUB_APP_PRIVATE_KEY < ./app.private-key.pemWith 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
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
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
agent-sdk slack setupagent-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
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
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.
| Command | Replay events | Default event | Read credential | --secret default |
|---|---|---|---|---|
gitlab replay | merge_request, note, pipeline, push | merge_request | GITLAB_TOKEN | GITLAB_WEBHOOK_SECRET |
bitbucket replay | pullrequest:created, pullrequest:updated, pullrequest:comment_created, repo:push, in Cloud or Data Center format | pullrequest:created | BITBUCKET_TOKEN | BITBUCKET_WEBHOOK_SECRET |
pagerduty replay | incident.triggered, .acknowledged, .annotated, .escalated, .resolved, .reopened | incident.triggered | None | PAGERDUTY_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.
| Variable | Contract |
|---|---|
CURSOR_API_KEY | Cursor credential. |
CURSOR_API_KEY_FILE | Path to a Cursor credential file. |
CURSOR_SERVICE_ACCOUNT_KEY | Team service-account credential. |
CURSOR_API_BASE_URL | Backend for login, account, deployment, and event commands. |
CURSOR_BACKEND_URL | Backend for agent turns. Set it with CURSOR_API_BASE_URL for a non-default backend. |
AGENT_SERVE_CONFIG_DIR | CLI config directory for stored credentials and update state. |
AGENT_SERVE_NO_UPDATE_CHECK, NO_UPDATE_NOTIFIER, CI | Turn off update checks when set to a value other than 0. |
GITHUB_WEBHOOK_SECRET | Default secret for GitHub forwarding and replay. |
GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY, GITHUB_APP_INSTALLATION_ID | GitHub App credentials for outbound API calls. |
GITHUB_TOKEN, GH_TOKEN | Tokens for outbound GitHub calls. |
GITLAB_TOKEN, GITLAB_WEBHOOK_SECRET | GitLab API token and default webhook token. |
GITLAB_API_BASE_URL | GitLab REST base URL for self-managed hosts. |
BITBUCKET_TOKEN, BITBUCKET_WEBHOOK_SECRET | Bitbucket API token and default signing secret. |
BITBUCKET_API_BASE_URL | Bitbucket Data Center REST base URL. |
SLACK_BOT_TOKEN, SLACK_APP_TOKEN | Slack 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.
| Code | Meaning |
|---|---|
0 | ok |
1 | failed, aborted, invalid_argument, rate_limited, or unavailable |
2 | usage, for a bad command, flag, or argument |
3 | pending, while the work still runs |
4 | not_found |
5 | unauthenticated or permission_denied |
6 | conflict or failed_precondition |