{"id":49880618,"url":"https://github.com/rootcell-ai/rootcell","last_synced_at":"2026-05-15T14:02:10.949Z","repository":{"id":356577890,"uuid":"1233139383","full_name":"rootcell-ai/rootcell","owner":"rootcell-ai","description":"Give the agent root in the cell, not on your host.","archived":false,"fork":false,"pushed_at":"2026-05-14T19:43:45.000Z","size":348,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-14T20:44:37.493Z","etag":null,"topics":["ai-agents","bedrock","coding-agent","egress-control","lima","macos","nixos","sandbox","transparent-proxy"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rootcell-ai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-08T16:25:16.000Z","updated_at":"2026-05-14T19:43:49.000Z","dependencies_parsed_at":"2026-05-08T19:04:11.829Z","dependency_job_id":null,"html_url":"https://github.com/rootcell-ai/rootcell","commit_stats":null,"previous_names":["jimpudar/lima-pi-vm","jimpudar/rootcell","rootcell-ai/rootcell"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/rootcell-ai/rootcell","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rootcell-ai%2Frootcell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rootcell-ai%2Frootcell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rootcell-ai%2Frootcell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rootcell-ai%2Frootcell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rootcell-ai","download_url":"https://codeload.github.com/rootcell-ai/rootcell/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rootcell-ai%2Frootcell/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33068894,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T11:35:32.926Z","status":"ssl_error","status_checked_at":"2026-05-15T11:35:31.362Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","bedrock","coding-agent","egress-control","lima","macos","nixos","sandbox","transparent-proxy"],"created_at":"2026-05-15T14:00:33.969Z","updated_at":"2026-05-15T14:02:10.937Z","avatar_url":"https://github.com/rootcell-ai.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rootcell\n\n[![build](https://img.shields.io/github/actions/workflow/status/rootcell-ai/rootcell/ci.yml?branch=main\u0026style=flat-square\u0026label=build)](https://github.com/rootcell-ai/rootcell/actions/workflows/ci.yml)\n\nGive the agent root in the cell, not on your host.\n\nrootcell gives a coding agent a disposable local VM where it can use root without\ntouching your host filesystem. All outbound traffic passes through a separate\nfirewall VM with DNS, HTTPS, and SSH allowlists. HTTPS is routed through a\ntransparent decrypting proxy, so rootcell can enforce host policy and\n`./rootcell spy` can show formatted Bedrock Runtime traffic when you need to see\nwhat the agent is sending.\n\n## Current Scope\n\nrootcell is early and intentionally narrow. Today it targets:\n\n- **Host OS:** macOS hosts.\n- **LLM provider:** Amazon Bedrock / Bedrock Runtime.\n- **Coding harness:** [Pi](https://pi.dev) inside the agent VM.\n\nThe agent and firewall environments are NixOS VMs, but the host-side lifecycle,\nnetworking, Keychain integration, and VM lifecycle currently assume macOS.\n\n## Why This Exists\n\nCoding agents are most useful when they can run commands, install tools, and edit\nfiles. That's a lot of trust to hand to a process with network access.\n\nrootcell gives you a local workspace where an agent can exercise root inside the\nVM without receiving broad access to your Mac:\n\n- A fresh NixOS VM for the agent's shell and tools.\n- No host-home mount in the agent VM.\n- A separate firewall VM with the only public internet route.\n- DNS, HTTPS, and SSH allowlists you can review and hot-reload.\n- A per-VM SSH key for Git pushes.\n- Provider secrets read from macOS Keychain at runtime, not stored in the VM or\n  the Nix store.\n\nUse it when you want the agent to go wild inside the VM, while keeping\nan explicit network boundary around the work.\n\n## How It Works\n\n```mermaid\nflowchart LR\n  Host[\"macOS host\u003cbr/\u003erepo, Keychain, ./rootcell\"] --\u003e|SSH| Firewall[\"firewall VM\u003cbr/\u003ednsmasq, mitmproxy\"]\n  Host --\u003e|SSH ProxyJump through firewall| Agent[\"agent VM\u003cbr/\u003eNixOS, pi, dev tools\"]\n  Agent --\u003e|DNS, HTTPS, SSH| Firewall[\"firewall VM\u003cbr/\u003ednsmasq, mitmproxy\"]\n  Firewall --\u003e|allowlisted egress| Internet[\"internet\"]\n```\n\nThe two VMs have different jobs:\n\n| Piece | What it does |\n| --- | --- |\n| `agent` VM | Runs `pi`, shell commands, Git, build tools, and project work. It has root inside the VM, but no direct public internet route. |\n| `firewall` VM | Owns the public egress path. It runs `dnsmasq` for DNS allowlisting and `mitmproxy` for HTTPS interception and SSH CONNECT policy. |\n| `./rootcell` | Host-side wrapper that creates, provisions, updates, and enters the VMs. It also syncs allowlists and injects configured provider secrets for each session. |\n\nRootcell supports named instances. Plain `./rootcell` uses the `default`\ninstance and creates VMs named `agent` and `firewall`. `./rootcell --instance\ndev` creates `agent-dev` and `firewall-dev`, with separate CA material,\nallowlists, Keychain mappings, and a separate private VM link.\n\nHTTPS egress is transparent from inside the agent VM. A normal command like\n`curl https://github.com` either works because the host is allowlisted, or fails\nbecause the firewall denies it. SSH is explicit because SSH has no SNI; the\nagent VM's SSH config tunnels it through the firewall so hostnames can still be\nallowlisted.\n\nCleartext HTTP is denied. All egress is expected to be HTTPS or SSH.\n\n## Quick Start\n\nYou need:\n\n- macOS. The current vfkit runtime path uses Apple's Virtualization Framework.\n- [Bun](https://bun.sh), [vfkit](https://github.com/crc-org/vfkit),\n  [zstd](https://facebook.github.io/zstd/), and Python 3 on the host `PATH`.\n- macOS command-line tools used by rootcell: `curl`, `ssh`, `scp`,\n  `ssh-keygen`, `openssl`, and `security`.\n- Amazon Bedrock credentials stored in macOS Keychain.\n\nThe default published VM images target Apple Silicon hosts. Intel hosts require\nthe architecture changes described in [Changing Architecture](#changing-architecture).\n\nThe agent and firewall are still NixOS VMs, and provisioning runs Nix inside\nthose VMs. Host-side Nix is optional for end users: use it only if you choose\nthe Nix setup below or if you are building release images.\n\n### Homebrew Setup\n\n```bash\nchmod +x ./rootcell\n\nbrew tap oven-sh/bun\nbrew install bun vfkit zstd python\nbun install --frozen-lockfile\n\n# Store the default Bedrock provider key in Keychain.\nsecurity add-generic-password -a \"$USER\" -s aws-bedrock-api-key -w \"\u003cyour-key\u003e\"\n\n# Start rootcell.\n./rootcell\n```\n\n### Nix Setup\n\nFrom the repository root:\n\n```bash\nchmod +x ./rootcell\n\nnix profile install .#hostTools\nbun install --frozen-lockfile\n\n# Store the default Bedrock provider key in Keychain.\nsecurity add-generic-password -a \"$USER\" -s aws-bedrock-api-key -w \"\u003cyour-key\u003e\"\n\n./rootcell\n```\n\nFor a one-off shell instead of a profile install:\n\n```bash\nnix shell .#hostTools --command bun install --frozen-lockfile\nnix shell .#hostTools --command ./rootcell\n```\n\nIf your host Nix install has not enabled flakes and the new CLI yet, add\n`--extra-experimental-features 'nix-command flakes'` to the host-side `nix`\ncommands above.\n\nFirst run downloads compatible rootcell VM images from the configured release\nmanifest, creates instance-local vfkit disks, and provisions the VMs. Later runs\nnormally take seconds.\n\n### Host Runtime\n\nrootcell does not install or build host tools at runtime. It expects `bun`,\n`vfkit`, `zstd`, and `python3` to be available from your chosen package manager.\nFor non-standard paths, set:\n\n```bash\nROOTCELL_VFKIT=/path/to/vfkit\nROOTCELL_ZSTD=/path/to/zstd\nROOTCELL_PYTHON=/path/to/python3\n```\n\nvfkit is the supported VM runtime:\n\n```bash\n./rootcell\n```\n\nImage resolution is controlled by:\n\n```bash\nROOTCELL_IMAGE_MANIFEST_URL=https://github.com/rootcell-ai/rootcell/releases/latest/download/manifest.json\nROOTCELL_IMAGE_DIR=/path/to/local/rootcell-image-dist\n```\n\n`ROOTCELL_IMAGE_DIR` must contain `manifest.json` plus the image files named in\nthat manifest. Image build definitions now live in `images/` and are exposed by\nthis repository's root flake. The default manifest URL points at this\nrepository's GitHub Release assets.\n\n## Daily Workflow\n\n```bash\n./rootcell                        # open a bash shell inside the agent VM\n./rootcell pi                     # run pi directly\n./rootcell -- nix flake update    # run any command inside the agent VM\n./rootcell allow                  # reload network allowlists after editing them\n./rootcell provision              # rebuild/re-provision after VM Nix or pi config edits\n./rootcell pubkey                 # print the agent VM's SSH public key\n./rootcell spy                    # tail formatted Bedrock Runtime traffic\n./rootcell spy --raw              # include sanitized raw JSON bodies too\n./rootcell spy --tui              # browse Bedrock Runtime traffic interactively\n\n./rootcell --instance dev         # open the dev instance shell\n./rootcell --instance dev allow   # reload only the dev instance allowlists\n```\n\n## Allowing Network Access\n\nNetwork policy is per instance. On first run, `./rootcell` copies each tracked\n`proxy/*.defaults` file to `.rootcell/instances/\u003cname\u003e/proxy/`:\n\n- `.rootcell/instances/default/proxy/allowed-dns.txt` controls which hostnames can resolve.\n- `.rootcell/instances/default/proxy/allowed-https.txt` controls which HTTPS hosts can be reached.\n- `.rootcell/instances/default/proxy/allowed-ssh.txt` controls which SSH hosts can be reached.\n\nFor most HTTPS access, add the host to both DNS and HTTPS, then reload:\n\n```bash\n$EDITOR .rootcell/instances/default/proxy/allowed-dns.txt\n$EDITOR .rootcell/instances/default/proxy/allowed-https.txt\n./rootcell allow\n```\n\nFor Git over SSH, add the host to the instance's `allowed-ssh.txt` and run\n`./rootcell allow`. GitHub, GitLab, Bitbucket, and Azure DevOps are included in the\ndefault SSH allowlist.\n\nReloading allowlists takes about a second and does not rebuild either VM. To\nreset a live allowlist to project defaults, delete the live file and run\n`./rootcell`; it will be re-seeded from its `.defaults` sibling. For a named\ninstance, use the same paths under `.rootcell/instances/\u003cname\u003e/proxy/` and run\n`./rootcell --instance \u003cname\u003e allow`.\n\n## Common Changes\n\nAfter editing these files, run `./rootcell provision`:\n\n- `flake.nix`, `common.nix`, `agent-vm.nix`, `firewall-vm.nix`, or `home.nix`\n- Anything under `pi/`\n- The checked-in allowlist defaults\n\nFor live allowlist edits only, use `./rootcell allow`.\n\n### Add Tools\n\nEdit `home.packages` in `home.nix`, then run:\n\n```bash\n./rootcell provision\n```\n\n### Customize Pi\n\nThe agent VM is preconfigured to run [Pi](https://pi.dev). Support for other\ncoding harnesses is on the roadmap.\n\nEverything under `pi/agent/` on the host is symlinked into `~/.pi/agent/` inside\nthe agent VM.\n\n- `pi/agent/AGENTS.md` becomes the global instruction file.\n- `pi/agent/skills/\u003cname\u003e/SKILL.md` becomes a global pi skill.\n\nAdd or edit files there, then run `./rootcell provision`.\n\nPer-project rules still belong in an `AGENTS.md` or `CLAUDE.md` at the root of\nthe project you are working on inside the VM.\n\n### Push to GitHub, etc\n\nThe agent VM generates its own RSA SSH keypair on first provision. The private\nkey stays in the VM; the public key is meant to be registered with GitHub,\nGitLab, Bitbucket, Azure DevOps, or a deploy key.\n\n```bash\n./rootcell pubkey\n```\n\nAfter registering the key, `git push` works from inside the agent VM as long as\nthe host is on that instance's `allowed-ssh.txt`.\n\n## Security Model\n\nrootcell is designed to reduce accidental and routine agent egress, not to be a\ncomplete data-loss-prevention system.\n\nWhat it does:\n\n- Keeps the host filesystem out of the VM by avoiding default host mounts.\n- Gives the agent VM only a private link to the firewall VM.\n- Routes DNS through a suffix allowlist.\n- Intercepts HTTPS at the firewall and checks both TLS SNI and HTTP `Host`.\n- Validates the upstream certificate before sending bytes onward.\n- Denies cleartext HTTP instead of allowlisting unauthenticated `Host` headers.\n\nWhat remains your responsibility:\n\n- Be careful with broad wildcards such as `*.cloudfront.net` or\n  `*.githubusercontent.com`; allowed shared infrastructure can become an exfil\n  path.\n- Avoid allowlisting DNS-over-HTTPS endpoints unless you really need them.\n- Treat any allowed writeable service as a possible outbound channel.\n- Remember that network policy cannot prevent timing channels or encoded data in\n  legitimate requests.\n\nKnown technical gaps and operational debugging notes live in\n[proxy/README.md](proxy/README.md).\n\n## Roadmap\n\nrootcell's current goal is to make the narrow macOS + Bedrock + Pi path solid\nbefore broadening the support matrix. Planned expansion includes:\n\n- **Host compatibility:** support both macOS and Linux hosts.\n- **LLM providers:** add OpenAI and Anthropic alongside Amazon Bedrock.\n- **Coding harnesses:** support Codex CLI and Claude Code CLI alongside Pi.\n\nThe long-term shape is a provider- and harness-pluggable local VM boundary, with\nthe same explicit network policy model across supported hosts.\n\n## Project Layout\n\n```text\nrootcell                 host entry point for VM lifecycle and commands\nsrc/                     Bun TypeScript implementation for migrated entrypoints\nflake.nix                Nix inputs, guest VM configs, images, and optional host tools\ncommon.nix               shared NixOS config for both VMs\nagent-vm.nix             agent VM network and trust-store config\nfirewall-vm.nix          firewall VM services and nftables rules\nhome.nix                 pi, Git, SSH, and developer tools for the agent VM\nnetwork.nix              default inter-VM network settings\n.env.defaults            seed values for per-instance `.env`\nsecrets.env.defaults     seed Keychain secret mappings for per-instance `secrets.env`\n.rootcell/               gitignored per-instance state, allowlists, CA, and generated files\nproxy/                   allowlists and mitmproxy/dnsmasq firewall code\n  agent_spy.py           Bedrock Runtime formatter for `./rootcell spy`\n  agent_spy_tui.py       Textual browser for `./rootcell spy --tui`\npi/agent/                global pi instructions, skills, and extensions\ncompletions/             bash and zsh completion for `rootcell`\n```\n\n## VM Lifecycle\n\nvfkit instance state lives under `.rootcell/instances/\u003cname\u003e/vfkit/`. The host\ncontrol key and generated SSH config live under `.rootcell/instances/\u003cname\u003e/ssh/`.\nThe agent VM is reached through SSH ProxyJump via the firewall VM; no VSOCK\ndevice is attached on the vfkit path.\n\n## Configuration\n\n### Environment\n\n`./rootcell` seeds `.rootcell/instances/\u003cname\u003e/.env` from `.env.defaults` on\nfirst run. Edit that file for instance-local settings such as:\n\n```sh\nAWS_REGION=us-west-2\nROOTCELL_SUBNET_POOL_START=192.168.100.0\nROOTCELL_SUBNET_POOL_END=192.168.254.0\n```\n\nThe first run also writes `.rootcell/instances/\u003cname\u003e/state.json` with the\ninstance's allocated `/24`. By default, rootcell chooses the first free subnet\nfrom `192.168.100.0/24` through `192.168.254.0/24`, uses `.2` for the firewall,\nand uses `.3` for the agent. Existing state is not recalculated if you later\nedit the pool values.\n\nTo pin a new instance to a specific subnet before first run, set both IPs in\nthat instance's `.env`:\n\n```sh\nFIREWALL_IP=192.168.109.2\nAGENT_IP=192.168.109.3\nNETWORK_PREFIX=24\n```\n\n`./rootcell` also seeds `.rootcell/instances/\u003cname\u003e/secrets.env` from\n`secrets.env.defaults` on first run. This file maps agent VM environment\nvariable names to macOS Keychain service names; it does not contain the secret\nvalues themselves:\n\n```sh\nAWS_BEARER_TOKEN_BEDROCK=aws-bedrock-api-key\n```\n\nFor example, to inject an additional `ANTHROPIC_API_KEY`:\n\n```sh\nsecurity add-generic-password -a \"$USER\" -s anthropic-api-key -w \"\u003cyour-key\u003e\"\necho 'ANTHROPIC_API_KEY=anthropic-api-key' \u003e\u003e .rootcell/instances/default/secrets.env\n```\n\nIf you want to use Anthropic or OpenAI subscriptions, you can log in from\ninside the VM.\n\nDo not put provider keys in `home.nix`; the Nix store is world-readable.\n\n### Shell Completions\n\n`rootcell completion` prints the yargs-generated completion script. The checked-in\nfiles under `completions/` are generated from that command; refresh them with\n`bun run completions` after changing commands or options. The generated scripts\nregister `rootcell`, so put `rootcell` on `PATH` before sourcing or installing\nthem.\n\nFor zsh, after `compinit`:\n\n```sh\nrootcell completion \u003e\u003e ~/.zshrc\n```\n\nFor bash:\n\n```sh\nrootcell completion \u003e\u003e ~/.bashrc\n```\n\n### Changing Architecture\n\nThe default configuration is for Apple Silicon hosts with `aarch64-linux`\nguests. For Intel Macs or x86 Linux guests, update these together:\n\n- `system` in `flake.nix`\n- The pi release tarball URL and hash in `home.nix`\n- The image build outputs and release assets under `images/`\n\n### Multiple Instances\n\nNamed instances are isolated from each other:\n\n```bash\n./rootcell --instance dev\n./rootcell --instance review\n```\n\nEach instance gets its own VMs, state directory, CA, allowlists, Keychain mapping\nfile, control SSH key, private-link state, and `/24`.\n\nThe `default` instance migrates from legacy repo-local files on first run: if\n`.env`, `secrets.env`, `proxy/allowed-*.txt`, or `pki/` already exist, rootcell\ncopies them into `.rootcell/instances/default/`. Named instances seed from the\nchecked-in defaults.\n\n## Troubleshooting\n\nSee what the firewall is denying:\n\n```bash\n./rootcell --instance default spy\n```\n\nSee formatted Bedrock Runtime requests and responses:\n\n```bash\n./rootcell spy\n./rootcell spy --raw\n./rootcell spy --tui\n```\n\nCheck that firewall services are listening:\n\n```bash\nssh -F .rootcell/instances/default/ssh/config rootcell-firewall -- \\\n  \"ss -tln '( sport = :8080 or sport = :8081 )' \u0026\u0026 ss -uln '( sport = :53 )'\"\n```\n\nTest an HTTPS allowlist entry from inside the VM:\n\n```bash\n./rootcell -- curl -v https://example.com\n```\n\nInspect the live allowlists inside the firewall VM:\n\n```bash\nssh -F .rootcell/instances/default/ssh/config rootcell-firewall -- \\\n  \"cat /etc/agent-vm/allowed-https.txt \u0026\u0026 cat /etc/agent-vm/dnsmasq-allowlist.conf\"\n```\n\n## License\n\nCopyright (C) 2026 Jim Pudar.\n\nrootcell is licensed under the GNU Affero General Public License v3.0 only\n(`AGPL-3.0-only`). See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frootcell-ai%2Frootcell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frootcell-ai%2Frootcell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frootcell-ai%2Frootcell/lists"}