foldyard
Bring your whole dev stack into the fold. Secretless by default.
Foldyard is a laptop-local, isolated development environment for your project's entire dev stack — not just an agent, not just a shell. Your docker-compose services (databases, emulators, app servers), your dependency installs, your IDE backend, and optionally your coding agent all run together inside a throwaway Linux VM running rootless Podman — one that mounts only the repo, and nothing else.
TL;DR
brew install uv lima podman # lima creates the VM; podman drives the socket it hands out
uv tool install "foldyard[host]" # puts `foldyard` on your PATH, with `fy` as shorthand
cd your-repo
foldyard init # writes foldyard.toml: a locked-down, stack-less box, with
# agents / stack / editor attach as commented opt-ins
fy box up # VM + dev box; egress fail-closed through a host-side proxy
fy box shell # you're in the yard
No custom image required — foldyard ships a Debian box (engine client, git, uv). To grow it
into one tuned for your repo: foldyard skill install bootstrap-devbox, then run the skill.
An agent inside the box (fy claude/fy codex) is told what fy is and how to edit the
config, so you can let them help you. The config changes won't apply automatically, but
instead you'll see the changes and have to approve on the next fy box up. This way the
agent inside the box can't sneak changes in, but you can still share the config with your team.
One prerequisite: a clean repo. The yard mounts only your repo, so the zero-credential guarantee holds exactly when that repo carries config, not credentials. Scan your history with gitleaks or TruffleHog first and move anything that surfaces into a posture. Foldyard can mount a clean repo; it can't clean a dirty one.
The walkthrough is docs/quickstart.md — and the whole manual ships
with the install, offline and version-matched: fy docs.
Architecture
Everything that holds a credential stays on your machine; the yard gets the repo and nothing else. One picture of the whole split:
The isolation is a ladder, not a switch — the same yard hardened one ring at a time, from a
rootless Podman VM through Lima with the wall to gVisor under the dev box, with the egress dial
alongside. Each step is one line in foldyard.toml, and the credentials never move:
Where each layer carries the weight differs by host — isolation-layers.md.
Why
A fold-yard is the enclosed farmyard where animals are folded (penned) for the night. Same idea here: everything that runs untrusted code lives in the yard, and your machine — keys, browser profile, other repos — stays outside the fence. Three ideas hold it up.
The unit of isolation is the project, not the agent. Agent sandboxes are plentiful, and isolated dev environments exist (Devcontainers, Codespaces, Gitpod, Coder). What's genuinely missing is one boundary that holds the real compose stack, the real e2e loop and real services by container name and zero credentials. → prior-art.md
Secretless by default, posture on demand. The yard starts with no ~/.ssh, no tokens, no
credential helpers — nothing to lift, and no keys to push with. When you need real access you
declare a posture (fy mode gcp=logs github=app), and host-side daemons outside the blast
radius mint short-lived scoped tokens and inject them at the egress proxy — so the token
reaches the upstream API but never the yard. Emergency rungs are TTL-bound and auto-revert. No
daemon running ⇒ no credential flows, whatever a file inside the yard says.
→ modes.md
Isolation without hiding. A container escape lands the attacker inside the disposable VM,
not on your machine — there is no host filesystem mounted to reach even at VM level. Because
the boundary doesn't depend on concealment, nothing needs to be nested or hidden: Podman
Desktop shows every container, and fy verify audits the mounts and exercises a battery of
known escapes on demand. (It tests the escapes we know about — it raises assurance, it doesn't
prove a negative.) → security.md
Who it's for
Agent users — hand Claude Code (or any agent) the in-VM machine socket: full stack autonomy, bounded to the repo and the containers inside the VM. The socket controls the machine from within the moat, not your host. Safer autonomy, not less of it.
Everyone else — supply-chain worms (Shai-Hulud and friends) ride npm install and
lifecycle scripts on developer laptops. Run installs, dev servers and your IDE backend in the
yard, and the worm wakes up with no ambient credentials and no push access, its reach bounded
to a repo the clean-repo prerequisite keeps boring. Egress routes through the host-side proxy:
every destination logged (SNI-only by default, full decrypt-and-log under capture=on), with
an opt-in default-deny wall and live host grants. → networking.md
Two honesty notes. Proxy routing rides proxy env vars, which cooperative software honours and
malware may not — [machine].wall = true (what foldyard init writes) closes that by
provisioning a fail-closed firewall into the VM itself, making the proxy the only way out.
And declaring a posture while running an untrusted install step is the one window where
install-time code and a live token coincide.
Shape
One Python CLI, one foldyard.toml in your repo, host state in ~/.foldyard/. Your own task
runners (just, npm scripts) stay yours — foldyard runs under them, not instead of them.
- Core — machine lifecycle · compose-stack runner (worktree-namespaced projects, shared
caches) with declarative posture overlays · long-lived dev box
(multi-session, shadow volumes, IDE-attachable) ·
verifyisolation battery · mode/posture substrate with TTLs and a host-side supervisor · credential-injecting egress proxy with capture logging, a default-deny wall and VM-level fail-closed forcing · doctor · TUI. - Plugins — credential minters (GCP metadata emulator, GitHub App header injection, generic header/query-param-auth APIs) · editor attach (VS Code) · agents (Claude Code and Codex, keyless: the proxy injects your key host-side, a dummy lives in the box).
Each project gets its own rootless VM, scoped by project name. The default backend is Lima
because it runs the per-project VMs side by side — so one project's open box shell / code
session survives while you work in another — and because it's the backend that can be
provisioned with the fail-closed wall. Other backends, and when to pick them, are in
configuration.md.
Status
The engine runs daily on Macs with a production project, but has only been lightly tested on
other repos, treat it as alpha quality for now. A Linux host is partly validated — the machine
VM, verify, both walls — but not the daily fy up loop; WSL2 runs the same CI tier (the host
wall excepted — a WSL2 kernel limit); what has and has not been run there is tracked in
docs/linux-support.md. Brave testers and issues very welcome!
More info
Start at the docs map; the "why" behind each design call is in docs/adrs/.
Metadata
Release files for foldyard 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| foldyard-0.3.1.tar.gz | 1.3 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| foldyard-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.0 MB
Release files / foldyard-0.3.1.tar.gz
| Download URL | foldyard-0.3.1.tar.gz |
|---|---|
| Size | 1.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c2ea2e2164f2cbc7902923f45890853e13fe05f3b000c22edb1e8621167f2b52
|
|
BLAKE2b-256 checksum How to use checksums |
ca3e4c18bfaf7a11266686c4338f6675e208b28fbf3a1a15c307d75ecd0fd07c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.16 {"installer":{"name":"uv","version":"0.12.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / foldyard-0.3.1-py3-none-any.whl
| Download URL | foldyard-0.3.1-py3-none-any.whl |
|---|---|
| Size | 683.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
26130c4a3d789129e03cd57297dca5e28a487d415d445f594d25ff54a1881be9
|
|
BLAKE2b-256 checksum How to use checksums |
78262640df499c88b92e5699a051ba2b286b7ee389309975ab1b3023d266eef5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.16 {"installer":{"name":"uv","version":"0.12.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|