A container-based lab for humans and AI coding agents to think, plan, code, and operate in an experimental space protected by guardrails.
Why it's great:
- Works standalone - Want to run an AI agent within a environment with guardrails?
work-labIS your answer - Works with devcontainers - Run alongside any project's devcontainer via SSH tunnel
- Zero project changes - Never modifies your repos
- Safe agent execution - Run
claude --dangerously-skip-permissionswithout the danger - One command -
wl start && wl muxand you're in
| Your situation | Mode | What to do |
|---|---|---|
| Project has no devcontainer | Standalone | work-lab is your devcontainer |
| Project has existing devcontainer | Sidecar | Run both containers side-by-side |
Mental model: work-lab is where you think and operate. Project devcontainers are where things run. They do not need to be the same place.
work-lab is an optional, personal environment for:
- Thinking and planning
- Running coding agent tooling (Claude, Gastown, SageOx)
- Experimenting safely (e.g.
claude --dangerously-skip-permissions)
It provides a consistent safe environment for engaging with your tools and AI coding agents, independent of whatever project you're working on.
- Not a project template. This repo never modifies the projects you work on.
- Not a replacement for project devcontainers. If a project has its own devcontainer, that's where builds and services run.
- Not infrastructure. No databases, no services, no application orchestration.
Platform: Linux and macOS only. Windows is not currently supported (contributions welcome).
| Requirement | Purpose | Install |
|---|---|---|
| Docker | Container runtime | brew install --cask docker (or alternatives) |
| devcontainer CLI | Start containers from CLI | npm install -g @devcontainers/cli |
Optional:
Choose your preferred method:
brew tap modern-tooling/tap
brew install work-labcurl -fsSL https://raw.githubusercontent.com/modern-tooling/work-lab/main/install.sh | bashThis clones to ~/.local/share/work-lab (XDG compliant), creates config directory, and pulls the pre-built image.
Click "Use this template" at the top of this repo to create your own customized version.
git clone https://github.com/modern-tooling/work-lab.git ~/.local/share/work-lab
export PATH="$PATH:$HOME/.local/share/work-lab/bin"cd /path/to/your/project # Any git repository
work-lab doctor # Check your environment
work-lab start # Start the container
work-lab mux # Attach to tmux session (or zellij if configured)Inside the container:
cd /workspaces/project # Your project is mounted here
claude # or gt (gastown), opencode, aider, etc.work-lab start # Start the container
work-lab shell # Attach an interactive shell
work-lab mux # Attach to multiplexer (tmux default, or zellij)
work-lab stop # Stop the container
work-lab ps # List running work-lab containers
work-lab doctor # Check environment and configuration
work-lab version # Show version informationTip: Add a short alias to your shell profile (~/.bashrc or ~/.zshrc):
alias wl='work-lab'Then use:
wl start # Same as: work-lab start
wl mux # Same as: work-lab muxwork-lab is the devcontainer. One container does everything.
flowchart TB
WL[work-lab container<br/>think + edit + run]
Host[(Host filesystem<br/>~/projects/foo)]
WL -->|bind mount| Host
style WL fill:#4a9eff,stroke:#2d7ad9,color:#fff
When to use: Project has no devcontainer, or you don't need its build environment.
Why it works well:
- No repo changes required
- Safe agent execution
- Reproducible tools
- One mental model
Run work-lab alongside your project's devcontainer. Both containers mount the same project - work-lab handles AI agents, the devcontainer runs your entire development environment (builds, tests, services, databases, the works).
flowchart TB
WL[work-lab container<br/>think + agent]
Proj[project container<br/>build + test + services]
Host[(Host filesystem<br/>~/projects/foo)]
WL -->|bind mount| Host
Proj -->|bind mount| Host
WL -.->|SSH tunnel| Proj
style WL fill:#4a9eff,stroke:#2d7ad9,color:#fff
style Proj fill:#10b981,stroke:#059669,color:#fff
linkStyle 2 stroke:#888,stroke-dasharray:5
When to use: Project has its own devcontainer with specific build tools, services, or runtime.
| Container | Purpose |
|---|---|
| work-lab | Thinking, agents, operations |
| Project's devcontainer | Build, run, test, services |
The magic: From inside work-lab, run commands in the devcontainer:
wl dc npm test # runs in devcontainer
wl dc make build # runs in devcontainer
# prefix + S # SSH into devcontainer (from tmux)Zero configuration needed - just add the sshd feature to your devcontainer.json and work-lab handles the rest.
Key insight: You do NOT merge devcontainers. They run independently, sharing only the filesystem via the host.
Avoid: Nesting containers, sharing Docker sockets, syncing services. These lead to fragility.
You can always update your ~/.config/work-lab/post-create.sh to install additional tools into the base work-lab environment:
| Tool | Purpose |
|---|---|
| git, curl, jq, ripgrep, fzf | Standard utilities |
| Node.js 22 LTS | JavaScript runtime |
| Go 1.24 | Go runtime (for gastown) |
| tmux | Persistent terminal sessions (useful for coding orchestrator) |
| Claude CLI | AI coding agent (optional to use) |
| Beads | Task management for AI coding agents (optional to use) |
Gastown (gt) |
AI coding agent orchestrator (optional to use) |
Note:
work-labis not specifically for Gastown — it's a general-purpose environment for any AI coding agent. Gastown happens to be one of the best AI coding agent orchestrators as of January 2026, so it's included by default.
Future change: Claude Code may be removed as a pre-installed default in a future release. You can always install it via
~/.config/work-lab/post-create.shif needed.
work-lab mux # Attach to work-lab
cd /workspaces/project # Your project is already here
gt # Start Gastown orchestratorWhen you run work-lab start from any git repository, your project is automatically mounted to /workspaces/project in the container. No configuration needed for basic usage.
Customize work-lab via ~/.config/work-lab/ on your host (XDG convention):
| File | When it runs |
|---|---|
post-create.sh |
Once, after container creation |
post-start.sh |
Every time container starts |
Example: Install a custom coding agent:
mkdir -p ~/.config/work-lab
cat > ~/.config/work-lab/post-create.sh << 'EOF'
#!/usr/bin/env bash
npm install -g opencode
cargo install --locked zellij # install zellij tmux alternative [optional]
EOFSee examples/ for more examples.
work-lab provides container isolation for AI coding agents. This is especially valuable when running agents with elevated permissions.
Running claude --dangerously-skip-permissions on your host machine gives the agent access to everything your user can access:
- SSH keys (
~/.ssh) - Cloud credentials (
~/.aws,~/.config/gcloud) - Browser data, cookies
- All your documents
- System files
Running the same command inside work-lab limits the blast radius to only what's mounted:
flowchart LR
subgraph Host["Host (protected)"]
SSH["~/.ssh"]
AWS["~/.aws"]
end
subgraph Container["work-lab"]
Agent["claude --dangerously-skip-permissions"]
Project["/workspaces/project"]
end
HostProject["your-project/"]
Agent --> Project
Project -.->|bind mount| HostProject
style Host fill:#e8d4d4,stroke:#996666,color:#663333
style Container fill:#d4e8d4,stroke:#669966,color:#336633
style Agent fill:#4a9eff,stroke:#2d7ad9
| Resource | On host | In work-lab |
|---|---|---|
SSH keys (~/.ssh) |
Accessible | Not mounted |
Cloud credentials (~/.aws) |
Accessible | Not mounted |
| Browser data | Accessible | Not mounted |
| System files | Accessible | Container's own |
| Your project | Accessible | /workspaces/project |
Claude config (~/.claude) |
Accessible | Mounted read-only (default) |
XDG configs (~/.config/*) |
Accessible | User-controlled (RO or RW) |
Result: Agent autonomy (no permission prompts) with bounded risk. Users can mount additional configs via ~/.config/work-lab/config.
The one-liner install (curl | bash) and :latest Docker tags carry inherent supply chain risks. For higher security:
- Review before running: Download
install.sh, inspect it, then execute - Pin image versions: Use specific SHA digests instead of
:latest - Use Homebrew:
brew install work-labprovides formula review and checksums
- Boring is good. Plain bash. Standard tools. No frameworks. Complexity is allowed only when it serves security (SSH tunnel) or user experience (terminal integration).
- Optional always. Nothing here is required.
- No repo modifications. Projects remain untouched.
- Light tooling. Only add what reduces thinking during initial setup.
- Clear boundaries.
work-labprovides thinking space, project devcontainers run.