返回资讯中心
外部精选
软件工程
#开发者实时流

safeagent 为每个代码工作树提供独立轻量 Linux 虚拟机,隔离并行编码会话

来源标题:Show HN: Safe and lightweight VMs for Coding agents

safeagent 为每个 git worktree 分配一台独立的小型 Linux 虚拟机,各自拥有进程、端口、Postgres、Valkey、Temporal 及数据副本,避免并行编码会话互相冲突,也防止代理执行的代码触达宿主机。它能从仓库自动读取锁文件、compose 文件和 env 中的地址,多数项目无需配置,并可直接接入 Claude Code,会话启动时在后台准备虚拟机。

Hacker News 最新msjpr2026/11/4 · 今天30 分钟阅读

以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。

A lightweight Linux VM for every checkout, so parallel coding sessions can't collide, and the code they run can't reach your machine.

Coding agents like Claude Code work best in parallel: several sessions, each in its own git worktree, each on its own task. Worktrees separate the files, but everything else is shared. Two sessions both want port 3000, one branch's migration breaks the other's database, and every command an agent runs has your whole machine within reach.

safeagent gives each worktree its own small Linux VM, with its own processes, ports, Postgres, Valkey (Redis) and Temporal, and its own copy of their data. It reads what it needs from the repository (lockfiles, compose files, monorepo packages, the local addresses its env files name), so most projects need no configuration. It plugs into Claude Code, so every worktree session gets one automatically and the VM is ready in the background while the session gets on with the work; with any other tool, safeagent create makes a workspace by hand.

Two real Claude Code sessions, recorded live with asciinema (idle time trimmed to 2 s; nothing else edited). As each session opens, safeagent prepares its workspace in the background (the VM, Postgres, Temporal, npm install, migrations), shown in the status line, while Claude gets on with the code. Each has its own database: both place order #1, and only the second, which merged a branch with a new migration, has a gift_note column.

Status: early development. macOS on Apple Silicon today; Linux hosts are being built. See What works today.

  1. Install safeagent on a Mac with Apple Silicon:

curl -fsSLO https://github.com/skerrysoft/safeagent/releases/latest/download/safeagent-darwin-arm64.tar.gz mkdir -p ~/.local/bin && tar -xzf safeagent-darwin-arm64.tar.gz -C ~/.local/bin # or anywhere on your PATH

Each release is built by GitHub Actions from this repository, with checksums (SHA256SUMS) and a signed build provenance attestation. To check a download was built here, before installing it:

gh attestation verify safeagent-darwin-arm64.tar.gz --repo skerrysoft/safeagent

Downloaded it with a browser instead? macOS then won't run it ("cannot be opened"), as it isn't notarized yet; clear the download flag with xattr -d com.apple.quarantine ~/.local/bin/safeagent.

git clone https://github.com/skerrysoft/safeagent && cd safeagent make build # bin/safeagent, signed to run VMs cp bin/safeagent ~/.local/bin/ # or anywhere on your PATH

  1. Connect it to Claude Code.

safeagent claude install

This shows the three hooks it will add to ~/.claude/settings.json (WorktreeCreate, WorktreeRemove, SessionStart), keeps a backup, and asks which folders to turn safeagent on for. safeagent only ever acts in those folders; everywhere else, worktrees stay plain worktrees.

The plugin carries the same three hooks (and a small script that finds the safeagent command), and nothing else. In any Claude Code session, from any folder:

/plugin marketplace add skerrysoft/safeagent /plugin install safeagent@safeagent

The first command adds this GitHub repository as a plugin marketplace; the second installs the plugin for your user, in every project. safeagent itself must still be installed (step 1), and it still only acts in the folders you enable (safeagent enable DIR). Use the plugin or safeagent claude install, not both: two WorktreeCreate hooks would both try to make the worktree.

  1. Start sessions in worktrees, as you already do.

claude --worktree fix-login

or turn on Worktree when starting a session in the Claude desktop app. Subagents and background sessions that use worktrees work the same way.

That's all. Optionally, show each workspace in Claude Code's status line, so you can see it being prepared (add to ~/.claude/settings.json):

"statusLine": { "type": "command", "command": "safeagent statusline" }

Without Claude Code (or with another agent), make a workspace yourself and work in it:

safeagent enable ~/code # once: safeagent acts only in folders you enable cd ~/code/shop safeagent plan # what safeagent found, before anything runs cd "$(safeagent create fix-login)" # a worktree that gets its own VM safeagent exec -- npm test # the first command boots and prepares it, then runs safeagent start # run the project's apps, forwarded to your machine safeagent status # services, apps, and where each is on your machine

What happens in a session

Claude creates the worktree through safeagent. In an enabled folder it becomes a workspace; elsewhere, a plain worktree, made the way Claude would make it.

The session opens right away, and safeagent prepares the workspace in the background: builds or reuses the VM image, boots the VM (about half a second), starts the services (Postgres, Valkey, Temporal), creates the databases, installs dependencies, builds, and runs the setup you configured. The first time for a project this takes a minute or two; after that, seconds. So the database is there when you run migrations or tests.

Nothing waits on that but the commands that need the VM. Claude can read and edit code and use git meanwhile. A command that needs the VM (npm test, say) waits for it, printing each step, and the status line shows where preparation has got to.

Commands go to the right place automatically. node, npm, npx, yarn, pnpm and corepack run in the VM, as do the commands of any other runtime the project lists (python, go, …). Everything else, git included, runs on your machine with your keys and settings. Claude is told how the workspace works when the session starts.

