Skip to content

CLI reference

@cursor/july installs july (so npx @cursor/july docs works), agent-sdk, and the legacy agent-serve alias. The examples on this page use agent-sdk. Run the CLI with Node 22.13 or newer. Don't run it with Bun; Bun corrupts tool-result streams from the Cursor SDK.

The current release still uses .agent-serve for on-disk state. See the rename table for identifiers still moving to agent-sdk names.

agent-sdk help prints the built-in summary. The Slack and GitHub packs also provide agent-sdk slack help and agent-sdk github help.

CommandDescription
serveServe agents over HTTP
devStart local development with serve --dev
chatTalk to a running agent
resumeReattach chat to a previous session
logsFollow local or hosted logs
sessionsList sessions on a running agent
sessionInspect one session
costReport per-session token usage and estimated cost
playgroundOpen the local or hosted playground
docsServe the shipped documentation site locally
runRun one or more turns locally, remotely, or on a hosted agent
callCall a server tool without a model turn
evalRun filesystem evals
trajectorySummarize a saved events.ndjson file
initScaffold a project, or print the setup guide
convert-automationExport a Cursor Automation into an agent project
install-skillsInstall the coding-agent skills without running init
infoPrint the discovered agent surface
validateCheck a project and fail on errors
login / logout / whoamiManage the host's Cursor credential
versionPrint the installed version and exit (also --version / -V)
updateUpgrade the installed CLI
deployDeploy one or more agents to Cursor managed hosting
deploymentsList hosted deployments
deploymentInspect one hosted deployment
stopStop a hosted deployment
rotate-tokenReplace a deployment's alias token
rotate-pod-credentialReplace a deployment's pod credential
secretsManage deployment secrets
mcpProxy the agent's MCP endpoint over stdio; mcp install writes ~/.cursor/mcp.json
mcp oauthAuthorize host MCP OAuth; optional --store to deployment secrets
slack ...Provision, set up, and check Slack channels
github ...Forward, replay, and inspect GitHub webhook channels

Choose a target

Request-sending commands support three target types.

TargetHow to select itCommands
Ephemeral local serverOmit --url and --prodrun, call, eval
Running serverPass --url <baseUrl>, unless the command uses the localhost default described nextchat, resume, logs, sessions, session, cost, playground, run, call, eval, mcp
Cursor managed hostingPass --prodchat, resume, logs, sessions, session, cost, playground, run, call, eval, mcp

chat, logs, sessions, session, cost, and playground default to http://127.0.0.1:3000. A --url must include the agent slug for a multi-agent server, such as http://127.0.0.1:3000/pr-approver. --slug doesn't change an explicit URL. mcp has no default target; pass --url or --prod.

With --prod, --slug selects the deployment and --team selects the Cursor team. The slug defaults to the --dir basename. The team defaults to the signed-in account's team. --url and --prod are mutually exclusive.

Use --bearer-token <token> when a running server requires bearer authentication. Hosted commands use your Cursor credential to request short-lived engine access. --api-key overrides the Cursor credential for login, serve, hosted targets, and managed-hosting commands. --state-root applies to serve and ephemeral run, call, and eval servers. Running and hosted targets ignore it.

For ephemeral run, call, and eval commands, omitting --slug selects an unslugged root mount when one exists. Otherwise, the Agent SDK selects the first discovered agent.

serve

serve hosts every agent under --dir in multi-agent mode by default.

bash
agent-sdk serve [--dir <path>] [--port 3000] [--host 127.0.0.1] [--dev]
                  [--mode multi|single] [--api-key <key>]
                  [--state-root <path>] [--bearer-token <secret> | --allow-anonymous]
                  [--allow-anonymous-cursor-github]
                  [--allow-anonymous-cursor-account-mcp]
                  [--public-url <url>] [--cloud-tools-url <url>]
                  [--cursor-github-proxy] [--no-control-plane]
                  [--no-schedules] [--no-playground]
                  [--no-docs] [--cursor-events --repo owner/name]...

