The binary has no runtime dependencies beyond a Docker socket.
Resources
10Install
npx skillscat add pacificbelt30/sandbox-codex Install via the SkillsCat registry.
SKILL.md — codex-dock Reusable Task Patterns
Domain-specific instructions and reusable patterns for AI agents working on
codex-dock.
Sources:doc/architecture.md,doc/auth-proxy.md,doc/commands.md,.golangci.yml,.github/workflows/ci.yml,README.md
1. Adding a New CLI Command
Pattern: All CLI commands use Cobra.
cmd/<name>.go ← Cobra command definition + flag binding
internal/<pkg>/ ← Business logic (keep cmd/ thin)Steps:
- Create
cmd/<name>.gowith avar <name>Cmd = &cobra.Command{...}. - Register it in
cmd/root.go(or whichever file callsrootCmd.AddCommand). - Bind flags with
viper.BindPFlagso they respect config file and env var precedence. - Implement business logic in
internal/<pkg>/. - Add a test in
internal/<pkg>/<name>_test.go. - Run
go vet ./...andgolangci-lint runbefore committing.
2. Adding a New Internal Package
Pattern: All business logic lives under internal/.
internal/<pkg>/
<pkg>.go ← Core implementation
<pkg>_test.go ← Unit tests- Export only what
cmd/needs. - Do not import
cmd/frominternal/(would create a cycle). - Error handling: return
errorvalues — never silently swallow errors.
3. Error Handling (errcheck Compliance)
The errcheck linter is enabled with check-type-assertions: true.
Do:
if err := someFunc(); err != nil {
return fmt.Errorf("context: %w", err)
}
// If truly ignorable, assign explicitly:
_ = optionalClose()Don't:
someFunc() // ❌ errcheck will fail
f.Close() // ❌ errcheck will failIn _test.go files, errcheck is relaxed — you may write someFunc() directly in tests.
4. Auth Proxy Token Lifecycle
Source:
doc/architecture.md,internal/authproxy/proxy.go
The Auth Proxy is the security boundary. When writing code that starts or stops containers:
Startup sequence (already implemented in cmd/run.go):
- Start Auth Proxy on a random host port (
127.0.0.1:<PORT>). - Issue a short-lived token:
proxy.IssueToken(containerName, ttl)→cdx-xxxx. - Pass
CODEX_TOKENandCODEX_AUTH_PROXY_URLas container env vars.
Shutdown sequence (F-AUTH-04 — not yet implemented):
// TODO: call this when container stops
proxy.RevokeToken(token)When implementing F-AUTH-04, call RevokeToken from sandbox.Manager.Stop() or the stop flow in cmd/run.go.
OAuth vs API key: The Auth Proxy auto-detects the mode by checking if ~/.codex/auth.json contains a refresh_token field. The /token endpoint returns either {"api_key": "..."} or {"oauth_access_token": "..."}.
5. Docker Container Creation Pattern
Source:
internal/sandbox/manager.go,internal/sandbox/types.go
RunOptions (defined in internal/sandbox/types.go) is the canonical input struct. Add new container parameters there, then read them in manager.go.
Security settings that must be preserved on every container:
HostConfig{
CapDrop: []string{"ALL"},
SecurityOpt: []string{"no-new-privileges"},
PidsLimit: ptr(int64(512)),
NetworkMode: "dock-net",
// ReadOnly applied via Mounts[0].ReadOnly
}Non-root user is enforced in docker/Dockerfile via USER codex (uid:1000).
6. Writing / Running Tests
Test packages covered by CI:
./internal/sandbox/..../internal/authproxy/..../internal/worktree/..../internal/config/...
Run all tests:
go test -race -coverprofile=coverage.out -covermode=atomic \
./internal/sandbox/... \
./internal/authproxy/... \
./internal/worktree/... \
./internal/config/...
go tool cover -func=coverage.outTest file naming: <file>_test.go in the same package. Use _test package suffix for black-box tests.
Race conditions: Always run with -race locally before pushing; CI enforces it.
7. Adding Configuration Options
Configuration uses Viper with this precedence:
CLI flags > CODEX_DOCK_* env vars > config.toml > built-in defaultsSteps:
- Add the field to the config struct (in
internal/config/if it exists, otherwise in Viper initialization). - Bind the Cobra flag:
viper.BindPFlag("field_name", cmd.Flags().Lookup("flag-name")). - Set an env var override:
viper.BindEnv("field_name", "CODEX_DOCK_FIELD_NAME"). - Document in
doc/configuration.mdandconfigs/config.toml.example.
8. Fixing Network Issues (F-NET-04)
Source:
doc/architecture.md,doc/network.md
Problem: Auth Proxy listens on 127.0.0.1 (host loopback), which is unreachable from containers on dock-net.
Fix pattern:
- Determine the docker bridge gateway IP for
dock-net(e.g.,192.168.200.1). - Bind the Auth Proxy listener to that IP instead of
127.0.0.1. - Set
CODEX_AUTH_PROXY_URL=http://192.168.200.1:<PORT>in the container env. - Add an iptables rule to allow only Auth Proxy traffic from dock-net containers.
This fix also enables full NF-SEC-01 compliance (TLS or UNIX socket).
9. TUI (Terminal UI) Patterns
Source:
internal/ui/ui.go,doc/commands.md
The TUI uses github.com/rivo/tview (backed by tcell). Refresh interval: 2 seconds.
Keybind registration pattern (Cobra-style for TUI):
switch event.Key() {
case tcell.KeyRune:
switch event.Rune() {
case 'S': // stop selected container
case 'D': // delete selected container
case 'A': // stop all containers
case 'R': // TODO: start container (F-UI-02 — unimplemented)
case 'Q': // quit
}
}Log view (F-UI-03): The log panel currently shows stub text. Fix by calling mgr.Logs(containerName) and feeding output to the tview TextView.
10. Pre-commit Checklist
Before every commit:
# 1. Format
gofmt -w ./...
# 2. Vet
go vet ./...
# 3. Lint
golangci-lint run --timeout=5m
# 4. Test
go test -race ./internal/sandbox/... ./internal/authproxy/... \
./internal/worktree/... ./internal/config/...
# 5. Module tidy (must produce no diff)
go mod tidy
git diff --exit-code go.mod go.sumAll five steps correspond to CI jobs (lint, vet, test, build) and must pass before pushing.
11. packages.dock File Format
Source:
doc/commands.md,internal/sandbox/packages.go
# Comment lines start with #
apt:libssl-dev # apt package
pip:requests # pip package
npm:typescript # npm package
libssl-dev # no prefix → treated as apt (F-PKG-05: auto-detection not implemented)When adding auto-detection for F-PKG-05, implement heuristics in internal/sandbox/packages.go.
12. Cross-Platform Build Targets
Source:
.github/workflows/ci.yml
| Target | Command |
|---|---|
| Linux amd64 (native CI) | go build -o codex-dock . |
| macOS arm64 | GOOS=darwin GOARCH=arm64 go build -o codex-dock-darwin-arm64 . |
| macOS amd64 | GOOS=darwin GOARCH=amd64 go build -o codex-dock-darwin-amd64 . |
| Linux arm64 | GOOS=linux GOARCH=arm64 go build -o codex-dock-linux-arm64 . |
The binary has no runtime dependencies beyond a Docker socket.