cooper

command module
v0.3.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 4, 2026 License: MIT Imports: 45 Imported by: 0

README

Cooper

Barrel-proof containers for undiluted AI

Run AI coding assistants in network-isolated Docker containers where every outbound request is visible, controllable, and reversible -- from a real-time TUI.

Why Cooper?

AI coding assistants need broad system access to be useful -- but that access is a liability. They can be prompt-injected into exfiltrating code through package registries, downloading malicious dependencies, or making unexpected network requests. Cooper solves this by running each AI tool in its own Docker container on a network that physically cannot reach the internet, with a Squid SSL-bump proxy as the only exit and a TUI control panel where you approve every non-whitelisted request in real time.

What you get:

  • No internet escape -- Containers run on a Docker --internal network with no gateway. Even raw sockets and curl --noproxy '*' can't get out. The Security Model enforces this at the Linux networking layer -- there is simply no route.
  • See every HTTPS request -- SSL bump decrypts TLS traffic so the Proxy Monitor shows complete URLs, methods, and headers -- not just domain names.
  • Approve requests in real time -- Non-whitelisted requests appear in the TUI Control Panel with a countdown timer and a short host-side alert phrase. Approve, deny, or let them timeout. One request at a time, no "always allow".
  • Access local host ports -- Forward PostgreSQL, Redis, dev servers, or any host service into barrels through Port Forwarding. Uses a two-hop socat relay so containers reach host services without any internet access.
  • Run scripts on host -- Let AI tools trigger deploy, restart, or test scripts through the Execution Bridge -- a controlled HTTP API that returns stdout/stderr without giving shell access to your machine.
  • Copy-paste images -- Paste screenshots and images into AI tools running inside containers with the Clipboard Bridge. Press c in the TUI to stage your clipboard -- AI tools inside barrels see it as a normal paste. Time-limited, per-barrel authenticated.
  • Run headed browsers -- Built-in Xvfb virtual display, Chromium dependencies, host font sync, and shared memory configuration for Playwright testing inside barrels -- headed mode works out of the box.
  • Multi-tool, multi-workspace -- Each AI tool gets its own container image. Open multiple barrels across different project directories, all monitored from one TUI.

Supported AI Tools

Tool Command Auto-approve flag
Claude Code cooper cli claude --dangerously-skip-permissions
GitHub Copilot CLI cooper cli copilot --allow-all-tools
OpenAI Codex CLI cooper cli codex --dangerously-bypass-approvals-and-sandbox
OpenCode cooper cli opencode --auto-approve

Auto-approve flags are safe because the container is already sandboxed -- Cooper's network isolation, seccomp profile, and capability restrictions replace each tool's built-in permission system.

Custom tools can be added by placing a Dockerfile in ~/.cooper/cli/{tool-name}/.

Supported Platforms

  • Linux: Any distro with Docker Engine 20.10+ and bash or zsh.
  • macOS (Apple Silicon): Docker Desktop 4.x+. Requires macOS 12+.
  • macOS (Intel): Docker Desktop 4.x+. Untested but expected to work.
  • Windows: Not supported.

How It Works

Cooper uses a dual-network architecture to enforce true network isolation at the Linux networking layer:

flowchart TB
    subgraph host["<b>HOST MACHINE</b>"]
        direction TB

        subgraph tui["<b>cooper up</b> &mdash; TUI Control Panel"]
            direction LR
            monitor["<b>Monitor</b><br/>Real-time request<br/>approve / deny"]
            bridge_api["<b>Execution Bridge</b><br/>localhost:4343"]
            clipboard["<b>Clipboard Manager</b><br/>TTL-based staging"]
        end

        host_services["<b>Host Services</b><br/>PostgreSQL, Redis,<br/>dev servers"]
    end

    subgraph external["<b>cooper-external</b> &mdash; bridge network <i>(has internet)</i>"]
        subgraph proxy_box["<b>cooper-proxy</b>"]
            direction TB
            squid["<b>Squid Proxy</b><br/>SSL bump on :3128"]
            socat_proxy["<b>socat relays</b><br/>port forwarding to host"]
        end
    end

    subgraph internal["<b>cooper-internal</b> &mdash; --internal network <i>(NO internet, NO gateway)</i>"]
        direction LR
        subgraph barrel1["<b>barrel-myproject-claude</b>"]
            claude["Claude Code<br/><i>auto-approve</i>"]
            tools1["Go + Node + Python<br/>Workspace mounted rw<br/>Cooper-managed caches rw"]
        end
        subgraph barrel2["<b>barrel-myproject-codex</b>"]
            codex["Codex CLI<br/><i>auto-approve</i>"]
            tools2["Same isolation,<br/>different AI tool"]
        end
    end

    allowed["<b>Allowed</b><br/>anthropic.com<br/>openai.com<br/>github.com"]
    denied["<b>Denied</b><br/>No route exists"]

    barrel1 -- "HTTPS_PROXY" --> squid
    barrel2 -- "HTTPS_PROXY" --> squid
    barrel1 -. "socat :4343" .-> socat_proxy
    barrel2 -. "socat :4343" .-> socat_proxy
    socat_proxy -- "host.docker.internal" --> host_services
    socat_proxy -- "host.docker.internal" --> bridge_api
    squid -- "Whitelisted" --> allowed
    squid -. "Non-whitelisted" .-> monitor
    monitor -. "approve / deny" .-> squid
    barrel1 --x denied
    barrel2 --x denied

