Metadata-Version: 2.4
Name: trusted-agent
Version: 0.11.0
Summary: Run Claude Code inside a podman container, wrapped by gVisor.
Requires-Python: >=3.10
Description-Content-Type: text/markdown

Run claude code in an isolated container sandbox.

```bash
uvx trusted-agent claude --dangerously-skip-permissions "Do something"
```

## Backends

The backend is auto-selected from the host OS. Override with `--backend {auto,podman-gvisor,apple-container}`.

- **`podman-gvisor`** (Linux default) — rootless [podman](https://podman.io/) running images under [gVisor](https://gvisor.dev/)'s `runsc`. Two layers: container + user-space kernel. Requires `podman` and `runsc` on `PATH`.
- **`apple-container`** (macOS default) — Apple's native [`container`](https://github.com/apple/container) CLI. Each container runs in its own minimal Linux VM via `Virtualization.framework`, so the VM boundary is the sandbox. Requires Apple Silicon and macOS 15+ (macOS 26 recommended). If `container` is not installed, the tool prompts to install it via Homebrew (`brew install --cask container`); `container system start` is invoked automatically when the service is not running.

You need to be signed-in in claude-code on the host.

### Security delta on macOS

The Linux backend applies several defense-in-depth knobs that have no equivalent under Apple Container and are skipped there:

- `--cap-drop=ALL`, `--userns=keep-id`, `--security-opt=no-new-privileges`, `--pids-limit`, and the cgroup flags (`--cgroup-manager=cgroupfs`, `--runtime-flag=ignore-cgroups`).

Apple's `container` CLI does not expose any of these Linux-side knobs. On macOS the per-container Linux VM provides a hardware-backed isolation boundary that those flags were emulating in software.

## Agents

The first token of the command picks which host configs are projected into the sandbox. Unknown commands (e.g. `bash`) get no projections.

- `claude` (default) — `~/.claude.json`, `~/.claude/.credentials.json`, `~/.claude/settings.json`, `~/.claude/plugins/`.
- `opencode` — `${XDG_DATA_HOME:-~/.local/share}/opencode/` (auth tokens) and `${XDG_CONFIG_HOME:-~/.config}/opencode/` (config, agents, skills).
- `crush` — `${XDG_CONFIG_HOME:-~/.config}/crush/` and `${XDG_DATA_HOME:-~/.local/share}/crush/`.

Each set is copied to a temp dir before mounting, so token refreshes and in-session writes never touch the host originals. The bundled variants only ship `claude`; install `opencode` or `crush` in a custom variant Dockerfile to use them.

## Variants

Pick a pre-built image variant with `--variant NAME` (defaults to `default`):

- `default` — node + python + common dev tools.
- `nodejs` — adds `pnpm` and `yarn`.
- `rust` — adds the Rust stable toolchain (with clippy and rustfmt).
- `android` — adds JDK 17 and the Android SDK.

```bash
uvx trusted-agent --variant rust claude
```

Drop your own `Dockerfile` at `~/.config/trusted-agent/variants/<name>/Dockerfile` to add a variant. User variants take precedence over bundled ones with the same name. To extend the lean base, start your file with `FROM trusted-agent-default:latest`.

Image caches are not shared between backends — each backend builds into its own store on first use.


# Changelog

All notable changes to this project are documented in this file. The format is
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.11.0

### Added
- `trusted-agent --version` / `-V` prints the installed version and exits.
- Project `~/.claude/skills` (user-defined skills) into the sandbox, same
  throwaway-copy model as plugins.

### Fixed
- Plugin skills now load inside the sandbox: plugin metadata records
  absolute install paths under the host home, which are rewritten to the
  guest home when the plugins dir is projected.

## 0.10.0

### Added
- Project host configs for `opencode` and `crush` into the sandbox when those
  are the command being run. Claude Code remains the default and keeps its
  existing projections; running anything else (e.g. `bash`) projects nothing.
- Apple backend forwards the host's DNS servers (`--dns`) to both
  `container run` and `container build`. Works around apple/container#402:
  the gateway DNS proxy silently fails to start whenever another host
  service (e.g. Mullvad's local resolver) holds port 53, leaving containers
  without DNS.

### Fixed
- Apple backend now detects whether the `container` CLI uses `image` or
  `images` as its image-management subcommand (renamed in 0.6.0). The old
  hardcoded `images` made `image_exists` always fail, so every run rebuilt
  the image from scratch.
- On macOS, Claude Code stores its OAuth tokens in the login Keychain, not
  in `~/.claude/.credentials.json`; the credentials projection now falls
  back to the `Claude Code-credentials` Keychain item, so the sandbox no
  longer starts logged out.
- Homebrew install hint updated: `container` ships as a formula now, not a
  cask (`brew install container`).

## 0.7.2

### Fixed
- `nodejs` variant build no longer collides with the pnpm/yarn corepack
  shims that ship in `node:22-slim` (`npm install -g` now passes `--force`).

## 0.7.1

### Fixed
- `trusted-agent --help` / `-h` now prints local usage and exits instead of
  building the image and forwarding the flag to `claude` inside the sandbox.

## 0.7.0

### Added
- Image variants. The single Dockerfile is split into `default` (lean base
  with Python), `nodejs` (adds pnpm + yarn), `rust`, and `android`. Pick one
  with `--variant NAME`. Users can drop their own variant at
  `~/.config/trusted-agent/variants/<name>/Dockerfile`; user variants take
  precedence over bundled ones.

### Changed
- Image is now tagged `trusted-agent-<variant>:latest` instead of
  `trusted-agent:latest`. The old image is no longer built and can be removed
  with `podman image rm trusted-agent:latest`.
- `default` variant no longer bundles the Rust toolchain or the Android SDK;
  use `--variant rust` / `--variant android` to get them.

## 0.6.2

### Added
- Render the changelog on the PyPI project page alongside the README, via the
  `hatch-fancy-pypi-readme` build hook.

## 0.6.1

### Added
- Mirror the host's `~/.claude/plugins/` into the sandbox at container start so
  installed plugins are available without manual reinstall. Carries over
  `enabledPlugins` and `extraKnownMarketplaces` from the host's
  `~/.claude/settings.json` into the projected user settings.

## 0.5.0

### Added
- Bind-mount the git common dir for linked worktrees so git commands resolve
  inside the sandbox.
- Rust toolchain (stable, with clippy and rustfmt) and the Android SDK
  (cmdline-tools, platform-tools, API 34, build-tools 34.0.0) in the image.

## 0.3.0

### Added
- Install `uv` / `uvx` in the sandbox image.
- README with basic usage.

## 0.2.0

### Added
- First working version: run Claude Code inside a podman + gVisor sandbox with
  a projected `~/.claude.json`, projected credentials, and a `/workspace`
  bind-mount.
