foldyard
Bring your whole dev stack into the fold. Secretless by default.
Foldyard is an isolated development environment that runs on your own computer, 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, if you want, your coding agent all run together inside a throwaway Linux VM running rootless Podman. The VM mounts your repo and nothing else.
New to the vocabulary? The glossary defines every term these docs use.
TL;DR
Install the prerequisites. Lima creates the VM; podman talks to the container engine inside it.
# macOS
brew install uv lima podman
# Linux (Debian/Ubuntu shown; x86-64 with KVM)
curl -LsSf https://astral.sh/uv/install.sh | sh
sudo apt-get install qemu-system-x86 qemu-utils ovmf podman
curl -fsSL https://github.com/lima-vm/lima/releases/download/v2.2.0/lima-2.2.0-Linux-x86_64.tar.gz \
| sudo tar Cxz /usr/local
Then:
uv tool install foldyard # puts `foldyard` on your PATH, with `fy` as shorthand
cd your-repo
foldyard init # writes foldyard.toml: a locked-down box with no stack yet;
# agents, stack and editor attach are commented-out opt-ins
fy box up # creates the VM and the dev box; all traffic goes out
# through a proxy on your computer
fy box shell # you're in the box
No custom image is needed: foldyard ships a Debian box with the engine client, git and uv. To
grow it into one tuned for your repo, run foldyard skill install bootstrap-devbox and then
the skill.
An agent inside the box (fy claude, fy codex) is told what fy is and how to edit the
config, so it can help you set foldyard up. Its edits don't take effect on their own: the next
fy box up shows you the change and asks you to approve it. The agent can't sneak a change
in, and you can still share the config with your team.
One prerequisite: a clean repo. The VM mounts only your repo, so the zero-credential guarantee holds exactly when that repo holds config, not credentials. Scan your history with gitleaks or TruffleHog first, and move anything they find out of the repo. Credentials the box really needs are supplied by modes without ever entering the VM. Foldyard can mount a clean repo; it can't clean a dirty one.
The full walkthrough is docs/quickstart.md. The whole manual also ships
with the install, offline and matched to your version: fy docs.
Architecture
Everything that holds a credential stays on your computer. The VM gets the repo and nothing else.
Isolation comes in layers, not as one switch. You can harden the same setup one step at a
time — from a rootless Podman VM, to Lima with a firewall inside the VM, to gVisor under the dev
box, to a second firewall on a Linux host — with egress control as a separate dial alongside.
Each step is one line in foldyard.toml, and the credentials never move:
Which layer carries the weight depends on your operating system — 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 computer — 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 missing is one boundary that holds the real compose stack, the real end-to-end test loop and real services reachable by container name — and zero credentials. → prior-art.md
Secretless by default, credentials on demand. The yard starts with no ~/.ssh, no tokens,
no credential helpers: nothing to steal and no keys to push with. When you need real access you
switch it on (fy mode gcp=logs github=on). Token services on your computer — outside anything
the yard can reach — make short-lived, scoped tokens, and the egress proxy adds them to requests
on the way out. The upstream API gets the token; the yard never does. Emergency levels that act
as you expire on a timer and switch themselves off. If no token service is running, no
credential flows, whatever a file inside the yard says. → modes.md
Isolation without hiding. A container escape lands the attacker inside the throwaway VM,
not on your computer — no host filesystem is mounted for it 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 tries a set of known escapes on
demand. (It tests the escapes we know about: it raises confidence, it can't prove there are
none.) → security.md
Who it's for
Agent users. Give Claude Code (or any agent) the container socket inside the VM: full control of the stack, bounded to the repo and the containers in that VM. The socket controls the VM from the inside, not your computer. 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 VM, and a
worm wakes up with no credentials and no push access, able to reach only a repo the clean-repo
rule keeps boring. All traffic out goes through the proxy on your computer: every request is
decrypted and logged (except trusted toolchain hosts you mark as passthrough), and an allowlist
decides what may go out, with grants you add live. → networking.md
Two honest caveats. Routing through the proxy relies on proxy environment variables, which
well-behaved software honours and malware may ignore. [machine] firewall = true (which
foldyard init writes) closes that gap: a firewall inside the VM refuses any traffic that
doesn't go through the proxy. And switching a credential on while running an untrusted install
step is the one window where install-time code and a live token meet.
Shape
One Python CLI, one foldyard.toml in your repo, and state on your computer in ~/.foldyard/.
Your own task runners (just, npm scripts) stay yours — foldyard runs under them, not
instead of them.
- Core — VM lifecycle · a compose-stack runner (one namespaced stack per worktree, shared
caches) with overlays that change with the mode · a long-lived
dev box (several sessions at once, IDE-attachable) · the
fy verifyisolation self-test · modes with time limits, run by a supervisor on your computer · an egress proxy that adds credentials, logs traffic and enforces the allowlist, backed by the VM firewall ·fy doctor· a TUI. - Plugins — token services (a GCP metadata emulator;
[[inject]]credentials from config alone — static header- or query-parameter tokens, GitHub App installation tokens) · editor attach (VS Code) · agents (Claude Code and Codex, keyless: the box holds a dummy key and the proxy swaps in your real one).
Each project gets its own rootless VM, named after the project. The default backend is Lima:
it runs one VM per project side by side, so a fy box shell or fy code session in one project
survives while you work in another, and it is the backend that can carry the VM firewall. The
alternative, and when to pick it, is in configuration.md.
Status
Alpha. Treat it that way, and expect rough edges.
- macOS — used daily with a production project. Other repos have only been lightly tested.
- Linux (x86-64) — CI boots a real Lima VM on an Ubuntu 24.04 runner and drives the real
loop on it:
fy up, the dev box, worktrees, VM lifecycle,fy verify, and both firewalls.fy tui,fy codeandfy openhaven't been tried on Linux yet, and some messages still give macOS-only hints (brew install …). - WSL2 — the same CI tests pass inside WSL2 on a Windows runner, except the host firewall, which the stock WSL2 kernel can't support. Not yet tried on a real Windows 11 machine.
What has and hasn't been run on Linux is tracked in docs/linux-support.md. Brave testers and issues very welcome!
More info
Start at the docs map. The reasoning behind each design decision is in docs/adrs/.
Metadata
Release files for foldyard 0.4.0
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.4.0.tar.gz | 1.6 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| foldyard-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.5 MB
Release files / foldyard-0.4.0.tar.gz
| Download URL | foldyard-0.4.0.tar.gz |
|---|---|
| Size | 1.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a39653ead7198c1d19e877e5cd3494f7ef671f4ccb7389138c363a47aeb4d53d
|
|
BLAKE2b-256 checksum How to use checksums |
277686381d0b665b55ad6fe5c78aef592c196ac647d36b2f98c75993c2b831e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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.4.0-py3-none-any.whl
| Download URL | foldyard-0.4.0-py3-none-any.whl |
|---|---|
| Size | 832.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8bd33cc7782f669a177b96b27b879c08620b18fbc369d5f35d69040a66ae8e05
|
|
BLAKE2b-256 checksum How to use checksums |
fecc4de516aa8dea568bd08d84eac8cc12d3919bc813607f13daa0ecb02b2747
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}
|