Key insight: The cooper-internal network is created with Docker's --internal flag -- it has no default gateway and no route to any external network. Containers on this network can only reach each other via Docker DNS. Even if an AI tool ignores proxy environment variables, opens raw sockets, or runs curl --noproxy '*', it cannot reach the internet. There is simply no route.

The proxy container sits on both networks -- it receives traffic from barrels on the internal network and forwards whitelisted requests to the internet via the external network. Non-whitelisted requests are held pending in the TUI for your real-time approval.

Quick Start

Prerequisites
  • Linux: Docker Engine 20.10+
  • macOS: Docker Desktop 4.x+ (Docker Engine runs inside a Linux VM)
  • Go 1.21+ (for installation via go install)
  • bash or zsh
Install
go install github.com/rickchristie/govner/cooper@latest

Make sure Go's bin directory is in your PATH. If cooper isn't found after install, add this to your ~/.bashrc or ~/.zshrc:

export PATH="$PATH:$(go env GOPATH)/bin"
Setup
# 1. Interactive configuration wizard
#    Sets up programming tools, AI tools, proxy whitelist, port forwarding,
#    barrel environment variables
cooper configure

# 2. Build container images (proxy + base + per-tool CLI images)
cooper build

# 3. Start the control panel TUI (must be running before using barrels)
cooper up

# 4. Open a barrel (from your project directory)
cooper cli claude
Day-to-day usage
# Start the control panel (once per session)
cooper up

# Open barrels from any project directory
cd ~/myproject && cooper cli claude
cd ~/other-project && cooper cli codex

# Update tool versions (mirrors host or fetches latest, based on your config)
cooper update

# Verify the full stack works end-to-end
cooper proof

Commands

Command Description
cooper configure Interactive TUI wizard -- programming tools, AI tools, whitelist, ports, barrel env, bridge
cooper build Build proxy and all CLI container images. --clean for no-cache rebuild
cooper up Start proxy, bridge, and TUI control panel. Must be running for barrels to work
cooper update Regenerate Dockerfiles and rebuild only images with desired-vs-built drift, including implicit tools and base runtime changes
cooper cli <tool> Launch a barrel. -c "cmd" for one-shot execution. list to show available tools
cooper proof Full lifecycle integration test -- preflight through AI smoke test, then teardown
cooper cleanup Remove all containers, images, and networks. Optionally remove ~/.cooper

TUI Control Panel

The control panel (cooper up) is the nerve center. It has these tabs:

Tab What it does
Containers Live CPU/memory stats for all barrels and proxy. Stop/restart containers
Monitor Real-time pending requests to non-whitelisted domains. Approve/deny with countdown
Blocked History of denied requests with full details
Allowed History of approved requests with response status codes and headers
Bridge Logs Execution bridge invocations -- route, script, status, duration, stdout/stderr
Ports Port forwarding rules. Add/edit/delete live (applied via SIGHUP, no restart)
Routes Execution bridge mappings (API path to host script). Add/edit/delete at runtime
Runtime Monitor timeout, history limits, clipboard TTL/size, and proxy alert sound toggle. Changes take effect immediately
About Version info, installed tool versions vs host versions, implicit language servers, startup warnings

