Project-scoped Docker sandboxes for development and AI-agent workflows.
Project description
sbox-cli
Project-scoped Docker sandboxes for development and AI-agent workflows.
sbox creates persistent Docker containers for the current project, mounts the project into the container, and makes it easy to resume or list those sandboxes later.
sbox python:3.12
sbox
sbox ls
Features
- Persistent Docker containers by default
- Current project mounted into the container
- Workdir inside the container matches the host project path
- Project-aware sandbox lookup using Docker labels
- Optional read-only project mounts
- Git worktree support for branch-isolated agent work
- Docker flag pass-through
- Installable Python package powered by
uv
Requirements
- uv
- Docker
- Git, for worktree support
Installation
Install the sbox-cli package as a uv tool to make the sbox command available:
uv tool install sbox-cli
Usage
Create a sandbox:
sbox python:3.12
Create a sandbox and run a command:
sbox python:3.12 bash
sbox alpine sh
Resume or select an existing stopped sandbox for the current project:
sbox
List sandboxes for the current project:
sbox ls
Options
--sbox-name NAME
Use an exact Docker container name.
sbox --sbox-name auth-agent python:3.12 bash
The container will be named exactly:
auth-agent
No prefix, suffix, project name, image name, or date is added.
--sbox-ro
Mount the project read-only.
sbox --sbox-ro python:3.12 bash
Useful for inspection, review, or read-only agent runs.
--sbox-worktree BRANCH
Create or reuse a managed Git worktree and run the sandbox there.
sbox --sbox-worktree feature-auth python:3.12 bash
Managed worktrees live at:
<repo>/.sbox/worktrees/<branch>
The container mounts that worktree instead of the main checkout.
Docker flag pass-through
Docker options can be passed before the image:
sbox -p 127.0.0.1:8000:8000 python:3.12 bash
sbox --network none alpine sh
sbox --rm ubuntu:24.04 bash
sbox -e FOO=bar python:3.12 bash
sbox does not add --rm by default. Containers are kept unless you pass --rm yourself.
Naming
Generated container names use:
sbox-<repo-or-dir>__<image>-<YYYYMMDD>
sbox-<repo-or-dir>.<branch>__<image>-<YYYYMMDD> # with --sbox-worktree
Examples:
sbox-shop-api__python-3.12-20260611
sbox-shop-api.feature-auth__python-3.12-20260611
sbox-scripts__alpine-20260611
If --sbox-name is provided, that exact name is used instead.
Project detection
If run inside a Git repository, sbox uses the Git root as the project.
Otherwise, it uses the current working directory.
Sandboxes are associated with projects using Docker labels, so lookup does not rely only on container names.
Worktrees
sbox supports both user-managed and managed Git worktrees.
User-managed worktree:
git worktree add ../shop-api.feature-auth -b feature-auth
cd ../shop-api.feature-auth
sbox python:3.12 bash
Managed worktree:
cd shop-api
sbox --sbox-worktree feature-auth python:3.12 bash
Managed worktrees are stored under:
.sbox/worktrees/
sbox adds .sbox/ to .git/info/exclude, not .gitignore.
Lifecycle
Create a sandbox:
sbox python:3.12 bash
Exit the container shell when done.
Later, resume it from the same project:
sbox
If the matching sandbox is stopped, sbox starts and attaches to it.
If the matching sandbox is already running, sbox prints a message and does nothing.
Remove containers manually with Docker:
docker ps -a --filter label=sbox=true
docker rm CONTAINER
Remove managed worktrees manually with Git:
git worktree remove .sbox/worktrees/<branch>
Detach keys
sbox uses --detach-keys=ctrl-@ instead of Docker's default (Ctrl-p, Ctrl-q), which interferes with normal terminal usage of Ctrl-p (previous history, readline backward-char, etc.) inside the container.
Timezone
If $TZ is set, sbox passes it into the container:
export TZ=Asia/Tokyo
sbox python:3.12 bash
If $TZ is not set, no timezone variable is passed.
Security notes
sbox adds:
--security-opt no-new-privileges
--init
The project directory is bind-mounted into the container. In normal mode, it is writable.
For read-only access:
sbox --sbox-ro IMAGE
Avoid passing dangerous Docker options unless you understand the consequences, especially:
-v /var/run/docker.sock:/var/run/docker.sock
--privileged
Docker containers are not a hard security boundary.
Troubleshooting
Docker is not available
Check Docker:
docker version
uv is not found
Check uv:
uv --version
Container already exists
The generated or custom name already exists.
Resume/select it:
sbox
Or remove it manually:
docker rm CONTAINER
Sandbox is already running
sbox does not automatically enter running containers.
Use Docker directly if you intentionally want another shell:
docker exec -it CONTAINER sh
Permission issues on Linux
Some images run as root and may create root-owned files in the mounted project.
You can pass Docker's user option:
sbox --user "$(id -u):$(id -g)" IMAGE
Development
Run the CLI from a checkout:
uv run sbox ls
Format and auto-fix style issues:
npm run style:fix
Run tests and checks:
npm run test
npm run syntax:check
npm run package:check
npm run style:check
Preview the next semantic release without publishing:
npm run release:check
This requires the checkout to have an origin remote, matching the GitHub
Actions release environment.
Release
Releases are automated from Conventional Commits on main and published as the
sbox-cli package on PyPI.
Python Semantic Release updates pyproject.toml,
uv.lock, and CHANGELOG.md automatically.
Recommended branch protection checks for main:
Lint CommitsStatic ChecksTest Python 3.11Test Python 3.12Test Python 3.13Test Python 3.14
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sbox_cli-0.1.0.tar.gz.
File metadata
- Download URL: sbox_cli-0.1.0.tar.gz
- Upload date:
- Size: 10.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9164aa4093ee62c7993962ed654dcf520fc4549d76a92142bd55140291253c0b
|
|
| MD5 |
e013ff0482e39dd83b5fef16df575613
|
|
| BLAKE2b-256 |
2f2475e8c853ba4943484f21a6d7926e65eb76d88951297b7bad1c50fad4a7ff
|
Provenance
The following attestation bundles were made for sbox_cli-0.1.0.tar.gz:
Publisher:
release.yml on TimoSutterer/sbox-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sbox_cli-0.1.0.tar.gz -
Subject digest:
9164aa4093ee62c7993962ed654dcf520fc4549d76a92142bd55140291253c0b - Sigstore transparency entry: 1789829045
- Sigstore integration time:
-
Permalink:
TimoSutterer/sbox-cli@1d477ff9dd3bac73d8d1779a53838aee8832499b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/TimoSutterer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1d477ff9dd3bac73d8d1779a53838aee8832499b -
Trigger Event:
push
-
Statement type:
File details
Details for the file sbox_cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sbox_cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ada3d93727517ed67e66d292704c92dd502892d4cc446cf6a6b02ac17a342fe
|
|
| MD5 |
2e6468a50865bc88c002d4d3cdeb3d5d
|
|
| BLAKE2b-256 |
88244a8559376625a926bcc9206e0658e92e6fc31fe7e773d0c53c256e226057
|
Provenance
The following attestation bundles were made for sbox_cli-0.1.0-py3-none-any.whl:
Publisher:
release.yml on TimoSutterer/sbox-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sbox_cli-0.1.0-py3-none-any.whl -
Subject digest:
9ada3d93727517ed67e66d292704c92dd502892d4cc446cf6a6b02ac17a342fe - Sigstore transparency entry: 1789829097
- Sigstore integration time:
-
Permalink:
TimoSutterer/sbox-cli@1d477ff9dd3bac73d8d1779a53838aee8832499b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/TimoSutterer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1d477ff9dd3bac73d8d1779a53838aee8832499b -
Trigger Event:
push
-
Statement type: