{"slug": "show-hn-clawk-give-coding-agents-a-disposable-linux-vm-not-your-laptop", "title": "Show HN: Clawk – Give coding agents a disposable Linux VM, not your laptop", "summary": "Clawk is a new open-source tool that gives coding agents like Claude Code or Codex a disposable Linux VM instead of direct access to the user's laptop. It runs agents inside a sandboxed environment with restricted network access and no host file exposure, allowing agents to install packages and run code without risk to the user's machine. The project is pre-1.0 and aims to provide a safer alternative to running agents with full permissions or constant approval prompts.", "body_md": "*Give a coding agent its own disposable Linux machine, not yours.*\n\n** Install** ·\n\n**·**\n\n[Quickstart](#quickstart)**·**\n\n[Why a VM?](#why-a-vm)**·**\n\n[How it works](#how-it-works)**·**\n\n[Compared to](#compared-to)**·**\n\n[FAQ](#faq)\n\n[Docs](/clawkwork/clawk/blob/main/docs)A coding agent is only useful when you let it actually *do* things: install\npackages, run the code it writes, start servers, use the network. On your own\nmachine that leaves two bad options. You approve every command (and babysit a\nprompt every few seconds), or you run `--dangerously-skip-permissions`\n\nand hope\nnothing important is one `rm -rf`\n\nor one leaked token away.\n\nclawk is a third option. `cd`\n\ninto a repo, type `clawk`\n\n, and Claude Code (or\nCodex, or a shell) is working inside a disposable Linux VM (your code mounted\nin, root in the guest, no permission prompts) while your files, your keychain,\nand the rest of your machine stay out of reach. **The agent gets its own\nmachine instead of yours.**\n\n[\n](/clawkwork/clawk/blob/main/assets/demo.gif)\n\n*One command to a working agent; an attempt to send data to an\nunknown server, blocked by the network allow-list; clawk attach\nresumes the session later.*\n\nThe boundary isn't a rule in a prompt the agent could be talked out of. It's a separate machine, and the only openings are the ones you mounted. From a shell inside a sandbox:\n\n``` bash\n$ curl https://tracker.evil.example   # not on the allow-list: blocked\ncurl: (7) Failed to connect to tracker.evil.example port 443 after 2 ms: Connection refused\n\n$ cat ~/.ssh/id_rsa                   # your keys never entered the VM\ncat: /home/agent/.ssh/id_rsa: No such file or directory\n\n$ git push                            # ...yet this works: ssh-agent is forwarded\nEnumerating objects: 5, done.\n```\n\nTo be honest about the limits, the allow-list blocks connections to *unknown*\nservers, not to ones you've allowed: github.com is pre-allowed and the\nforwarded ssh-agent can push, so treat anything the agent can read as\nsomething it could publish. The\n[security model](#security-model-and-its-limits) spells this out.\n\nAnd if the agent wrecks the VM, run `clawk destroy && clawk`\n\n: a fresh VM, same\nrepo, and `--resume`\n\nrestores the conversation.\n\nImportant\n\n**Pre-1.0 and moving fast.** Expect breaking changes between releases and\nthe occasional rough edge; things can and will break. Please file issues;\nthat feedback is shaping 1.0.\n\n**Let the agent do anything.** It runs in a disposable VM with a restricted network, so`rm -rf`\n\n, package installs, and untrusted code can't reach your host, your files, or anything you didn't explicitly share.**Working in one command.**`cd`\n\ninto a repo and run`clawk`\n\n. No Dockerfile, devcontainer, or setup file. First boot builds a rootfs from your image; every boot after takes seconds.**Break it without losing anything.** Destroy and recreate freely; your code and the agent's conversations live on the host. Only the disposable VM disk is lost.**A real Linux box, your toolchain.** Any OCI image is the rootfs: a full OS with exactly the tools your project needs. No Docker daemon required.**Secrets stay on your machine.** Outbound traffic is allow-listed and your ssh-agent is forwarded, so`git push`\n\nworks without keys entering the VM.**A sandbox per project or ticket.** Run several at once; multi-repo tickets get a git worktree per repo with coordinated PRs. Idle VMs automatically release memory and suspend to disk, so a forgotten sandbox costs (almost) nothing.\n\nclawk is a general-purpose local environment for autonomous coding agents. The VM is the point: it's a whole machine the agent can own, not a process wrapped in policy on the one you're using.\n\n**A separate kernel.** The guest runs its own Linux kernel, so the host filesystem isn't hidden behind deny rules; it was never mounted.**A conventional Linux environment.** Standard kernel, standard userland,`/dev/kvm`\n\n-shaped expectations, so tools behave the way their docs say, without a syscall-filter surprise.**Root in the guest.** Install system packages, edit`/etc`\n\n, load a module, bind a privileged port. It's the agent's box to reconfigure.**A disposable lifecycle.** Cheap to break and quick to recreate; a wrecked VM is one`clawk destroy && clawk`\n\naway, with your repo and conversations untouched on the host.**Stronger separation from the host.** Isolation rests on the hypervisor boundary rather than on getting a process-sandbox policy exactly right.\n\nThat combination runs workloads a restricted process sandbox tends to fight you on:\n\n- installing packages and native dependencies;\n- running background services (databases, queues, dev servers);\n- executing untrusted builds and tests at full speed;\n- using system-level Linux tooling that expects a real machine;\n- and, with a KVM-enabled guest kernel on supported hardware, container and\nKubernetes dev workflows such as Docker or Kind running\n*inside*the sandbox. This is opt-in and hardware-gated; see[Images](/clawkwork/clawk/blob/main/docs/images.md#guest-kernel-override)for the exact requirements.\n\nNone of this is the *product*; clawk is for local agent work in general.\nDocker and Kubernetes are just the sharpest example of \"needs a real machine,\nnot a sandboxed process.\"\n\nRequires macOS 14+ on Apple silicon. (Linux is supported via firecracker and\ncurrently experimental; see\n[VM providers](/clawkwork/clawk/blob/main/docs/commands.md#vm-providers) for the gaps. This README is\nmacOS-first.)\n\n```\nbrew install clawkwork/tap/clawk\n```\n\n**From source** (contributors, or if you don't use Homebrew), needs Go 1.26+:\n\n```\ngit clone https://github.com/clawkwork/clawk && cd clawk\nmake install\n```\n\nEither way there's no extra host tooling: no Docker, no qemu, no sudo. The hypervisor is Apple's Virtualization.framework, linked into the binary. First run probes for anything missing and offers to fix it.\n\n**Uninstall:** `clawk destroy`\n\nyour sandboxes, `rm -rf ~/.clawk`\n\n, then remove\nthe binary with `brew uninstall clawk`\n\n(or delete it from `$GOBIN`\n\nfor a\nsource install). Nothing else was installed: there are no launchd jobs; the\nper-sandbox daemons are ordinary processes that exit with their VMs.\n\nThe everyday case, a sandbox for the directory you're in:\n\n```\ncd ~/code/my-project\nclawk                      # boot a sandbox for this dir + attach claude\nclawk run shell            # drop into a shell in the same sandbox\nclawk run codex            # or another agent: codex, opencode, shell\nclawk down                 # stop the VM (repo + agent state persist)\nclawk attach               # come back later — boots if stopped, reattaches claude\nclawk destroy              # remove the VM (conversation history is kept)\n```\n\nCommon options:\n\n```\nclawk run claude -- --resume            # pass args through to the agent\nclawk forward add my-project 3000       # expose a guest dev server on localhost:3000\nclawk network allow my-project api.example.com\n```\n\nWorking on a ticket that spans several repositories? One command creates a\nsandbox with a git worktree per repo on a fresh branch, and `clawk pr`\n\nlater\nopens cross-linked PRs for whatever changed:\n\n```\ncd ~/code/my-workspace     # contains a clawk.mod listing the repos\nclawk work INFRA-123       # one sandbox, a worktree per repo, claude attached\nclawk pr INFRA-123         # push branches + open one PR per repo\n```\n\nThe full ticket lifecycle (status, follow-up branches after merges,\nrebases) is in ** docs/ticket-mode.md**.\n\nTip:using Claude Code? Run`claude setup-token`\n\nthen`clawk auth set-token`\n\nonce, and every sandbox comes up already signed in, with no`/login`\n\nand no login conflicts between parallel sandboxes. See.[docs/claude-auth.md]\n\nOne rule governs persistence: *the VM is disposable; everything you'd miss\nlives on the host.*\n\n`clawk down` |\n`clawk destroy` |\n|\n|---|---|---|\n| Your repo (mounted worktree; commits, branches) | ✅ | ✅ |\n| Agent state (Claude/Codex conversations, memory) | ✅ | ✅ |\nThe VM disk (apt installs, caches, `$HOME` ) |\n❌ (rebuilt fresh at every boot*) | ❌ (that's the point) |\n\n* Two exceptions: resuming a `clawk snapshot`\n\nrestores the disk and\nmemory exactly as suspended, and the Linux/firecracker provider keeps\nits disk until destroy. Tools every boot needs belong in the image\n(`vm ( image … )`\n\n); per-boot setup belongs in `on up`\n\nhooks.\n\nAgent state is host-mounted per sandbox: the guest's `~/.claude/projects/`\n\nand `~/.claude/memory/`\n\n(and codex's `~/.codex/`\n\n) live under\n`~/.clawk/namespaces/default/state/<name>/`\n\non the host, so a recreated\nsandbox picks up its old conversations with `--resume`\n\n.\n\nRunners launch in their \"externally sandboxed\" modes: claude gets\n`--dangerously-skip-permissions`\n\n, codex gets\n`--dangerously-bypass-approvals-and-sandbox`\n\n. On your own machine those flags\nwould be reckless; here they are the point: the VM boundary and the network\nallow-list provide the containment, so the agent works at full speed without\nper-action prompts. The agent can only affect what you mounted and\nallow-listed, nothing more (see [SECURITY.md](/clawkwork/clawk/blob/main/SECURITY.md)).\n\nPrefer the confirmation prompts anyway? Add `--safe`\n\nto any attach\n(`clawk --safe`\n\n, `clawk run claude --safe`\n\n) and the runner starts without its\nbypass flags for that session.\n\nOutbound traffic is denied by default; each sandbox has its own allow-list.\nDNS resolves everything; TCP, UDP (including QUIC), and ICMP echo to unlisted\nhosts are refused. Common registries (npm, PyPI, crates.io, GitHub,\nAnthropic, …) are pre-allowed, and the filter is DNS-aware, so allowing\n`example.com`\n\nkeeps working as its IPs rotate.\n\n```\nclawk network allow my-project api.stripe.com '*.internal.mycorp.com' 10.0.0.5\nclawk network denials my-project     # what the agent tried that got blocked\nclawk forward add my-project 3000    # localhost:3000 → the guest's dev server\n```\n\nDenials are recorded by the *hostname the guest resolved*, so `clawk network denials`\n\nreads as a log of what the agent tried to reach. Reusable named\npolicies (including subscribing to external blocklists like oisd) and the\n`use`\n\nchain that layers them are in\n** docs/networking.md**.\n\nNo config file is required; defaults are sensible. When a project needs\nmore, a `clawk.mod`\n\nfile describes it, in a go.mod-style syntax:\n\n```\nsandbox my-project (\n    vm (\n        cpu    4\n        memory 8GiB\n        image  golang:1.25          # any OCI image is the rootfs\n    )\n    network ( allow api.example.com )\n    forwards ( 3000 )\n    env ( DATABASE_URL )            # names only; values come from your shell\n    on create ( \"go mod download\" )\n    agent (\n        instructions \"Ask before running destructive commands.\"\n    )\n)\n```\n\nThe block is a *template*: snapshotted when the sandbox is created, so a\nrunning sandbox never changes unexpectedly. The full reference (shares,\nsecret files, skills, agent memory seeding, multi-repo workspace roots) is\nin ** docs/configuration.md**; images and custom\nguest kernels (including the KVM-enabled kernel used for nested\nvirtualization) are in\n\n**.**\n\n[docs/images.md](/clawkwork/clawk/blob/main/docs/images.md)\n\n```\nclawk list                  # all sandboxes\nclawk status [<name>]       # state, forwards, blocked hosts; --json for scripts\nclawk up / down             # boot / stop\nclawk pause / resume        # suspend / resume the running VM in memory\nclawk snapshot              # save to disk: RAM freed, guest intact; resume restores it\nclawk destroy               # remove the VM; host-side state persists\n```\n\n`clawk snapshot`\n\nis hibernation for sandboxes: the guest's memory is saved\nbeside its disk and the next boot restores the guest exactly where it was.\nBackground processes and dev servers continue as if nothing happened, and\n`clawk attach`\n\nputs you back in front of the agent. The full command surface,\nrunner dispatch, and the idle-management machinery (ballooning, admission\ncontrol, auto-stop) are in ** docs/commands.md**.\n\n```\nyou ──▶ clawk CLI ──▶ per-sandbox daemon (detached; owns the VM)\n                        ├─ gvproxy: in-process userspace TCP/IP stack —\n                        │  the DNS-aware outbound filter the guest can't reconfigure\n                        ├─ vsock bridge to the in-guest pty-agent (no sshd)\n                        ├─ ssh-agent proxy, macOS (signing stays on the host)\n                        └─ VM: Virtualization.framework (macOS) / firecracker (Linux)\n                             ├─ clawk-init, PID 1 (no systemd, no cloud-init)\n                             ├─ your repo, live-mounted over virtio-fs\n                             └─ claude / codex / shell on a PTY\n```\n\nA few deliberate choices, in brief:\n\n**The rootfs is an ordinary OCI image.** clawk pulls it (no Docker daemon), flattens the layers, and writes an ext4 disk directly, with no root and no loop devices. Every sandbox from the same image is a copy-on-write clone (APFS`clonefile`\n\n/`FICLONE`\n\n), so per-sandbox disk cost is what the guest writes.**The network is filtered below the guest.** The VM's entire L3 (gateway, DHCP, DNS, NAT) is a userspace stack inside the daemon process. Every outbound connection and DNS answer consults the allow-list there, where even root inside the guest cannot change it. No host iptables, no sudo.**One way in.** No sshd, no cloud-init: a single vsock agent is the only control path into the guest, and each attach is container-exec-style: a fresh process, torn down on disconnect.\n\nThe full picture (the guest stack, both providers, the frame-level\nnetworking) is in ** ARCHITECTURE.md**, and the reasoning\nbehind each decision in\n\n**.**\n\n[DESIGN.md](/clawkwork/clawk/blob/main/DESIGN.md)**Containers & devcontainers.** They share your kernel and see your filesystem minus deny rules; a single kernel bug or a mistaken mount can expose the host. Devcontainer setups often bind-mount the host Docker socket to build images, handing the container control of the host daemon; clawk keeps Docker*inside*the VM instead. And there's no`Dockerfile`\n\n/`devcontainer.json`\n\nto write: any OCI image is the rootfs.**OS-level agent sandboxes.** Tools like Anthropic's sandbox-runtime apply process-level guardrails on your real machine: great for lightweight rules, but one policy mistake exposes everything (keychain included), and installs, background services, or a nested hypervisor are awkward to allow safely. clawk moves the whole workload onto a different machine.**General-purpose VM managers (e.g. Lima).** Lima gives you a Linux VM; clawk is a*workflow*on top of one: a VM per project with the repo mounted, an agent attached and authenticated, egress allow-listed by default and denials logged, agent conversations persisted across destroys, and a ticket mode that manages worktrees and PRs. (Under the hood both use Virtualization.framework.)**Cloud sandboxes.** Local-first: your code never leaves the machine, nothing is billed by the hour, and the worktree the agent edits is the one in your editor, live-mounted on macOS (the Linux provider currently bakes it in at create; see[Roadmap](#roadmap)). Cloud sandboxes fit fleets; clawk is for the machine on your desk.\n\nTwo boundaries do the work: the VM (the host filesystem is invisible except\nwhat you mount) and the outbound allow-list (enforced in userspace below the\nguest, for every protocol that can leave it). What clawk does **not** protect\nagainst:\n\n**Whatever you mount or allow is exposed.** Worktrees are writable, so an agent can commit bad code or push to any repo your forwarded ssh-agent can reach. Review what comes out of a sandbox like you'd review a stranger's PR.**Secrets you push in are visible.**`files ( … )`\n\nand`shares ( … )`\n\ncontents, forwarded env vars, and the Claude token are the agent's to read (and, if a destination is allow-listed, to send there). Share the minimum.**Hypervisor escapes.** clawk relies on Virtualization.framework/KVM isolation; it does not add defenses beyond them.\n\nIf you find a way to break a boundary (guest-to-host escape, network-filter\nbypass, credential leakage), please report it privately via\n[SECURITY.md](/clawkwork/clawk/blob/main/SECURITY.md).\n\n**What's the overhead?**\nThe first boot from an image pays a one-time rootfs build (pull → flatten →\next4). After that, disks are copy-on-write clones and the kernel direct-boots,\nwith no firmware and no installer. Idle VMs release memory down to ~1 GiB, stop\nautomatically after 30 idle minutes, and can be snapshotted to disk so they\ncost only storage.\n\n**Does it work on Intel Macs? Windows?**\nNo. macOS needs Apple silicon (macOS 14+). On Linux, the firecracker\nprovider works but is experimental (see\n[docs/commands.md](/clawkwork/clawk/blob/main/docs/commands.md#vm-providers)). No Windows support.\n\n**Do I need Docker installed?**\nNo. clawk pulls OCI images and builds bootable disks itself. Docker *images*\nare the input format; the Docker engine is not involved. (Running a Docker\ndaemon *inside* a sandbox is a separate, opt-in feature; see\n[Images](/clawkwork/clawk/blob/main/docs/images.md#guest-kernel-override) for the hardware and kernel\nrequirements.)\n\n**Why \"clawk\"?**\nThe mark is a claw; *clawkwork* is a play on *A Clockwork Orange*. A VM you\nwind up, set loose, and can always reset.\n\nNext up: running more sandboxes than your RAM can hold at once.\n\n**Idle stops that snapshot.** Manual suspend-to-disk shipped as`clawk snapshot`\n\n/`clawk resume`\n\n; next, the*automatic*idle stop uses it too, so dev servers survive the stop and a suspended sandbox costs only disk.**A cap on running VMs.** Instead of refusing a new VM when RAM is committed, suspend the least-recently-used sandbox to disk and start the new one.**Firecracker parity.** Live worktree propagation and host-file push on Linux.\n\nPre-1.0 and under active development, and evolving quickly: expect breaking changes between releases. The CLI surface changes least and internals most, but nothing is frozen until 1.0.\n\nIssues and PRs are welcome. See [CONTRIBUTING.md](/clawkwork/clawk/blob/main/CONTRIBUTING.md) to build\nand test, [ARCHITECTURE.md](/clawkwork/clawk/blob/main/ARCHITECTURE.md) for how it's built, and\n[DESIGN.md](/clawkwork/clawk/blob/main/DESIGN.md) for where it's headed.\n\n[Apache License 2.0](/clawkwork/clawk/blob/main/LICENSE). clawk vendors two third-party components under\ntheir own licenses (gvisor-tap-vsock, Apache-2.0; an hcsshim ext4 writer, MIT);\nsee [NOTICE](/clawkwork/clawk/blob/main/NOTICE).", "url": "https://wpnews.pro/news/show-hn-clawk-give-coding-agents-a-disposable-linux-vm-not-your-laptop", "canonical_source": "https://github.com/clawkwork/clawk", "published_at": "2026-07-13 14:02:03+00:00", "updated_at": "2026-07-13 14:49:24.256644+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-safety", "ai-tools", "ai-infrastructure"], "entities": ["Clawk", "Claude Code", "Codex", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/show-hn-clawk-give-coding-agents-a-disposable-linux-vm-not-your-laptop", "markdown": "https://wpnews.pro/news/show-hn-clawk-give-coding-agents-a-disposable-linux-vm-not-your-laptop.md", "text": "https://wpnews.pro/news/show-hn-clawk-give-coding-agents-a-disposable-linux-vm-not-your-laptop.txt", "jsonld": "https://wpnews.pro/news/show-hn-clawk-give-coding-agents-a-disposable-linux-vm-not-your-laptop.jsonld"}}