If --dir is an agent project, it mounts under its directory name. If it contains agent projects, each child mounts separately. The index lives at /. Each agent is available at /<slug>/v1/* and /<slug>/playground. On a TTY, press Enter to reload agent code. Unless --state-root is set, each mount uses <agent-project>/.agent-serve; slugged mounts use <agent-project>/.agent-serve/<slug>.

FlagMeaning
--portListen on this port. 0 selects an available port. The default is 3000. When the default is taken, serve tries the next free port and prints a notice; an explicit --port fails with a next-port hint instead.
--hostBind this host. The default is loopback-only 127.0.0.1.
--devDisable automatic schedule and reminder firing, admit unsigned loopback GitHub deliveries, widen playground session access on loopback, and start Vite HMR when available.
--modeUse multi for slugged routes and an index, or single for one agent at the unslugged /v1/*. The default is multi.
--api-keyUse this Cursor API key. The command falls back to CURSOR_API_KEY, then the stored login.
--state-rootStore sessions, streams, workspaces, and channel state here. Keep durable production state outside the agent repository.
--bearer-tokenRequire this bearer token on routes without authored auth. Mutually exclusive with --allow-anonymous.
--allow-anonymousAdmit every caller as one anonymous principal. Use only behind a trusted network boundary.
--allow-anonymous-cursor-githubAllow anonymous callers to drive sessions holding a Cursor account's repo-scoped GitHub credential. Use only behind an authenticating proxy.
--allow-anonymous-cursor-account-mcpAllow anonymous callers to drive Cursor account MCP connectors (defineConnection({ cursorAccount: true })). Use only behind an authenticating proxy (hosted alias token counts).
--public-urlSet the externally reachable host URL. Cloud-runtime peer connections need it to call back into this server.
--cloud-tools-urlAuthenticated HTTP MCP URL for this deployment's direct server-tool endpoint. Hosted deployments configure it automatically.
--cursor-github-proxyRoute githubChannel({ cursorAccount }) API calls through the Cursor backend's GitHub forwarder instead of minting raw installation tokens into this process. AGENT_SERVE_GITHUB_PROXY_URL overrides the base URL.
--no-control-planeSkip the bundled schedule and reminder clocks. Cursor hosting passes this so the platform fires timed work through internal routes instead.
--no-schedulesDisable the cron runner outside dev mode.
--no-playgroundSkip the web playground and its build or HMR process.
--no-docsSkip the documentation site at /docs and its build.
--cursor-eventsPull SCM events from Cursor's /v0/scm-events in addition to authored webhook routes. Requires a signed-in host. Pass repeatable --repo owner/name values; repos declared by githubChannel({ cursorAccount }) also enable the relay. State lives under <state-root>/cursor-events/.

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

dev

dev is the local-development shortcut for serve --dev. Pass the agent folder as a positional path, or run it from inside the project:

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

dev accepts the same flags as serve. You can use --dir instead of the positional path. Dev mode is always on: schedules and reminders wait for manual dispatch, GitHub accepts unsigned loopback deliveries, and Vite HMR starts when the toolchain is present. Prefer this over serve --dev while iterating. Pass at most one positional path. Don't combine a positional path with a different --dir.

chat

chat talks to a running agent from the terminal. It never starts a server.

bash
agent-sdk chat --url http://127.0.0.1:3000/pr-approver
agent-sdk chat --message "Is the PR ready to approve?"
agent-sdk chat --message "Inspect PR 42" --json
agent-sdk chat --prod --slug pr-approver --team 123

chat streams text, tool calls, and a per-turn usage footer. On a TTY, --message seeds the interactive REPL. With non-TTY input, --message runs one turn and exits; without it, chat reads newline-delimited messages until EOF. --json requires --message, runs one turn, and prints { ok, sessionId, continuationToken, trajectory }. --text prints a compact trajectory when combined with --json. --no-color forces plain interactive output.

Use --session <id> to reattach a stored session. The command looks up its continuation token when you omit --continuation-token. Use --resume to select the most recently updated session with a continuation token.

resume

resume is the direct way to reattach the chat REPL.

bash
agent-sdk resume ses_123 --url http://127.0.0.1:3000/pr-approver
agent-sdk resume --url http://127.0.0.1:3000/pr-approver
agent-sdk resume ses_123 --prod --team 123 --slug pr-approver
agent-sdk resume ses_123 --message "Continue the review" --json

Pass a session ID to select it. Omit the ID to select the most recently updated followable session from /v1/sessions. The command looks up a missing continuation token, replays the transcript, and accepts follow-ups. resume --json requires --message. The same operation is available as chat --session <id> or chat --resume.

logs

logs follows the local or hosted log buffer.

bash
agent-sdk logs [--url http://127.0.0.1:3000] [--once] [--json]
agent-sdk logs --prod [--slug <slug>] [--team <id>] [--once] [--json]

Local mode reads /v1/logs from the running server. Hosted mode reports deploy progress until the deployment is running or degraded, then follows reachable runtime logs. The command follows until Ctrl-C by default. --once prints the current buffer and exits. --json emits newline-delimited JSON events.

sessions

sessions lists sessions on a running or hosted agent.

bash
agent-sdk sessions [--url <baseUrl> | --prod] [--slug <slug>]
                  [--team <id>] [--bearer-token <token>] [--json]

Text output shows session ID, channel, mode, turn count, running status, and update time. --json prints full session summaries in { sessions }, including continuation tokens.

session

session inspects the event stream for one session.

bash
agent-sdk session <sessionId> [--url <baseUrl> | --prod]
                 [--slug <slug>] [--team <id>]
                 [--json | --text | --events] [--out <file.ndjson>]

By default, session prints a compact trajectory. --text selects the same format. --json prints the trajectory object. --events prints { sessionId, events } with the raw event list. You can't combine --events and --json. --out <file.ndjson> writes the raw NDJSON trace to a file instead of printing. The file uses the same format as run --events and the playground download. Use resume to continue the conversation.

cost

cost reports token usage and estimated cost.

bash
agent-sdk cost [sessionId] [--url <baseUrl> | --prod]
              [--slug <slug>] [--team <id>] [--json]

With a session ID, cost prints per-turn token usage and estimated cost for that session. Without one, it prints one row per session on the target plus a total. Costs are the engine's recorded estimates from turn.completed events; turns persisted before cost tracking count as unpriced. --json prints the underlying report, or { sessions } when aggregating. Like session, the command supports --dir, --bearer-token, and the --url/--prod targets, and defaults to the local server.

playground

playground opens an agent's web playground.

bash
agent-sdk playground [--url <baseUrl> | --prod] [--session <id>]
                    [--slug <slug>] [--team <id>]
                    [--bearer-token <token>] [--print]

--session opens a deep link to one session. --print prints the URL without opening a browser.

For an unauthenticated local URL, playground opens the browser and exits. --prod and --bearer-token start a loopback proxy to inject browser-inaccessible credentials. The proxy stays open until Ctrl-C, including when you pass --print.

docs

docs serves the documentation shipped inside @cursor/july and opens it in a browser. You don't need an agent project.

bash
npx @cursor/july docs
agent-sdk docs [--port <n>] [--host 127.0.0.1] [--print]

The site is the same VitePress build mounted at /docs on a running serve host. docs starts a loopback-only static server (default port is an ephemeral port) and keeps it open until Ctrl-C. --print prints the URL without opening a browser.

run

run sends one or more turns and prints a JSON result.

bash
agent-sdk run --dir . --message "Is https://github.com/acme/checkout/pull/42 ready?"
agent-sdk run --dir . --message "Inspect PR 42" --message "Summarize the risks"
agent-sdk run --url http://127.0.0.1:3000/pr-approver --message "Inspect PR 42"
agent-sdk run --prod --slug pr-approver --team 123 --message "Inspect PR 42"
agent-sdk run --dir . --messages-file ./prompts.json

Without --url or --prod, the command starts an ephemeral server on an available port. Its state root is a temporary directory outside the project unless you pass --state-root. The command closes the server after the turns finish.

FlagMeaning
--message <text>Send a user message. Repeat the flag for a multi-turn run.
--messages-file <path>Read a JSON array of strings. File messages run before repeated --message values.
--session <id>Follow up an existing session. Unlike chat, run doesn't look up a missing continuation token.
--continuation-token <token>Continue the existing session selected by --session.
--events <file>Write the raw NDJSON event stream to this path.
--no-eventsDon't write an event stream.
--textPrint a compact trajectory instead of the JSON result.
--timeout-ms <n>Abort the turn after a positive number of milliseconds. There is no default timeout.
--no-streamHide live tool and reply progress on stderr. Progress is on by default when stderr is a TTY.
--slug <slug>Pick one agent when local discovery mounts several agents. With --prod, select the hosted deployment.

The default trace path is <dir>/.agent-serve/traces/<sessionId>.ndjson. JSON output contains ok, sessionId, continuationToken, trace, playgroundUrl, playgroundHint, visualize, and trajectory. The command exits non-zero when the trajectory fails.

call

call invokes a server tool directly, with no model turn.

bash
agent-sdk call inspect_pr --dir . \
  --input '{"prUrl":"https://github.com/acme/checkout/pull/42"}'
agent-sdk call inspect_pr --url http://127.0.0.1:3000/pr-approver \
  --input '{"prUrl":"https://github.com/acme/checkout/pull/42"}'
agent-sdk call refresh_cache --url http://127.0.0.1:3000/pr-approver \
  --session ses_123
agent-sdk call inspect_pr --prod --slug pr-approver --team 123 --input '{}'

call sends POST /v1/tools/:toolName and runs the tool in the serving process without a model turn. --input accepts any valid JSON and defaults to {}. Tools with a Zod input schema validate and transform the value before execution. A local call needs no inference credential. A hosted call still needs Cursor credentials to reach the deployment.

--session runs the tool inside an existing session and records it on the event stream. If a model turn is active or pending, the server returns session_busy; retry after the turn finishes. The command prints the server's JSON response and exits non-zero unless the HTTP response succeeds with ok: true. See Tools.

eval

eval runs the project's filesystem evals.

bash
agent-sdk eval --dir . --list          # discovered datapoints
agent-sdk eval --dir .                 # run all
agent-sdk eval --dir . builds/checkout # one datapoint
agent-sdk eval --dir . builds          # every datapoint in the file
agent-sdk eval --dir . --tag smoke     # by tag (repeatable)
agent-sdk eval --dir . --json          # machine-readable results
agent-sdk eval --dir . --verbose       # stream t.log lines + reply snippets
agent-sdk eval --prod --slug pr-approver --team 123
# prints Eval ID immediately on --prod/--url; then:
agent-sdk eval status <evalId> --prod --slug pr-approver
agent-sdk eval cancel <evalId> --prod --slug pr-approver

eval runs evals/**/*.eval.{ts,js} on an ephemeral server or against --url. Select one or more exact case IDs, file ID prefixes, or tags. Omit selectors to run all cases. Repeated --tag flags use OR matching.