Your apps start when you start them, not before. Preparing a workspace never runs the project's own apps (its API, web app, workers). When your change is ready to try, run safeagent start (all of them) or safeagent start web (one, with the library watchers it needs), or ask Claude to. They run in the VM, restart if they crash, and are forwarded to your machine; safeagent stop stops them, and so does the VM stopping (safeagent down, or 30 minutes unused). Running your own dev command (npm run dev) works too: it runs in the VM like any other.

Removing the worktree removes the workspace: its VM and its data. Uncommitted work and branches with commits are never deleted.

How it works

One VM per workspace, on Apple's Virtualization framework: a small Linux kernel (Alpine's) and a userland built from signature-verified Wolfi packages, shared read-only by every workspace that needs the same runtimes and services. It boots in about half a second.

Your checkout, live. The worktree is shared into the VM at the same path (virtio-fs), so your editor, git and the VM all see the same files. Dependencies install into it as Linux builds.

Its own disks. Service data (Postgres, Valkey) and caches (the home directory, /tmp) live on sparse disk images of the workspace's own; the rest of the system is in memory.

A guest agent, the VM's first process, runs the services and apps and takes commands from safeagent over SSH on vsock, with keys pinned per workspace.

A user-mode network. The VM's network card connects to a network stack inside safeagent (gVisor's), which lets it reach the internet and nothing local. Ports are forwarded to your machine's 127.0.0.1.

Sized to the project: 4 CPUs and 3 GB by default, more memory for each service and app, within half your machine.

Configure a project

Most projects need no configuration. safeagent reads the files a project already has:

It also installs dependencies from the lockfile (npm ci, pnpm install --frozen-lockfile, uv sync --frozen, …), reads every package of a monorepo, gives each new workspace copies of your checkout's local .env files (so apps run as they do in your checkout), creates the local databases they point to, and builds what the apps import. safeagent itself reads env files only for local addresses, ports and variable names: every other value, and any password in a URL, is dropped as the file is read, and nothing from them is stored, printed or sent anywhere. It also finds the project's apps (packages with a dev script and a port, Procfile processes, Django's and Rails' dev servers), which safeagent start runs, with their ports forwarded to your machine; they never start on their own. safeagent plan shows all of it before anything runs, including how each app is wired: what in the VM answers at every local address its env files name, and what nothing does. To say exactly what a workspace needs, add a safeagent.yaml at the repository root:

services: [postgres, temporal] runtimes: [python@3.12] # Node is always there packages: [ffmpeg] # extra packages, by name setup: # in the VM, in order, when the data is new

  • npm ci
  • npm run migrate apps: [api, web] # what safeagent start runs ports: [3000] # forward another port to your machine

Setup runs once for a workspace's data, and again when its inputs change (dependencies, migrations, safeagent.yaml). The safeagent.yaml reference explains every key and exactly what runs when, in which order.

The services' variables are set for every command in the VM, so they win over the same names in a .env file (dotenv loaders don't override variables that are already set). safeagent status shows the services and the ports they are forwarded to on your machine; safeagent url postgres prints a URL, password included, for tools such as psql or a database GUI.

The checkout is never copied into the VM. Your worktree stays an ordinary folder on your machine; the VM sees the same folder, live, at the same path, through a shared file system. Git runs on your machine, not in the VM, so it works as it always does:

Code in the VM can't redirect your git: the worktree's .git pointer is locked, and repositories or Claude Code settings planted in the checkout are quarantined (see Security).

A workspace can start with real data, migrated for its own branch. A dump in the repository loads in safeagent.yaml (seed: {postgres: db/seed.sql.gz}); a dump that isn't (an anonymized copy of production, say) loads from your machine:

safeagent reset --empty && safeagent seed ~/dumps/prod.dump # in one workspace safeagent snapshot save # make it the default

Every new workspace of the repository then starts from that snapshot (on macOS, an APFS clone: instant, and taking no space until it changes) and runs its own branch's setup on top. safeagent reset goes back to the snapshot; safeagent snapshot ls and safeagent snapshot rm NAME manage them.

Snapshots and safeagent reset cover service data only. What commands keep in the VM's home directory and /tmp (package caches, downloaded browsers, build output) lives on a second disk of the workspace's own, so it doesn't take the VM's memory; the home directory keeps it across restarts, and /tmp starts empty. It is never in a snapshot, safeagent reset leaves it, and removing the workspace deletes it.

Workspaces run untrusted code: dependencies' install scripts, repository scripts, and whatever an agent decides to run. safeagent is built to contain it. Found a way out? Please report it privately, as SECURITY.md describes.

Each of these is tested by attacking a real VM from the inside (scripts/escape-test.sh), and the parsers that read VM or repository input are fuzzed.

The full threat model, and the rules every change is tested against, are in docs/design.md.

You rarely need these with Claude Code; these are the ones for working by hand:

Commands that act on a workspace use the one you're in, unless you name one.

Settings, through environment variables for now:

✅ Claude Code hooks: CLI, desktop app, subagents, background sessions; plugin verified

✅ One VM per workspace on macOS (Apple Silicon) ~0.5 s boot

✅ Preparation in the background, with progress in the status line and safeagent status

✅ Networking: internet yes; your machine, local network and cloud metadata no

✅ Services: Postgres 17 + pgvector, Valkey, Temporal; data kept per workspace

✅ Runtimes: Node, Python, Go, Ruby, Java, Bun, Deno; ex

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →