@kentcdodds/cursor
Cursor API SDK for cloud agents, runs, artifacts, workers, models, repositories, and raw requests.
AGENTS.md
203 lines · 6.7 KB · Markdown@kentcdodds/cursor — agent notes
Human setup and intent live in README.md. This file is for
agents: imports, smoke checks, snippets, and edge cases. Secrets by name
only — never paste key values. Do not disable live webhooks or jobs.
Secrets
| Name | Scope | Required | Notes |
|---|---|---|---|
cursorApiKey | user | Yes | Raw key from cursor.com/dashboard → API Keys |
githubPersonalAccessToken | user | No | Only for agentsWithOpenGithubPrs |
Host: api.cursor.com. Placeholder: {{secret:cursorApiKey}}.
Import paths
| Export | Import |
|---|---|
| overview | kody:@kentcdodds/cursor |
request (cursorRequest) | kody:@kentcdodds/cursor/request |
| agents | kody:@kentcdodds/cursor/agents |
| runs | kody:@kentcdodds/cursor/runs |
| artifacts | kody:@kentcdodds/cursor/artifacts |
| workers | kody:@kentcdodds/cursor/workers |
| models | kody:@kentcdodds/cursor/models |
| repositories | kody:@kentcdodds/cursor/repositories |
me (apiKeyInfo) | kody:@kentcdodds/cursor/me |
agent-usage (getAgentUsage) | kody:@kentcdodds/cursor/agent-usage |
Prefer static kody:@kentcdodds/cursor/... imports from execute. Do not lead
with packages.invoke.
Defaults: ./request → cursorRequest; ./agents → listAgents; ./runs →
listRuns; ./artifacts → listArtifacts; ./workers → getFleetSummary;
./models → listModels; ./repositories → listRepositories; ./me →
apiKeyInfo; ./agent-usage → getAgentUsage.
Smoke test (read-only)
import { apiKeyInfo } from 'kody:@kentcdodds/cursor/me'
export default async function main() {
return await apiKeyInfo()
// => { apiKeyName, userEmail, ... }
}Optional read-only follow-ups: listModels() from ./models, or
listAgents({ limit: 5 }) from ./agents.
Hand a file to a Cursor cloud agent
Prefer @kentcdodds/agent-files as the durable handoff pipe. Mint a short-lived
R2 PUT URL with a tiny MCP execute call, PUT the bytes outside MCP (curl/fetch),
then put downloadUrl in the cloud agent prompt so it can curl/download on the VM.
Do not rely on CloudAgent / chat image attachments for usable bytes on the VM —
prompt.images is vision-only. Dropbox is an optional secondary when the file should
live in Dropbox; agent-files is the default for agent↔agent binary handoffs.
1) Mint upload target (execute)
import createUpload from 'kody:@kentcdodds/agent-files/create-upload'
export default async function main() {
return await createUpload({
filename: 'report.png',
contentType: 'image/png',
confirm: true,
})
// => { key, upload: { method, url, headers }, downloadUrl, expiresAt }
}2) PUT bytes (outside MCP)
# Use every header from upload.headers; body is the raw file.
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: image/png" \
# plus remaining keys from target.upload.headers \
--data-binary @./report.pngOr in one shot after minting:
const target = await createUpload({ filename: 'report.png', contentType: 'image/png', confirm: true })
await fetch(target.upload.url, {
method: 'PUT',
headers: target.upload.headers,
body: fileBytes, // ArrayBuffer / Blob / Uint8Array
})
// hand target.downloadUrl to createAgent / createRun3) Include downloadUrl in createAgent / createRun prompt
import createUpload from 'kody:@kentcdodds/agent-files/create-upload'
import { createAgent } from 'kody:@kentcdodds/cursor/agents'
import { createRun } from 'kody:@kentcdodds/cursor/runs'
export default async function main() {
const target = await createUpload({
filename: 'fixture.zip',
contentType: 'application/zip',
confirm: true,
})
// PUT fileBytes to target.upload.url with target.upload.headers first…
const { agent } = await createAgent({
prompt: {
text: [
'Download the fixture and unzip it into ./fixtures before editing.',
`curl -fsSL '${target.downloadUrl}' -o /tmp/fixture.zip`,
'unzip -o /tmp/fixture.zip -d ./fixtures',
].join('\n'),
// images: [...] // vision-only; not a byte handoff
},
repository: 'https://github.com/your-org/your-repo',
ref: 'main',
})
const { run } = await createRun({
agentId: agent.id,
prompt: `Also fetch the same fixture again if needed: ${target.downloadUrl}`,
})
return { agentId: agent.id, runId: run.id, downloadUrl: target.downloadUrl }
}Common snippets
Create agent + follow-up run:
import { createAgent } from 'kody:@kentcdodds/cursor/agents'
import { createRun } from 'kody:@kentcdodds/cursor/runs'
export default async function main() {
const { agent } = await createAgent({
prompt: 'Add a README with setup instructions',
repository: 'https://github.com/your-org/your-repo',
ref: 'main',
})
const { run } = await createRun({
agentId: agent.id,
prompt: 'Also add a troubleshooting section',
})
return { agentId: agent.id, runId: run.id }
}Billed usage (do not estimate dollars from token counts):
import { getAgentUsage } from 'kody:@kentcdodds/cursor/agent-usage'
export default async function main() {
return await getAgentUsage({ agentId: 'bc-…' })
// cost.rawUsd / cost.chargedUsd from API cost record; chargedCents === 0 → plan-included
}Raw escape hatch:
import { cursorRequest } from 'kody:@kentcdodds/cursor/request'
export default async function main() {
return await cursorRequest({ path: '/v1/models' })
}Pull requests
createAgentalways enables ManagePullRequest tools. If you create via rawcursorRequest, sendautoCreatePR: trueso those tools are available.- When the cloud agent's task results in code changes, the agent itself must push its branch and create/update the PR via Cursor Cloud's ManagePullRequest before finishing. Do not have Kody, a Kody workflow, or Kody's GitHub integration open the PR as a substitute.
- The PR must be authored by the Kent C. Dodds Cursor/GitHub account so the standard AI reviewer is triggered.
- Include this PR-authorship requirement explicitly in every agent creation prompt when spawning via this package.
Edge cases
- Prefer this package to launch Cursor Cloud agents. Unless the user requests
another model, resolve the current latest Grok id with
listModels— do not default to Fable or GPT. listRepositoriesis rate-limited (about 1/min, 30/hour) and may be slow.- Workers (
./workers) need a pool service-account key path Cursor exposes; ordinary Cloud Agent flows do not. - Enterprise Admin / Analytics / AI-Code-Tracking / Bugbot: use
./request, not typed helpers. - Never paste
cursorApiKeyor GitHub token values into chat or logs. - File handoffs: use
@kentcdodds/agent-filescreateUpload→ PUT → putdownloadUrlin prompt text. Do not treatprompt.imagesas VM bytes.