An eval run requires evals/evals.config.{ts,js} with maxConcurrency between 1 and 200. Timeout priority is the case's timeoutMs, the CLI's --timeout-ms, the config's timeoutMs, then 180 seconds.

FlagMeaning
--listPrint discovered cases without running. --list --json prints them as an array.
--tag <tag>Run cases with this tag. Repeated flags use OR matching.
--jsonPrint { ok, passed, failed, results }.
--verboseStream t.log lines and reply snippets.
--no-streamHide live progress on stderr.
--strictExit 1 when a scored case misses a soft threshold.
--max-concurrency <n>Override maxConcurrency from evals.config.ts.
--junit <path>Write JUnit XML for CI annotations.
--artifacts <dir>Write run artifacts here. The default is a timestamped directory under <dir>/.agent-serve/evals/.
--no-artifactsSkip run artifacts.
--skip-reportIgnore reporters from evals.config.ts and eval files.
--out <path>Also write the full results JSON to this path (also for eval status <evalId>).
--no-waitReturn with the Eval ID as soon as a --prod or --url batch is accepted.
--timeout-ms <n>Per-case timeout override.

Failed cases exit 1; no matching cases exit 2. See Evals.

trajectory

trajectory summarizes a saved event stream.

bash
agent-sdk trajectory --events /tmp/run.ndjson [--text]

trajectory converts a saved NDJSON stream into the trajectory JSON returned by run. --text prints the compact view. The command exits non-zero when the reconstructed trajectory failed.

init

init scaffolds a new project.

bash
agent-sdk init ./my-agent          # scaffold package.json, tsconfig.json, agent/ + a demo tool
agent-sdk init ./my-demo --template demo              # record a PR walkthrough
agent-sdk init ./my-reviewer --template security-reviewer   # review PRs for security bugs
agent-sdk init ./my-triage --template triage-linear   # comment on Linear issues
agent-sdk init ./my-triage --template triage-jira     # comment on Jira issues
agent-sdk init ./my-owners --template agentic-owners  # review PRs via owners policies
agent-sdk init ./pr-autofixer --template pr-autofixer # fix PRs on a cloud VM
agent-sdk init ./pr-autofixer --template pr-autofixer \
  --var repos=acme/widgets,acme/api --json
agent-sdk init ./my-agent --json   # machine-readable summary for tooling
agent-sdk init                     # no directory: print the setup guide

init leaves existing files unchanged and labels each one create or exist. It prints the project path, then runs npm install so @cursor/july resolves for dev and run.

Templates may ship init.json. On a TTY, init asks those questions before writing files. pr-autofixer asks for GitHub repos. Repeat --var id=value to answer without a prompt. --json and non-TTY hosts skip the interview unless --var is set.