Clipboard bar is always visible at the top -- press c to copy an image from your host clipboard so AI tools can paste it, x to clear.

When a new request enters manual approval, Cooper can play one short host-side alert phrase. The Runtime tab includes a persisted checkbox for this, and it defaults to off so Cooper stays quiet unless you explicitly enable it. Linux uses PulseAudio or PipeWire's PulseAudio compatibility layer, macOS uses afplay, and if host audio is unavailable Cooper keeps running and disables the alert with a startup warning.

Configuration

All configuration lives in ~/.cooper/. Run cooper configure to change settings through the interactive wizard.

Programming Tools

Cooper detects Go, Node.js (npm/yarn/bun), and Python (pip/pipenv/poetry) on your host and offers three version modes:

Mode Behavior When to use
Mirror Matches your host machine version Keep container in sync with local dev
Latest Fetches latest stable from upstream APIs Always stay current
Pin Exact version you specify Reproducible builds

Built-in programming tools also install Cooper-managed standard language-server tooling, versioned from the selected runtime:

  • Go -> gopls
  • Node.js -> typescript-language-server and typescript
  • Python -> pyright and python-lsp-server

These are implicit defaults attached to the language tool, not separate top-level programming tools. TypeScript remains bundled under Node.js.

~/.cooper/config.json stores both desired configuration and built state. That built state includes top-level container_version values, resolved implicit_tools, and the built base Node runtime (base_node_version). cooper update and startup/About warnings compare those built values against the current desired state.

cooper configure save-only is allowed to reuse last-built implicit tool versions only when the relevant built runtime still matches the current desired runtime. If Cooper cannot prove that match, it fails instead of generating misleading Dockerfiles.

Run cooper update to apply Mirror/Latest changes after host upgrades. When built language-server versions or the effective base Node runtime drift from the current desired versions, startup warnings and the About tab surface that mismatch before you open barrels.

AI Tools

Same three version modes (Mirror/Latest/Pin) for each AI tool. Each enabled tool gets its own Docker image (cooper-cli-{tool}) built on top of cooper-base.

Custom Tools

Place a Dockerfile in ~/.cooper/cli/{name}/ using FROM cooper-base. Cooper builds it as cooper-cli-{name} and never overwrites user-created directories. Launch with cooper cli {name}.

Domain Whitelist

All traffic is blocked by default except:

  • AI provider API domains for enabled tools (anthropic.com, openai.com, etc.)
  • raw.githubusercontent.com (read-only, safe)

Package registries (npm, PyPI, Go proxy, crates.io) are blocked by default to prevent supply-chain attacks where an AI could be tricked into downloading malicious packages or exfiltrating data through registry requests. You can whitelist specific registries if needed, or approve individual requests through the TUI monitor.

Add trusted domains through cooper configure (company APIs, staging servers, metrics dashboards). For everything else, approve requests one at a time through the TUI monitor.

Port Forwarding

Forward host service ports into barrels (e.g., PostgreSQL, Redis, dev servers). Uses a two-hop socat relay: barrel -> proxy -> host.

Note (Linux): Host services must bind to 0.0.0.0 or the Docker gateway IP to be reachable from containers. Services bound to 127.0.0.1 are handled by Cooper's HostRelay, which transparently proxies connections from the gateway IP to localhost.

Note (macOS): Docker Desktop handles host access natively. Services on any bind address, including 127.0.0.1, are reachable from containers via host.docker.internal. No HostRelay is needed.

Barrel Environment

Use the Barrel Environment screen in cooper configure to define global env vars that are loaded into every later cooper cli session.

Example values:

API_BASE_URL=https://internal.example.com
FEATURE_FLAG=1
EMPTY=
  • Scope is global: the values live in ~/.cooper/config.json and apply to all barrels, tools, and workspaces.
  • Runtime-only: changes apply on the next cooper cli session. No cooper build is needed.
  • Precedence is safe: Cooper loads user env first, then restores protected runtime env such as HTTP_PROXY, PATH, TZ, DISPLAY, token env, terminal color/hyperlink policy and metadata env, IDE env, and COOPER_* names.
  • Protected names cannot be configured, including HTTP_PROXY, PATH, TZ, TERM, COLORTERM, NO_COLOR, FORCE_COLOR, OPENAI_API_KEY, and any COOPER_* variable.
  • Values are stored in plain text in ~/.cooper/config.json. This is not a secret store.
