Saphan StudioDocs
Configuration

What has to be installed, and by whom

The product installs nothing on your machines; what the work needs belongs to your estate.

Studio installs nothing on your machines. Ever. Not a package manager, not a runtime, not a language toolchain. If something it needs is absent, it refuses by name and prints what is missing — it never repairs your host behind your back.

That leaves two separate questions, and they are answered by two different people.

What YOU install: the binary, and nothing else. saphan is a single self-contained executable. Everything it needs to read this configuration, verify signatures, talk to the record and enforce its own confinement travels inside it. There is no pip install, no npm install, no runtime to provision before Studio will start.

What the WORK needs is a property of the work, not of Studio. A fleet that compiles Go needs a Go toolchain on the machine doing the compiling. One that builds an iOS client needs Swift; one that builds Android needs the Android SDK. Studio does not supply these and does not want to: they belong to your build estate, they are versioned on your terms, and an engine that silently installed them would be changing your hosts without asking.

How Studio behaves when a toolchain is missing: it refuses at the door, names the binary it could not find, and stops. It does not fall back to a different tool, does not partially proceed, and does not report success on a reduced measurement. A run whose toolchain is absent is a refusal you can read, not a green result you have to distrust.

Why this is worth a section of its own. The failure this prevents is the one where an automated system quietly provisions something on a production host, and nobody can later say when the machine changed or who changed it. Studio's answer is to make the absence visible and the decision yours. If you want a toolchain present, you put it there deliberately — and the audit trail of that act belongs to your estate, where it can be reviewed, not to a log line inside somebody else's daemon.

Where each host's permitted commands are declared: workspace.worktree_grant_class (§4) names the permission class a spawned agent runs under. The grant is a file you own and version, not a setting Studio computes.

On claude-code, a grant lists the executables an agent may invoke and anything outside it is refused by name at the moment of the call. On the other five backends the grant is not provisioned at all, so it names nothing and nothing is refused by name.

backendgrant provisioned by this engine?what bounds the spawn
procnonot this engine — no jail is composed for a substrate binary on any transport; the operator's own executable runs unwrapped, and its legitimate writes were never scoped to a workdir
claude-codeyes — .claude/settings.jsonthis engine's OS-level jail, composed on every local spawn, together with the grant's own permission policy
codexnonot this engine — the vendor's OWN OS sandbox, plus the argv pins composeCodex sets under --strict-config; nesting our jail inside codex's was MEASURED to fail outright
openai-compatnonot this engine — there is no OS child to jail at all; the step executes an HTTP request in-process
agent-loopnonot this engine at the spawn — the child re-execs and confines ITSELF, through this engine's own composer, before it ever calls an endpoint
qwen-codenothis engine's OS-level jail — on Linux only, MEASURED on strix 2026-08-29, qwen 0.22.2, Landlock abi=8, under the domain this engine's own composer emits: a write inside the workdir succeeded, the same write one directory ABOVE it returned EACCES, and with no domain applied it succeeded again — that third line is the negative control and it was executed, not reasoned. ⛔ Darwin is NOT covered by that reading and this row does not claim it: the mechanism there is seatbelt, not Landlock+bwrap, and what this fleet holds on macOS is a COLLISION reading rather than a boundary one — with qwen's own sandbox on, our seatbelt domain fails outright (sandbox_apply: Operation not permitted, exit 71). Nobody has run the measured pair under seatbelt, so nobody may write it here. On macOS, then, what removes a qwen leg's hands is the vendor's own headless default — give it --allowed-tools (docs/Qwen Code §4)

Read §4.1 before assuming a declared class covers a leg.