On a TTY, init also asks whether to install or update the coding-agent skills in ~/.cursor/skills/agentkit/. If accepted, it overwrites them with the version bundled in the installed package. The prompt is skipped for --json and non-interactive hosts.

If the host isn't signed in, init runs agent-sdk login and waits for the browser flow. It then prints the cd, agent-sdk login, and agent-sdk dev steps still needed.

With --json, init still installs dependencies but never blocks on login or skill installation. It prints { ok, directory, created, skipped, installed, installError, next } (with login in next when unsigned).

convert-automation

convert-automation exports a Cursor Automation into an agent project.

bash
agent-sdk convert-automation <url> [--dir <path>] [--json]

<url> is the dashboard URL (…/automations/<uuid> or …/custom-agents/<uuid>) or a bare UUID. The command fetches the Automation with your Cursor credentials. It writes converted files to --dir, which defaults to ./<automation-name>, adds missing init scaffold files, and runs npm install. File generation does not overwrite existing paths. The install may still update lockfiles or run lifecycle scripts from an existing package.json.

MCP servers convert to Cursor-account connections resolved at runtime. The project contains their names, not server URLs or credentials. Local runs use the signed-in account. Hosted deployments use a separate service account; authorize each generated connection with mcp oauth after the first deploy. Review the generated project, then run validate and dev.

Warnings do not change the exit status. Bad arguments, authentication failures, fetch failures, and file write failures return a nonzero exit code.

--json prints { ok, directory, files, warnings, setupSteps, installed, installError, mcpConnections }. On failure it prints { ok: false, error } and still writes the prose error to stderr.

The Convert a Cursor Automation guide covers generated files and behavior the converter cannot reproduce.

install-skills

install-skills installs the package's coding-agent skills into ~/.cursor/skills/agentkit/.

bash
agent-sdk install-skills [--print] [--json]

Running the command is the confirmation: it never prompts, and it overwrites the installed skills with the version bundled in the package. init offers the same install once, interactively. --print previews the skills, the removals, and the install path without writing anything. --json prints { ok, dryRun, directory, firstInstall, skills, removed }.

info

info prints the discovered agent surface.

bash
agent-sdk info --dir . [--json]

info reports the model, instruction size, tools, skills, MCP connections, subagents, channel routes, schedules, hooks, and diagnostics. Text output summarizes each mounted agent. --json prints { agents: [{ slug, ...projectInfo }] }, with one entry per mounted slug. Use validate, not info --json, when a script needs an error exit status.

validate

validate checks the project and sets the exit code.

bash
agent-sdk validate --dir .

validate prints diagnostics for each agent and exits non-zero when any diagnostic has error severity. serve also refuses to start when errors are present. Warnings don't change the exit status.

login / logout / whoami

Three commands manage the host's Cursor credential.

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

login signs the host in to Cursor: browser sign-in mints a named, dashboard-revocable API key, and only the key is stored (the default name is <invoked command> (<hostname>)). It powers inference, the cloud runtime, and Cursor account MCP connections. --key-name changes the name of a browser-minted key. login --api-key validates and stores a key you already created.

whoami shows which credential is active and why. CURSOR_API_KEY takes precedence over the stored login. logout removes the local credential file but doesn't revoke the API key. Revoke it in the Cursor dashboard when it should stop working.

Non-production backends: login and account RPCs honor CURSOR_API_BASE_URL while the SDK harness honors CURSOR_BACKEND_URL. Set both to the same URL, or keys minted on one backend are rejected by the other.

update

update upgrades an installed copy to the latest published version.

bash
agent-sdk update

The command checks npm's latest tag, detects how the Agent SDK was installed, and runs the matching npm, pnpm, Yarn, or Bun upgrade command. It handles global installs and project dependencies. It doesn't prompt before running the package-manager command.

Source checkouts, npx or pnpm dlx caches, and unknown install layouts aren't changed. The command prints a manual upgrade hint instead.

Published installs also check for a newer version at most once every 24 hours and print an update warning on stderr. Source checkouts, CI, and commands with an explicit --json flag skip this automatic check.

deploy

deploy sends one or more agents to Cursor managed hosting.