Execution Bridge

Map API routes to host scripts so AI tools can trigger actions without shell access:

/deploy-staging  ->  ~/scripts/deploy-staging.sh
/restart-dev     ->  ~/scripts/restart-dev.sh
/go-mod-tidy     ->  ~/scripts/go-mod-tidy.sh

Scripts should take no input and handle concurrency. Stdout/stderr is returned in the HTTP response.

Clipboard Bridge

Press c in the TUI to capture an image from your host clipboard. AI tools inside barrels see it as a normal paste -- no special commands needed.

  • User-initiated -- your clipboard is never passively exposed. You choose when to share.
  • Time-limited -- staged images expire after a configurable TTL (default 5 minutes).
  • Per-barrel authenticated -- each barrel gets a unique cryptographic token. No cross-barrel access.
  • Format support -- PNG, JPEG, GIF, BMP, TIFF, WebP, SVG (via ImageMagick). All converted to PNG.

Works transparently with every supported AI tool. Claude Code and OpenCode use shim scripts that intercept clipboard helper calls. Codex and Copilot use an X11 bridge that owns the virtual display clipboard. Custom tools get both strategies.

Configure TTL and max image size in the TUI Runtime Settings tab.

Playwright Support

Every barrel comes with the runtime environment Playwright needs for headless browser testing:

  • Chromium shared-library dependencies pre-installed
  • Xvfb virtual display (1920x1080) with authenticated X11
  • Baseline font set (DejaVu, Roboto, Noto, Noto CJK, Liberation, Noto Color Emoji)
  • Host fonts synced to ~/.cooper/fonts (mounted read-only into barrels)
  • Shared Playwright browser cache (~/.cooper/cache/ms-playwright, mounted read-write)
  • Configurable shared memory (barrel_shm_size, default 1g) -- Docker's default 64m is too small for browsers

Cooper does not install Playwright itself or download browsers. Your project provides npm install playwright and playwright install. When Playwright downloads browsers, the requests appear in the TUI monitor for approval.

Volume Mounts

Host Path Container Path Mode Purpose
Current directory Same path read-write Workspace
.git/hooks Same path read-only Prevent hook injection
~/.claude, ~/.claude.json /home/user/... read-write Claude Code auth/config
~/.copilot /home/user/.copilot read-write Copilot auth/history
~/.codex /home/user/.codex read-write Codex config
~/.config/opencode, ~/.local/share/opencode, ~/.local/state/opencode, ~/.opencode /home/user/... read-write OpenCode config, state, and install data
~/.gitconfig /home/user/.gitconfig read-only Git identity
~/.cooper/cache/go-mod /home/user/go/pkg/mod read-write Go module cache
~/.cooper/cache/go-build /home/user/.cache/go-build read-write Go build cache
~/.cooper/cache/npm /home/user/.npm read-write npm cache
~/.cooper/cache/pip /home/user/.cache/pip read-write pip cache
~/.cooper/tmp/{container} /tmp read-write Per-barrel temp directory

Language caches are Cooper-managed under ~/.cooper/cache/, auto-configured based on which programming tools are enabled. They start empty and fill naturally during normal package-manager usage. Each barrel gets its own host-backed /tmp directory, isolated per container to avoid collisions between barrels sharing a workspace. Cooper clears the entire ~/.cooper/tmp/ tree whenever cooper up starts and whenever it shuts down, so every control-plane session begins and ends with a pristine temp area.

Security Model

Layer Mechanism
Network --internal Docker network -- no gateway, no route to internet
Proxy Squid SSL bump with domain whitelist and real-time approval
Capabilities --cap-drop=ALL -- all Linux capabilities dropped
Privileges --security-opt=no-new-privileges
Seccomp Custom profile allowing bubblewrap (for Codex) while restricting everything else
Process --init for proper PID 1 signal handling
CA Per-installation local CA for TLS interception, never shared
Git hooks .git/hooks mounted read-only to prevent injection
Dependencies Package registries blocked by default; caches Cooper-managed under ~/.cooper/cache/
Clipboard User-initiated, time-limited, per-barrel authenticated, fail-closed

Adding Dependencies

Package registries are blocked by default. To install dependencies inside a barrel, either whitelist the needed registries in cooper configure or approve individual requests through the TUI monitor.

