Sandbox orchestration for Claude Code. Launches an interactive Claude Code session inside a Podman container, with a credential gateway that strips and re-injects API keys outbound, scopes secrets per binary, and applies a YAML policy that controls egress and package trust.
Status: experimental. macOS (Apple Silicon) and Linux.
macOS host Linux host
├── openlock CLI (Bun) ├── openlock CLI (Bun)
├── openshell-gateway (port 18081) ├── openshell-gateway (port 18081)
└── Podman Machine (Apple HV) └── podman (rootless)
└── sandbox container └── sandbox container
Each openlock sandbox <path> call:
- Detects capabilities (js / py) from the project, picks an image and policy.
- Builds the supervisor + sandbox images via
podman buildif missing. - Starts the gateway (
cargo buildfirst run, ~1–2 min). - Bundles your repo with
git bundle, uploads it, pre-trusts/sandbox/repo. - Injects host git identity (
user.name/user.emailfromgit config --global). - Launches Claude Code inside the sandbox; outbound traffic flows through the gateway with credentials injected from your
openlock logintoken. - On exit, fetches sandbox commits back into your repo under
refs/sandbox/<session>/*. - Container persists (entrypoint is
sleep infinity) so you can resume the same session later. Re-runningopenlock sandbox <path>reattaches. - Stops the gateway when no other
openshell-sandbox-*containers remain.
curl -fsSL https://raw.githubusercontent.com/vessux/openlock/main/install.sh | bashDrops openlock into ~/.local/bin. Set OPENLOCK_INSTALL_DIR to override. The fork binaries (gateway, supervisor, openshell CLI) are fetched lazily on first run into ~/.cache/openlock/bin/.
- podman —
podman machinestarted on macOS, or a reachable rootless socket on Linux (systemctl --user enable --now podman.socket) gitclaudeCLI inside the sandbox is bundled into the container image — no host install needed
Verify with openlock doctor.
The golden path is install → doctor → init → validate → sandbox:
# Linux only: enable the podman API socket once
systemctl --user enable --now podman.socket
openlock doctor # check prerequisites, get actionable fixes
openlock init /path/to/your/repo # scaffold .openlock/ (interactive)
openlock validate /path/to/your/repo # lint the manifest + policy
openlock sandbox /path/to/your/repo # launch (path defaults to cwd)sandbox requires an .openlock/ (run openlock init first, or it errors). If you have no
credentials it runs openlock login (the Anthropic provider imports your Claude subscription
token from an isolated claude auth login). The first run also git inits the path if it
isn't a git repo yet, and (re)attaches the session.
# launch (or resume) a sandbox for a project
openlock sandbox /path/to/your/repo
# rebuild sandbox images
openlock update-images
# manage the gateway directly (start keeps it running across cleanups)
openlock gateway start|stop|statusAfter the session exits, sandbox commits are in your repo under refs/sandbox/<session>/*. Inspect with git log refs/sandbox/<session>/main and merge or cherry-pick as needed.
| Command | Purpose |
|---|---|
doctor |
Check system health and prerequisites |
setup |
Configure machine defaults (runtime, harness, provider) |
login |
Authenticate with the gateway |
logout |
Remove stored provider credentials |
providers |
List configured providers |
init [path] |
Scaffold .openlock/ for a project (interactive) |
validate [path] |
Validate .openlock/ config + policy |
sandbox [path] |
Create or resume a sandbox session |
list |
List all sessions |
status [name] |
Show session metadata + container state |
stop [name] |
Stop session containers (preserves state) |
clean [name] |
Tear down session (rm container + state + host refs) |
reap |
Stop idle sessions (no removal) |
shell [name] |
Open bash inside the session container |
exec [name] -- <cmd> |
Run a command inside the session container |
refs |
Inspect and promote sandbox commits to real branches |
report |
Collect diagnostic bundle for bug reports |
gateway start|stop|status |
Manage the gateway |
update-images [--no-cache] |
Rebuild sandbox container images |
complete <bash|zsh|fish> |
Print shell completion script |
cred-refresh |
Start the credential refresh service |
Sandbox boundary. Always reach into a session via
openlock shell/openlock exec— neverpodman execdirectly, which bypasses the supervisor (egress policy,cred_inject, and the per-binary credential gate stop applying). See Security & runtime.
- Installation & shell completion
- Sessions: picker & lifecycle
- Mounts, args & env
- Policies
- Security & runtime
- Agent config reference — for AI agents configuring openlock
containers/ Containerfiles for the four sandbox images
policies/ YAML egress + trust policies
providers/ Credential refresh config
src/cli.ts Entry point
src/sandbox/ Sandbox orchestration
src/cred-refresh/ Credential refresh service
src/validate-policy/ Policy linter
For working on openlock itself, clone the openshell-fork sibling at ./openshell-fork and run from source:
git clone -b main https://github.com/vessux/OpenShell.git openshell-fork
bun install
bun run src/cli.ts <subcommand>When ./openshell-fork/.git exists, openlock auto-detects dev mode and builds the gateway / supervisor / openshell CLI from source instead of fetching the pinned release. Dev mode also requires bun, cargo, and on macOS cargo-zigbuild.
Apache-2.0. See LICENSE.