bash
agent-sdk deploy [--dir <path>] [--slug <slug> | --all] [--team <id>]
                [--repo <https-url>] [--ref <git-ref>] [--path <agent-path>]
                [--cursor-events-repo owner/name]...
                [--allow-domain <domain>]... [--no-wait] [--json]

Managed hosting requires team-admin permission and the team's cloud-agent entitlement. --team defaults to the signed-in account's team.

For a single project, the slug defaults to a normalized version of the directory name. Deployment slugs contain lowercase letters, digits, _, or -, with a maximum of 64 characters. For a directory with several agents, select one with --slug, deploy all with --all, or choose from the TTY prompt. Non-interactive callers must pass --slug or --all. If --dir contains no agent project or child agents, deploy requires --slug (or a slug derived from the directory name) and an https git repository URL (--repo, or inferred from origin when --dir is an agent project). --all fails when there is no agent project.

The command infers --repo, --ref, and --path from the current Git checkout when possible. Explicit flags take precedence. --repo must use HTTPS. Repeat --cursor-events-repo to select SCM event sources. Repeat --allow-domain to add engine egress domains; these values are combined with hosting.egressDomains from the agent config. Egress domains apply only to repository-backed deployments. Each domain must be a lowercase hostname with at least two labels and an alphabetic top-level domain. One leading *. wildcard is allowed. A deployment can declare at most 20 domains.

By default, the command polls every three seconds for up to ten minutes and succeeds only when the deployment reaches running. --no-wait returns after the deployment request is accepted. Multi-agent deploys run sequentially. When several agents are selected, --path is ignored and each project infers its own path. A single-target --json run prints one object; a multi-target run prints an array.

The first deployment can return an alias token. It appears once in text or JSON output and can't be retrieved later. Store it as a secret. Send it as X-Agent-Alias-Token when calling the stable alias URL, or use it to sign in to the hosted playground.

See Deployment for the hosting security model and state layout.

deployments

deployments lists the selected team's deployments.

bash
agent-sdk deployments [--team <id>] [--json]

Text output shows each slug, status, generation, deployment kind, and update time. --json prints { deployments }.

deployment

deployment prints the full status of one deployment.

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

Text output includes status, generation, kind, alias, source, egress domains, secret names, engine state, and the last error when present. --json returns the full API response. It can include short-lived engineAccess.headers, so handle JSON output as a credential.

stop

stop shuts down a deployment.

bash
agent-sdk stop <slug> [--team <id>] [--no-wait] [--json]

The command polls for up to ten minutes until the status reaches stopped. --no-wait returns after the stop request is accepted.

rotate-token

rotate-token replaces the alias token used by callers and the hosted playground.

bash
agent-sdk rotate-token <slug> [--team <id>] [--json]

The old token stops working immediately. The replacement is shown once. --json prints { aliasToken }.

rotate-pod-credential

rotate-pod-credential replaces the credential used by the running engine pod.

bash
agent-sdk rotate-pod-credential <slug> [--team <id>] [--json]

The command prints only the masked key (--json prints { podCredentialMaskedKey }). The running pod keeps the old credential until the next deploy, so nothing breaks in between. Run agent-sdk deploy --slug <slug> to inject the replacement and retire the old credential.

mcp

mcp proxies an agent's MCP endpoint over stdio for MCP clients that spawn local servers, such as Cursor.

bash
agent-sdk mcp --prod [--slug <slug>] [--team <id>]
agent-sdk mcp --url <baseUrl> [--bearer-token <token>]
agent-sdk mcp install [--prod | --url <baseUrl>] [--name <serverName>]
                     [--print] [--json] [--remote]

The bare command reads newline-delimited JSON-RPC on stdin and forwards one POST per message to <target>/v1/mcp. It requires --prod or --url. With --prod, it resolves the hosted deployment through the signed-in Cursor account and re-mints short-lived engine credentials as they expire, so no durable secret lands in a config file. stdout is reserved for the MCP wire; logging goes to stderr.

mcp install writes the matching entry into ~/.cursor/mcp.json so the agent shows up as an MCP server in Cursor. --name overrides the server name (the default is the slug, or a name derived from --url). --print prints the entry instead of writing the file, and --json prints a machine-readable result. --remote (with --prod) writes a remote HTTP entry pointing at the stable Cursor MCP gateway instead of the local stdio proxy, for MCP hosts that can't spawn stdio servers. The remote entry carries your API key in plain text, so treat the file as a credential.

mcp oauth