# Inside a barrel (after whitelisting registries or approving via monitor):
go mod download          # cached in ~/.cooper/cache/go-mod
npm install              # cached in ~/.cooper/cache/npm
pip install -r req.txt   # cached in ~/.cooper/cache/pip

Caches persist across barrel runs under ~/.cooper/cache/, so subsequent installs are fast.

Troubleshooting

Run the full diagnostic suite
cooper proof

This stands up the entire stack, tests SSL, proxy, tools, AI CLI connectivity, port forwarding, and bridge -- then tears everything down. Output is designed to be copy-pasted into a GitHub issue.

Check logs
# Command logs
ls ~/.cooper/logs/

# Proxy logs (from running container)
docker logs cooper-proxy
Rebuild everything
# Clean rebuild (no Docker cache)
cooper build --clean
Remove everything
cooper cleanup

License

MIT

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
cmd
acl-helper command
cooper-x11-bridge command
cooper-x11-bridge is an X11 CLIPBOARD selection owner that runs inside Docker containers.
cooper-x11-bridge is an X11 CLIPBOARD selection owner that runs inside Docker containers.
internal
aclsrc
Package aclsrc embeds the ACL helper source files so they can be written into the proxy Docker build context.
Package aclsrc embeds the ACL helper source files so they can be written into the proxy Docker build context.
app
Package app defines the App interface -- the boundary between the TUI (presentation) and business logic (infrastructure).
Package app defines the App interface -- the boundary between the TUI (presentation) and business logic (infrastructure).
configure
Package configure implements the interactive TUI wizard for `cooper configure`.
Package configure implements the interactive TUI wizard for `cooper configure`.
logging
Package logging provides a simple file logger with rotation for Cooper.
Package logging provides a simple file logger with rotation for Cooper.
proof
Package proof implements the `cooper proof` diagnostic command — a fully self-contained integration test that stands up the entire Cooper stack, validates every layer (networking, proxy, SSL, tools, AI CLIs), and tears it down.
Package proof implements the `cooper proof` diagnostic command — a fully self-contained integration test that stands up the entire Cooper stack, validates every layer (networking, proxy, SSL, tools, AI CLIs), and tears it down.
pubsub
Package pubsub provides a generic, unbounded, concurrent-safe publish-subscribe broker.
Package pubsub provides a generic, unbounded, concurrent-safe publish-subscribe broker.
squidlog
Package squidlog provides a file tailer for the Squid access log.
Package squidlog provides a file tailer for the Squid access log.
tableutil
Package tableutil provides a reusable table renderer for TUI screens.
Package tableutil provides a reusable table renderer for TUI screens.
testdriver
Package testdriver provides a reusable runtime driver for Cooper.
Package testdriver provides a reusable runtime driver for Cooper.
tui
tui/about
Package about implements the About tab sub-model.
Package about implements the About tab sub-model.
tui/bridgeui
Package bridgeui implements the Bridge Logs tab sub-model.
Package bridgeui implements the Bridge Logs tab sub-model.
tui/events
Package events defines shared message types used by both the root tui package and the tab sub-model packages (proxymon, containers, loading, etc.).
Package events defines shared message types used by both the root tui package and the tab sub-model packages (proxymon, containers, loading, etc.).
tui/history
Package history provides a reusable two-pane list+detail model for the Blocked and Allowed history tabs.
Package history provides a reusable two-pane list+detail model for the Blocked and Allowed history tabs.
tui/loading
Package loading implements the Loading and Shutdown screens for the Cooper TUI.
Package loading implements the Loading and Shutdown screens for the Cooper TUI.
tui/portfwd
Package portfwd implements the Port Forwarding tab sub-model.
Package portfwd implements the Port Forwarding tab sub-model.
tui/settings
Package settings implements the Runtime tab sub-model.
Package settings implements the Runtime tab sub-model.
tui/squidlog
Package squidlog implements the Squid Logs tab sub-model.
Package squidlog implements the Squid Logs tab sub-model.
tui/theme
Package theme holds shared type definitions, constants, and pre-computed styles used by both the root tui package and the tui/components sub-package.
Package theme holds shared type definitions, constants, and pre-computed styles used by both the root tui package and the tui/components sub-package.
x11src
Package x11src embeds the cooper-x11-bridge source so it can be written into the base Docker build context.
Package x11src embeds the cooper-x11-bridge source so it can be written into the base Docker build context.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL