Development record
The agents abcd launches on its own work inside a sandbox the operating system enforces
Typed links: builds_on itd-2609091014076309 (the worktree store, which gives every launched agent the separate checkout this sandbox confines it to); related_intents itd-148 (the read-only primary checkout, the same isolation enforced on sessions rather than on launched agents) and itd-2609221017023290 (the credential store, whose keychain home a sandboxed launch must still reach); related_adrs adr-2610161621415708 (the proposed rule this intent enacts), adr-42 (the guard is a mistake filter, and a boundary needs an execution-layer control) and adr-2609091248200336 (machine-scoped scratch, where the worktrees this sandbox opens live). Related issues, named here rather than in related_issues because none of them is promoted into this intent: iss-2610161612203555 (restores abcd's guard to each launch; this intent depends on it, see Open Questions), and iss-2608230847432285 with iss-213 (worktrees alone did not isolate sessions; itd-148 carries both).
Press Release
When you leave abcd working through the night, the agents it starts on its own can change their own work and nothing else on your computer. Each agent abcd launches runs inside a fence your computer's operating system enforces, not only abcd's own checks. The agent can edit the copy of the project it was given and the notes abcd keeps for that piece of work. It cannot change your other projects, your settings, or the choices you made about how abcd runs, and it cannot read your passwords, keys and sign-ins. On a computer that cannot put up the fence, abcd says so before the first agent starts, so you never find out in the morning.
"I used to leave a run going and wonder over breakfast what else it had touched," said Maya, an autonomous-development practitioner. "Now the agents abcd starts can only change the work they were given. The one night my laptop couldn't fence them in, abcd told me before it began, and the choice was mine."
Why This Matters
abcd now starts agents that nobody watches. When a person routes a role to a runner on their own machine, abcd launches that agent itself, without a terminal, with its tools granted up front because no one is there to answer a prompt. Two things stand between such an agent and the rest of the computer today: the list of tools it was granted, and abcd's command guard. Neither confines what an allowed tool touches. The guard is a mistake filter, not a boundary: adr-42 decided so, and the guard's chapter of the brief says that anything needing an enforced boundary needs a control at the execution layer, "a sandbox, a permission system, a restricted shell", with the guard in front of it to teach. Both recorded the principle; no record enacted it. And a launched agent currently carries no guard at all, because the launch loads no hooks (iss-2610161612203555 restores it).
The vendors whose agents abcd sits beside draw the same line, as the research note of 2026-08-18 on the guard's parse-layer limits records. Claude Code documents its command patterns as steering and says its sandbox holds even when a prompt injection gets past the model; Codex keeps an OS-enforced sandbox mode apart from the approval policy layered on top; GitHub Copilot's coding agent runs in a throwaway, firewalled environment rather than behind a command list. Cursor's history shows why the line matters: its command denylist, and then the allowlist that replaced it, were both bypassed. Claude Code's own guide to sandbox environments is blunter for the unattended case: a run without permission prompts belongs inside a container, a virtual machine or a whole-process sandbox, and its shell-only sandbox "is not sufficient for fully unattended runs".
The product thinker named sandboxing these runs an important feature on 2026-10-16. The decision recorded earlier that day, dcn-2610161612269647, says abcd "does not sandbox"; dcn-2610161619296615 corrected it, because the question that day had dropped the sandbox option to fit the screen and no ruling was made on it.
What this intent can honestly promise is bounded by where abcd starts processes. abcd launches a process only for a role the person routed to a runner, through one launch point in its runner. The drains and builds a person's own session drives run on that session, under the host's settings, and abcd never edits those settings, so for them abcd can detect and report how isolated the run is but cannot fence it. The network is a separate question: limiting it to a list of hosts narrows mistakes but does not stop code being sent elsewhere, so it is proposed as its own later part (Open Questions 1 and 3).
Mechanism
We expect the fence to stop an agent abcd launches from changing anything outside its own work, because the operating system enforces it below anything the agent, or a command the agent runs, can change; abcd's guard still steers the agent inside it. It would be shown wrong if a launched agent, with the fence on, changed a file outside the paths its run was given. (Facilitator-proposed, 2026-10-16.)
Scope Conditions
- macOS and Linux; Windows is out.
- Agents abcd's runner launches, not a session the person drives.
- Local runs on the person's own computer, not cloud sessions.
- One project per run.
- The operating system's fence can start: on Linux, unprivileged user namespaces are not blocked.
- The machine-load gate and every check that reads the whole machine run in abcd, outside the fence.
Acceptance Criteria
Seeded by the facilitator on 2026-10-16; proposals until the product thinker confirms them.
- Given a run whose agent abcd launches through its runner, when the agent tries to write a file outside its worktree and its run's receipt folder, then the operating system refuses the write and the run records the refusal.
- Given the same agent, when it edits files in its own worktree and commits there, then the edit and the commit succeed, and so does pushing its branch to origin.
- Given a launched agent, when it tries to change the person's abcd settings, rules, trusted roots or another project's worktree under
~/.abcd.noindex/, then the write is refused. - Given a computer on which the fence cannot start, when a run is about to launch its first agent, then abcd refuses to start the run, names the reason and how the person may turn the fence off for their own computer, and launches nothing.
- Given a person who has turned the fence off for their computer in their user layer, when a run starts, then abcd says once that its launches are unfenced, and a project's own files can never turn the fence off.
- Given a fenced run, when its lane builds and tests the project, then it uses a fresh Go build cache of its own and leaves the person's caches unchanged.
- Given a fenced run on a loaded machine, when abcd's load gate decides whether a preflight may start, then the gate reads the whole machine from outside the fence and is not misled by the fence's own view.
- Given abcd's guard is active in a launched agent, when the agent runs a command the guard refuses, then the refusal and its advice reach the agent inside the fence as they do outside.
- Given a fenced run, when it finishes, then the person's host settings are byte-identical to before the run.
SOTA
Surveyed on 2026-10-23; sources, evidence tiers and the local fit risks are in the security-isolation SOTA note. This is half of the check decision 6 asked planning to make first: it weighs srt against a microVM, native profiles and the host's Bash sandbox, not against the other open-source fences, and not on a non-Claude launch (Codex, opencode); the other half is finished at the fit-challenge before the build.
- Anthropic's sandbox-runtime (
srt) meets the ADR's policy by configuration. Writes are allow-only, reads deny-then-allow, network denied until a domain is listed; it wraps any command; Seatbelt on macOS, bubblewrap plus a seccomp filter on Linux; Apache-2.0, "Beta Research Preview", installed with npm (sandbox-runtime README). - It denies the paths the ADR names on its own:
.git/hooks,.git/config,.mcp.json,.claude/commands,.claude/agentsand shell start-up files, even inside an allowed write path (Claude Code sandbox environments). - On Linux the deny list is built once at launch and "does not cover anything the session creates later, such as
git init,git clone, or scaffolding"; on macOS the denies are checked at write time. The run must create every worktree before the fence goes up (same page). - Whole-process is the vendor's own bar for unattended runs: the shell-only sandbox "is not sufficient for fully unattended runs"; a run without prompts belongs "inside a container, a VM, or the sandbox runtime" (same page).
- Every comparable harness uses the same primitives: Codex is "an OS-enforced sandbox", Seatbelt on macOS and bubblewrap on Linux; Gemini CLI uses
sandbox-execprofiles or a container (Codex sandboxing; Gemini CLI sandbox). sandbox-execis deprecated in its man page ("Thesandbox-execcommand is DEPRECATED") and relied on by all three vendors; no Apple removal statement was found (sandbox-exec(1)).- Linux prerequisites are the ADR's scope condition: Ubuntu 24.04's default AppArmor policy blocks bubblewrap's user namespaces, fixed by a
bwrapprofile; Landlock is the kernel's unprivileged alternative, with a Go binding that would be a Go dependency and covers Linux only (Claude Code sandboxing; Landlock; go-landlock). - Inside the fence, unix sockets are blocked by default, so a push over SSH needs the agent socket allowed (by path on macOS, wholesale on Linux) or HTTPS through the credential store (README).
- Detection is a probe, not a config read: the host's own check is a write outside the allowed paths failing with "Operation not permitted" or "Read-only file system" (Claude Code sandboxing).
- A microVM (Docker Sandboxes) is the stronger, heavier alternative, with its own egress proxy and credential sentinel, at the cost of a Docker dependency (Docker Sandboxes architecture).
Path 1: adopt sandbox-runtime as the first fence behind the internal/core/fence seam, its policy generated per launch as an srt settings file. It is a new runtime dependency (Node and npm; ripgrep on macOS and Linux by the README's requirements list, though the harness's own page says no extra package on macOS; bubblewrap and socat on Linux) and the adr-22 exception the ADR proposes, so it needs explicit sign-off. The independent fit-challenge is still owed before the build, and the questions below are kept for it.
Questions this pass raised for the fit-challenge before the build. They are kept here, not under Open Questions, so they do not hold a build the record already rules ready:
- On Linux the mandatory deny list is built at launch, so a worktree or clone the agent creates afterwards sits outside it: does the run forbid creating worktrees inside the fence, or rebuild the fence around them?
- Which route a fenced push takes: the
ssh-agentsocket allowed by path, or HTTPS through the credential store the fence must still reach.
Open Questions
None open. Each question the two reviews raised is settled in Decisions 1 to 8. How opencode launches are fenced is left to the spec, under decision 6.
Decisions
Ruled by the product thinker on 2026-10-16, in the planning interview:
- Split into three parts. (A) The agents abcd's runner launches run inside a sandbox the operating system enforces; this record carries part A. (B) Drains and builds the person's own session drives report how isolated they are, since abcd never changes the person's host settings and cannot fence that session. (C) Limiting which hosts a run may reach is a later, separate feature. Parts B and C are filed as their own drafts before planning goes on.
- Kept apart from the worktree store, building on it. The store (itd-2609091014076309) says where a launched agent's copy lives; this record says what the agent may reach from it. This one waits for the store to ship.
- The fence refines the read-only primary checkout (itd-148) for launched agents. itd-148 states the rule, that the main copy of the files is not edited outside a declared coordinator, and its check guides every session; this record is that rule's enforcing half for the agents abcd launches, so a change to the rule changes both.
- Who is covered and the network limit are settled by the split (facilitator, recorded without a question). Part A covers only the agents abcd's runner launches; the person's own session is part B's; the network promise belongs to part C. No question was put because ruling 1 leaves one defensible answer for each.
- Planned now, built after its two dependencies (facilitator, recorded without a question). It builds on the worktree store, and the guard reaches each launched agent only once iss-2610161612203555 lands; planning does not wait on either, building does. One defensible answer, so no question was put.
- Which fence (Q8). While abcd launches Claude, through the Claude Code harness or the claude CLI, the fence is Anthropic's own. The product thinker prefers a state-of-the-art open-source fence abcd adopts, and abcd does not build its own, which would be beyond what abcd is. The choice is revisited when abcd supports another harness (Codex, for one), and how opencode launches are fenced today is open. Anthropic's sandbox-runtime is itself open source (Apache-2.0) and wraps any process, so planning checks first whether it already meets the preference for every harness, against the other open-source options, before anything is built.
- A computer that cannot put up the fence (Q9): the run stops until the person acts. The person can turn the fence off for their own computer only, in their user layer under
~/.abcd.noindex/, never in a project. - Go build caches inside the fence (Tech Q1): a fresh cache per run. A run cannot plant anything in the person's later builds, at the cost of cold builds and race runs.
Audit Notes
Empty. Populated by intent-auditor when intent moves to shipped/.
Grounds
- pursued: abcd is starting to run unattended across several accounts at once, and the agents it launches today reach anything the person's account can write; it would be shown wrong if fenced runs broke ordinary work, such as tests, git or the tool's own checks, often enough that people switched the fence off
Frontmatter
| id | itd-2610161621364075 |
|---|---|
| type | intent |
| lifecycle | planned |
| kind | standalone |
| severity | major |
.abcd/development/intents/planned/itd-2610161621364075-a-person-who-leaves-abcd-to-run-on-its.md
open on GitHub ↗ · commit history ↗
References5
- adr-42The guard's parse layer is a mistake filter, not a security boundary — matching is two-tier, and completeness is abandoned as a goalrelated
- adr-2609091248200336A tool never creates directories in user-owned project space; the store's location binds now and its verbs bind when the store shipsrelated
- itd-148Every change starts in its own worktree in abcd's store: the primary checkout is a read-only surface, and abcd blocks mutations there for every session but a declared coordinatorrelated
- itd-2609091014076309Session and agent worktrees live in a machine-scoped store that abcd lists and reclaims, never beside the user's own projectsbuilds on
- itd-2609221017023290abcd keeps every external credential the same wayrelated
Referenced by5
- adr-2610161621415708Unattended runs abcd launches execute inside an OS sandboxrelated
- adr-2610240850193281A human-set autonomy grant permits, separately from the agent-written waiting-on badgerelated
- itd-2609091014076309Session and agent worktrees live in a machine-scoped store that abcd lists and reclaims, never beside the user's own projectsrelated
- itd-2610222215485265abcd drain --drive works through the ledger from a plain terminalrelated
- spc-2610161751056096a-person-who-leaves-abcd-to-run-on-itsimplemented by
mentions14
- adr-22Bundled dependencies become pluggable adapters over a native default
- adr-2610222222326104abcd drives agents with no host session only on the person's own invocation, on the person's own account behind a wall, and hands back what it cannot finish
- dcn-26101616122696472026-10-16 — Agents keep running past the host's permission prompts in two ways (product thinker, 2026-10-16): abcd teaches agents the command forms the host can check (iss-2610161612200864), and, for the agents abcd itself starts without a terminal, abcd answers the prompts per launch with its guard rules (iss-2610161612203555). abcd does not approve commands in interactive sessions, does not sandbox, and never edits the person's host settings.
- dcn-26101616192966152026-10-16 — Correction to dcn-2610161612269647: sandboxing autonomous runs was not declined. The 2026-10-16 question offered only teaching and per-launch approvals, after the sandbox option was dropped to fit the screen, so the product thinker made no ruling on it; it stays open, and the product thinker named it on the same day as an important feature for autonomous runs.
- dcn-26101618092596232026-10-16 — The fence for the agents abcd's runner launches (itd-2610161621364075 part A) is Anthropic's sandbox-runtime (srt, Apache-2.0, npm @anthropic-ai/sandbox-runtime, tested against 0.0.79, which is not an exact pin: an untested version is warned about and a failed trial launch refuses) for both the claude and the opencode runner, on macOS and Linux, run by abcd at its one launch point as srt --settings <per-launch file> -- <harness>, behind a fence seam (internal/core/fence: a fence-neutral Policy and a Fence interface with Check, Wrap and Refusals) whose one adapter, internal/core/fence/srt, runner.sandbox.backend selects with srt as its default. Grounds: ruling 6 names Anthropic's own fence while abcd launches Claude and rules out a fence of abcd's own; srt wraps any process, so one fence and one policy derivation serve both runners (one-canonical-primitive), which settles how opencode launches are fenced; it is the code Claude Code's own sandbox is built on and the vendor's guide names it for a whole-process boundary. Weighed and not picked: nono (Apache-2.0, Seatbelt and Landlock, pre-1.0, not Anthropic's; the first alternative if the srt probes fail), landrun and go-landlock (Linux only, and abcd would write the policy layer), bubblewrap alone (a building block, Linux only), nsjail (Linux only, built for jailing services), firejail (setuid root, CVE-2022-31214), a sandbox-exec profile of abcd's own (a fence of abcd's own, and the command is deprecated), Codex's sandbox (ships inside another vendor's agent; reconsidered when abcd launches Codex). An adversarial fit-challenge kept the pick and changed the design: the main git directory is narrowed to what a lane's commit writes with a ref check after each launch, srt's interpreter and package are admitted as well as its script, srt's placeholders are cleared after a killed launch, opencode's state is seeded rather than shared, and reads of credential stores a launch never needs are denied. srt is a new required program on the runner route and brings a network host list with it, since it refuses '*'; both wait for the product thinker's sign-off before anything is built. An advisor's fit review the same day kept the pick and changed the design again: GOPATH moves into the run's fence folder with the Go caches, since the checksum-database cache lives under it, and the hosts GOPRIVATE and GONOPROXY name join the host list; lane commits are proposed unsigned inside the fence and signed by abcd at land, so no signing key is opened to the agent; automatic gc is sealed off for each launch; the approver is abcd's own executable, admitted as srt is; srt is framed as adr-22's first declared exception, scoped to the runner route, with the per-machine off switch in place of degradation; and the probes now come before the sign-off. Five questions go to the product thinker with the sign-off, listed in spc-2610161751056096.
- dcn-26102220414179342026-10-22 — Anthropic's sandbox (srt) is required for the agents abcd starts on its own (product thinker's ruling of 2026-10-22, spc-2610161751056096 step 2 question a, itd-2610161621364075): every agent the runner launches runs inside srt, on macOS and Linux, and on a machine without it no such agent starts; this is adr-22's first declared exception, scoped to the runner route alone, and the per-machine off switch runner.sandbox.off stays the person's way out. The proposed marks on adr-22's consequence and on the dependencies chapter's paragraph come off
- dcn-26102220414340562026-10-22 — The sandbox intent's promise is narrowed to what holds (product thinker's ruling of 2026-10-22, spc-2610161751056096 step 2 question e, itd-2610161621364075): a fenced agent changes nothing outside its own work, and cannot read the person's passwords, keys and sign-ins (the credential stores the spec denies, the macOS keychain included); the press release is rewritten to say that, and no longer says the person's other projects and settings stay out of its reach, since a fenced agent can still read most of what the person can
- dcn-26102222163464482026-10-22 — The plain-terminal drain is one intent that refines the shipped drain bundle (facilitator, on the product thinker's delegation of 2026-10-14 and 2026-10-16, itd-2610222215485265): the decomposition table routes it FILE-AS-IS, since its fence (itd-2610161621364075), its routed judge's isolation (commands/drain.md) and the consent to start agents are rules already in force, cited rather than restated; it refines itd-2610161016401115, whose press release promised a plain-terminal drain and which delivered the routed judge but no loop, rather than reopening a shipped record; revised after review round 1: the path reverses the host-delegated boundary for an opt-in use, as itd-2609201916151817's decision 5 flagged, so that reversal is recorded as adr-2610222222326104, proposed until the sign-off (grounds: the decomposition-calibration note under 2026-10-22; itd-84)
- iss-213Several agents sharing ONE git worktree silently invalidated a verification result and came close to losing committed work. Observed repeatedly during the 2026-08-11 install-test round, in a repo that is about to run more agents, not fewer.
- iss-2608230847432285Per-agent worktrees do not isolate a session whose shell cwd reverts to the shared checkout, so the mitigation iss-213 recommended has a hole. This refines iss-213, which recorded several agents sharing one git worktree silently invalidating a verification result, and whose recommended direction was to give each agent its own worktree so the whole class disappears. That direction is now in force via the AGENTS.md Concurrent sessions section, and on 2026-08-23 three concurrent sessions demonstrated it does not hold. A session's shell cwd can be silently reset from its worktree back to the primary working directory, and the notice arrives on the tool result AFTER the command that caused it, so the contamination lands on the NEXT command. It fails toward the shared tree, which is the wrong direction: two sessions wrote into the main checkout while believing they were in their own worktree. One appended to two Go test files, the other filed a capture and edited three record files, and both discovered it only when a third session read git status in the main checkout and asked who owned the diffs. Nobody lost work, because the convention that a diff you did not make is a peer's work held and the owners were asked rather than the files committed. The isolation property did not hold; the coordination convention compensated for it. Two details generalise beyond this instance. First, the failure is silent in BOTH directions: nothing warns the writer, and nothing would have warned a committer using git add -A, because the misplaced files are indistinguishable from that session's own in git status. What stood between this and a bad commit was one session committing with explicit paths and another happening to run git status for an unrelated reason. Detection was not mechanical in any of the three cases. Second, this is the write-side twin of iss-213 rather than a restatement of it: iss-213's dangerous member was a verification result that described no tree in particular, on the read side, while this is work landing in a tree whose HEAD another session is preparing to move. Same root cause, that the checkout is the unit of isolation and nothing enforces which checkout a session is in, on opposite sides of the read/write boundary. The mechanical mitigation is to address the tree explicitly on every git invocation, git -C <abs-path>, and to use absolute paths for file writes, rather than relying on a persisted cd: a cd is a session-global mutation with no scope and no expiry, which is the wrong shape for the mechanism that is supposed to provide isolation. AGENTS.md states that the checkout is the unit of isolation without saying what makes a session stay in its checkout, and that gap is what let three sessions make the same mistake in one day. Decide the routing: an AGENTS.md line under Concurrent sessions is the cheapest rung and matches how the sequential-id caveat was handled, while the durable form is whatever makes a session's tree unambiguous rather than remembered.
- iss-2610161612203555An agent abcd starts without a terminal has nobody to answer the host's permission prompts. A command the host cannot check is then refused, and the lane stalls or fails. The product thinker chose to have abcd answer those prompts for the agents it starts, using its existing guard rules.
- itd-2610070544145422Someone on Windows installs abcd and it just works: the
- itd-2610240850336695The person grants their sessions what they may do alone, until a time
- itd-2611040344170206Unattended work runs on a named profile, one per way of paying