Skip to content

Turn features on and off

Add one config.yaml block and its env vars, restart, and that capability's commands, dashboard section and Worker appear together.

You need: config.yaml, its environment, and a way to make a change live (restart; on Cloudflare deploy config then deploy restart, see Operate production).

Pick a shape

Copy the nearest fixture from src/core/testing/capabilityFixtures.ts.

ShapeWhat is onStart here
minimalSlack and one provider; tools on the bot host; dashboardAuth: none (loopback only)Run it locally
local-fullminimal + in-process memory, run history on disk, GH_TOKEN, an mcp block, one ingress bearer, a local docs URL. No Workers, so no residents, costs, schedules or ledgerAdd blocks to minimal (Configuration)
cloud-fullFour Workers: sandbox execution, residents, durable memory, run history, ledger, MCP, costs, schedules, GitHub App, ingress, AccessDeploy, then Operate production

Add the block

CapabilityTurn it onOnOffCost
executionexecution.type: local (default) · e2b + E2B_API_KEY · cloudflare + execution.url + SANDBOX_TOKENWhere bash runs. cloudflare: one sandbox container per thread; local: the bot hostNothing hidden. local lets anyone who reaches the coding agent run commands on the host (Execution and trust)cloudflare: the sandbox Worker (deploy/cloudflare-sandbox/), billed per running instance; e2b: an E2B account
residentsexecution.resident.baseUrl + RESIDENT_OPERATOR_TOKEN (runs) + RESIDENT_ADMIN_TOKEN (repo …)repo commands; Residents section and /residents; a warm environment per onboarded repository (Onboard a repo)Every request clones cold into a per-thread workspaceThe resident Worker (deploy/cloudflare-resident/): one Durable Object and one container per repository, an R2 bucket. The most expensive capability
memorymemory.enabled: true; durable with memory.worker.baseUrl + MEMORY_TOKENmemory commands; background-memory block on every turn; reflection pass after a runModel input byte-identical to a build without memoryLaptop: nothing (in-process, lost on restart); durable: the state Worker (deploy/cloudflare-memory/)
runHistoryrunHistory.store: file, or runHistory.worker.baseUrl + MEMORY_TOKENFinished runs stay on /runs?all=1, runs get and runs events for retentionDays; friction report has runs to readFinished runs evicted about a minute after they endfile: host disk under data/runs/ (ephemeral on Cloudflare Containers); worker: the state Worker's RunHistoryDO
runLedgerRun history on the state Worker (worker, not file)A live run survives a bot restart; a follow-up steers into it; /runs lists every bot generationA restart mid-run loses the run; its card closes as interruptedIncluded in the state Worker
mcpAn mcp block (credentialKeyEnv, default MCP_CREDENTIAL_KEY, 32 bytes base64)mcp commands; mcp__<server>__<tool> tools on runs; the one-time connect page (Connect an MCP server)No external tools; mcpServers entries never connectLocal: sealed credentials in data/mcp-secrets.json; with runtimeOverrides.worker: the state Worker
costsA costs block + CF_ANALYTICS_TOKEN (Account Analytics: Read); optional ANTHROPIC_ADMIN_KEYCosts section, /costs, /costs/<group>.json (Check spend)/costs answers 503Read-only API tokens; nothing stored
schedulesschedules.worker.baseUrl + MEMORY_TOKEN; the cron identity in SWITCHBOARD_INGRESS_TOKENS with a grants.http:cron entryFiring history on the Scheduled tab and in schedule listSchedules listed, no firing historyThe state Worker's ScheduleDO; the bot Worker's cron triggers
githubGITHUB_APP_ID + GITHUB_APP_PRIVATE_KEY + GITHUB_APP_INSTALLATION_ID, or a personal GH_TOKENgithub_* tools; the coding agent's push and PR; friction propose files issuesAgents answer from the conversation and the web; no PRsA GitHub App (recommended: scoped, rotates) or one personal token
ingressSWITCHBOARD_INGRESS_TOKENS: JSON map bearer → { subject, channel? }, each subject granted in grants.http:<subject> / mcp:<subject>POST /ingress and the MCP server at /mcpBoth routes refuse every bearerNothing
readingDiffAbridgeThe meat binary on the bot host's PATH (the bot image ships it) + the Anthropic provider's key + review.readingDiff.provider not off (see below)review abridge; with provider: meat an abridged diff on every reviewReviews record the full diff only; no review abridge anywhereOne Opus-class call per abridged review
dashboardAuthdashboard.auth; default access when ACCESS_TEAM_DOMAIN + ACCESS_AUD are set, else none. token needs dashboard.token.actor and DASHBOARD_TOKEN (or the env var dashboard.token.env names)access: anyone your Access policy admits, service tokens for machines. token: dashboards and /api/* for the bearer as one actor. none: loopback callers onlynone refuses every remote caller; an explicit none on a public PUBLIC_BASE_URL refuses to startCloudflare Access (free tier covers small teams); token and none: nothing

Abridged reading diffs (meat)

Every PR review already records its full git diff. review abridge <run id> (chat, CLI, POST /api/review.abridge; needs review:write) adds meat.dev's abridged version — run on the bot host over the complete diff GitHub serves for the PR, with the bot's own Anthropic key — and stores it on the run; ask again and the stored one is answered. To have it happen on every review, set:

yaml
review:
  readingDiff:
    provider: meat # git (default): on demand only · off: no reading diff at all
    meatModel: claude-opus-5 # the default; an Opus-class model is the floor that actually abridges
    meatTimeoutS: 240

Cost: one Opus-class call per review (meat caches by model + diff, so a repeat is free). It never delays the review: the abridging runs after the record is written, and a restart mid-run simply leaves the run to be abridged on demand. Needs runHistory (the record it is appended to) and the GitHub App or GH_TOKEN (the compare diff; a whole recorded diff is the fallback). SWITCHBOARD_READING_DIFF=git|meat|off overrides provider on a deployed bot.

memory.worker, runHistory.worker, schedules.worker and runtimeOverrides.worker all name the state Worker, same MEMORY_TOKEN; deploy it once.

Check which commands you turned on

A command under two capabilities is on when either gives it a backend.

CapabilityCommands that depend on it
executionrepo test, repo build
residentsrepo list, repo onboard, repo offboard, repo reconfigure, repo rebuild, repo test, repo build
memorymemory list, memory forget
runHistoryreview abridge, friction report, friction propose
runLedger
mcpmcp list, mcp add, mcp connect, mcp show, mcp remove
costs
schedulesschedule list
github
ingress
readingDiffAbridgereview abridge
dashboardAuth

The other 21 commands are on in every installation.

Restart and confirm

You should see, in the startup log:

[capabilities] {"execution":"local","residents":false,…}

A missing env var fails fast, by name; if a command is missing from help, this says why.

Next