Skip to main content
Capy’s security model starts from one assumption: the agent running on a machine can be manipulated by whatever it reads (a malicious repo, a poisoned web page, a crafted issue). So the design treats the machine as untrusted, and puts nothing durable on it worth stealing.

One machine per thread

Every thread runs on its own isolated Ubuntu 24.04 VM, and every task subagent that writes gets its own. Machines never share state across organizations or users. Machines sleep when idle: the filesystem is persisted to disk and the VM is freed, so nothing keeps running and nothing keeps billing. Waking resumes from disk: memory, processes, and connections don’t survive, but your files do. A machine left asleep for 2 days moves to colder storage (still resumable); at 30 idle days it’s deleted for good.

GitHub credentials never land on the machine

No reusable GitHub credential (user token, installation token, or app key) ever sits on a machine, at rest or in memory. The agent still does ordinary git and gh work; the credentials live elsewhere. The only credential on the machine is a short-lived signed grant that’s useless against GitHub: it only authenticates to Capy’s git proxy. The proxy verifies the grant, attaches a GitHub installation token on Capy’s side per operation, and streams the bytes through. Grants are pushed to the machine by Capy’s control plane and die on their TTL: even if one is copied off the machine, the copy expires on the same clock, and an asleep machine’s grant just expires at rest. Identity still works the way you configured it. Commit author and PR author follow your GitHub connection whether the agent uses the product’s PR flow or plain gh pr create. Disconnecting your GitHub account in settings stops its use immediately and revokes the token at GitHub. The proxy does credential isolation and nothing else: it doesn’t rewrite commands or gate refs. Branch rules are GitHub branch protection, where they belong.

Secret values stay sealed

Environment variables you configure for a project are customer data, encrypted under a dedicated KMS boundary. Each value is sealed to its exact project, scope, and name, so ciphertext moved anywhere else won’t open. Values are decrypted only to write an env file on an authorized machine during setup: mode 0600, outside the repository tree, excluded from diffs and snapshots, never placed in command arguments. The agent sees names and configured status only; Capy itself never surfaces a value in prompts, list APIs, logs, events, or error text. But a value written to the machine is part of the environment there, so a command the agent runs can print it, and that output enters the transcript like any other output. The secrets page states this threat model plainly. The single place a value can be read back is an authorized human session in the app, one name at a time; there is no bulk value read anywhere. Values you hand to a single running thread through the composer are narrower still: write-only, with no reveal endpoint at all.

Capy never merges on its own

Capy never merges a PR or enables auto-merge unless you explicitly ask for that specific merge in the current conversation. The rule covers every branch and every path: gh pr merge, merge API calls, and auto-merge enablement alike. This is one of three rules with no override: no merging without an explicit ask, no exposing or committing secrets, no fabricating results. Your AGENTS.md files and project rules can reshape everything else about how Capy works; they can’t relax these.

Data handling

Your code is processed only to serve your requests; Capy does not train models on your code. Conversation history and thread state are stored encrypted on Capy’s backend, and machine filesystems follow the retention lifecycle above: colder storage after 2 idle days, deletion at 30. For enterprise compliance requirements, contact us.