Appearance
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
| 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:
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 3000It 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 eventsStart 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 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
text
agent-sdk version [--json]
agent-sdk --versionUpdate the CLI
text
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
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]| 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
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.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
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.
| 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 |