mcp oauth authorizes a defineConnection({ url, oauth: true }) or defineConnection({ cursorAccount: true }) connection.

URL connections run a browser PKCE flow. Tokens are written to mcp-auth.json under the agent-serve config dir (default ~/.config/agent-serve). Pass --store to upsert matching MCP_OAUTH_<CONNECTION>_* secrets on the hosted deployment.

Cursor-account connections authorize the hosted deployment's service account through the Cursor backend's connector consent flow. Those tokens live on the Cursor backend, so --store isn't needed; the command prints a note when you pass it anyway.

bash
agent-sdk mcp oauth <connection> [--dir .] [--store] [--slug <slug>] [--team <id>]

<connection> is the agent/mcp-connections/<connection>.ts basename. --slug defaults to the --dir basename. --team defaults to the signed-in account's team. You need agent-sdk login (or --api-key) before --store.

Secret names are MCP_OAUTH_<NAME>_ACCESS_TOKEN, _REFRESH_TOKEN, and _CLIENT_ID (<NAME> is the connection id in upper snake case). Declare them in hosting.secretNames so deploy validation expects them. Secrets apply on the next deploy.

Tokens are bound to the connection's resource URL. Changing the URL invalidates the local entry; run mcp oauth again.

See the Host MCP OAuth guide.

secrets

secrets manages environment secrets for a deployment.

bash
agent-sdk secrets set <slug> NAME [NAME2 ...] [--team <id>] [--json]
agent-sdk secrets list <slug> [--team <id>] [--json]
agent-sdk secrets unset <slug> NAME [--team <id>] [--json]

Pass names only. On a TTY, secrets set prompts for each value with hidden input (nothing echoes). When stdin is piped, provide one line per name. Values never print on stdout.

Do not put values on the command line. NAME=VALUE in argv shows up in shell history and in agent-captured terminals. The CLI refuses that form unless you pass --from-argv (still warns). Prefer a file redirect when a human is not at the prompt:

bash
agent-sdk secrets set weather-agent WEATHER_API_KEY < ./weather-api-key.txt

Secret names use UPPER_SNAKE_CASE, start with a letter, and contain at most 64 characters. Names beginning with CURSOR_ are reserved. Values can contain at most 4096 bytes, and one deployment can hold 32 secrets.

secrets list returns names and creation times, never values. Secret changes reach the engine on its next deploy. secrets set upserts the named secrets without deleting others.

JSON output is { secretNames } for set, { secrets } for list, and { removed } for unset.

slack

The slack pack provisions, generates, and checks Socket Mode channel setup.

bash
agent-sdk slack setup
agent-sdk slack create [--dir <path>] [--name <name>] [--prod]
                      [--slack-team <T…>] [--team <id>]
                      [--icon <https-url-or-file>]
                      [--prefix <prefix> | --no-prefix] [--json]
agent-sdk slack destroy [--dir <path>] [--prod] [--slack-team <T…>]
                       [--team <id>] [--json]
agent-sdk slack icon <https-url-or-file> [--dir <path>] [--prod]
                    [--slack-team <T…>] [--team <id>] [--json]
agent-sdk slack init --manual [--dir <path>] [--name <name>]
                    [--prefix <prefix> | --no-prefix] [--channel-posts]
agent-sdk slack manifest [--dir <path>] [--name <name>]
                    [--env dev|prod|both] [--channel-posts] [--print]
agent-sdk slack doctor [--dir <path>] [--prefix <prefix> | --no-prefix] [--json]

slack setup prints the two-product chooser plus the --manual setup checklist. It doesn't change files.

slack create opens the signed-in Cursor dashboard wizard. Finish Slack consent and the bot name there. The CLI writes the token pair into <dir>/.env.local and runs doctor. It requires a signed-in host (agent-sdk login or CURSOR_API_KEY). --prod provisions the production app; the default is the development app. --name / --icon / --channel-posts prefill the wizard. A second create for the same slug and env overwrites the live Slack app. If Slack needs a workspace admin's approval, the wizard waits; keep the CLI running, open Slack's Request approval page (the CLI prints the link), and click Retry after the admin approves. Token values never print.

slack destroy deletes the provisioned app for the selected environment. Tokens already written to .env.local stay in place and stop working.

slack icon sets the provisioned app's icon from an https image URL or a local png, jpg, or gif file of at most 512KB.

slack init without --manual exits non-zero and writes no files. Use slack create for the dashboard wizard. slack init --manual writes the channel file, development and production manifests, env.example, and setup status under the project. You paste those manifests at api.slack.com. The command refuses to overwrite a target file. If a collision occurs, it exits non-zero; files created earlier in the run remain. The token prefix defaults to the directory basename normalized to uppercase snake case. Explicit --prefix values use the same normalization. For example, pr-approver becomes PR_APPROVER_SLACK_BOT_TOKEN. --no-prefix uses shared SLACK_BOT_TOKEN and SLACK_APP_TOKEN. --channel-posts subscribes the manifests to channel-post events. The command always prints a JSON summary.

slack manifest regenerates selected manifest files. --env defaults to both, and --name defaults to the directory name. --print writes the manifest JSON to stdout instead of changing files. With the default --env both, it prints development JSON, a --- prod --- separator, then production JSON.

slack doctor checks both tokens, Socket Mode connectivity, and Slack's auth.test. It exits non-zero when any check fails.

See the Slack guide.

github

The github pack discovers githubChannel() definitions and sends live or synthesized deliveries to them.

bash
agent-sdk github doctor [--install] [--json]
agent-sdk github events [--dir <path>] [--host <host>] [--port <n>] [--json]
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|owner/repo#N> --dir .
    [--events a,b,c|'*'] [--action <action>] [--conclusion <result>]
    [--comment <body>] [--context <name>] [--slug <slug>] [--channel <id>]
    [--host <host>] [--port <n>] [--url <url>] [--secret <secret>]
    [--dry-run] [--out <dir>] [--json]

github events prints each discovered channel's delivery URL and event set. When it finds no channels, it returns an empty result and exits successfully.

github forward wraps gh webhook forward. It infers the repository from the Git remote when you omit --repo and --org. URLs and events come from the discovered channels; --events overrides the event set. Use --slug or --channel to narrow discovery when several channels match. Otherwise, one local proxy fans deliveries out to every match. --url targets one channel. For forward, pass --events when no matched channel can supply the event set.

Repository forwarding needs repo-admin access. Organization forwarding needs org-owner access. The relay authenticates with the GitHub CLI's stored login. A GITHUB_TOKEN or GH_TOKEN environment override can make delivery requests return 401, even when hook creation succeeds. Unset those variables before forwarding.

Pass --secret or set GITHUB_WEBHOOK_SECRET to sign deliveries. serve --dev accepts unsigned loopback deliveries. A non-dev target requires the same secret on both sides.

github replay needs read access, not admin access. It reads the pull request through gh api, builds GitHub webhook payloads, and posts them to the selected channels. Supported events are pull_request, issue_comment, pull_request_review_comment, check_run, check_suite, workflow_run, and status. The default is pull_request with action synchronize. Comment events need --comment.

Use --events '*' to replay every supported event declared by the channel. --dry-run prints payloads without posting them. --out writes fixture files but still posts unless you also pass --dry-run.

github doctor checks gh, its login, and the pinned cli/gh-webhook extension. --install installs or repairs the extension. An environment-token override is a warning and doesn't make github doctor fail.

See the GitHub guide.

Environment variables

These environment variables affect the CLI and its channel packs.

VariableMeaning
CURSOR_API_KEYCursor credential. It takes precedence over the stored login.
CURSOR_API_BASE_URLBackend used by login, account, deployment, and event-relay RPCs in non-production environments.
CURSOR_BACKEND_URLBackend used by the Cursor SDK harness in non-production environments.
AGENT_SERVE_CONFIG_DIRDirectory for stored credentials and update-check state. The default is ~/.config/agent-serve.
AGENT_SERVE_NO_UPDATE_CHECK / NO_UPDATE_NOTIFIERDisable the automatic published-version check when set to a non-empty value other than 0.
CIDisable the automatic published-version check when set.
GITHUB_WEBHOOK_SECRETDefault signing secret for GitHub forwarding and replay.
GITHUB_APP_ID / GITHUB_APP_PRIVATE_KEY / GITHUB_APP_INSTALLATION_IDGitHub App authentication for outbound API calls.
GITHUB_TOKEN / GH_TOKENToken authentication for outbound API calls. Unset both for github forward.
SLACK_BOT_TOKEN / SLACK_APP_TOKENSlack tokens for one agent. Use <PREFIX>_SLACK_BOT_TOKEN and <PREFIX>_SLACK_APP_TOKEN for each agent on a multi-agent host.

What's next