> ## Documentation Index
> Fetch the complete documentation index at: https://docs.clawker.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> System layers, package DAG, CLI commands, and key abstractions

# Architecture

## System Overview

Clawker is a CLI tool plus two long-lived daemons — `clawkercp` (the control plane, one per host) and `clawkerd` (one per agent container) — that together manage isolated Docker containers for AI coding agents. The CLI is the root of trust; the daemons hold the security boundary at runtime.

```
┌────────────────────────────────────────────────────────────────────────────┐
│  CLI Layer                                                                  │
│  cmd/clawker → internal/clawker → internal/cmd/root                         │
│  12 command groups, 50+ subcommands (Cobra, Factory DI)                    │
└──────┬──────────────────────────┬──────────────────────┬────────────────────┘
       │                          │                      │
       ▼                          ▼                      ▼
┌──────────────┐    ┌─────────────────────┐    ┌────────────────────────────┐
│ Container    │    │ Configuration       │    │ Control Plane              │
│ Subsystem    │    │ Subsystem           │    │ (cmd/clawkercp, PID 1     │
│              │    │                     │    │  of clawker-controlplane)  │
│ docker/      │    │ storage/ (engine)   │    │                            │
│ workspace/   │    │ config/ (project)   │    │ AdminService gRPC (mTLS    │
│ containerfs/ │    │ config/ (settings) │    │  + OAuth2): 13 firewall    │
│ bundler/     │    │ project/ (registry) │    │  RPCs + ListAgents         │
│              │    │ storeui/ (TUI edit) │    │ AgentService gRPC (mTLS):  │
│ pkg/whail    │    │                     │    │  clawkerd Register +       │
│ (engine lib) │    │                     │    │  Session command channel   │
└──────┬───────┘    └─────────────────────┘    │ Ory auth stack (Hydra,     │
       │                                       │  Kratos, Oathkeeper)       │
       ▼                                       │ Agent sqlite registry      │
  moby/moby (Docker SDK)                       │ Overseer event bus         │
                                               │ Owns: firewall (Envoy +    │
                                               │  CoreDNS) + eBPF cgroup    │
                                               │  programs + dns_cache map  │
                                               │ netlogger (drains          │
                                               │  events_ringbuf → emits    │
                                               │  ebpf-egress OTLP logs)    │
                                               └──────────┬─────────────────┘
                                                          │ mTLS Session
                                                          ▼
                                               ┌────────────────────────────┐
                                               │ clawkerd                   │
                                               │ (PID 1 of every agent      │
                                               │  container; ENTRYPOINT)    │
                                               │                            │
                                               │ Inbound mTLS gRPC :7700    │
                                               │ Forks user CMD with kernel-│
                                               │  side privilege drop       │
                                               │ Two-phase orphan reaper    │
                                               │ Signal forwarding to child │
                                               │  pgroup                    │
                                               └────────────────────────────┘
```

The control plane is **not** the firewall — it is the supervisor that, among other things, owns the firewall lifecycle. See [Control Plane](/control-plane) for the user-facing CP guide and [Firewall](/firewall) for the firewall guide.

## CLI Command Structure

Commands are organized under `internal/cmd/` with subpackages per subcommand:

| Command Group  | Subcommands                                                                                                                              | Purpose                                                                             |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `container`    | list, run, start, stop, kill, exec, attach, logs, inspect, cp, pause, unpause, restart, rename, remove, stats, top, update, wait, create | Docker container management                                                         |
| `image`        | list, build, inspect, remove, prune                                                                                                      | Image lifecycle                                                                     |
| `volume`       | list, create, inspect, remove, prune                                                                                                     | Volume management                                                                   |
| `network`      | list, create, inspect, remove, prune                                                                                                     | Network management                                                                  |
| `project`      | init, register, list, info, edit, remove                                                                                                 | Project registration and config                                                     |
| `worktree`     | add, list, prune, remove                                                                                                                 | Git worktree management                                                             |
| `firewall`     | status, list, add, remove, reload, refresh, up, down, enable, disable, bypass, rotate-ca                                                 | Egress firewall control (all RPCs route through `f.AdminClient` to the CP daemon)   |
| `controlplane` | up, down, status, agents                                                                                                                 | Break-glass control plane lifecycle + registered agent listing                      |
| `auth`         | rotate                                                                                                                                   | CLI-side auth material (CA, server certs, OAuth2 signing key)                       |
| `monitor`      | init, up, down, status                                                                                                                   | Observability stack (OTel Collector, OpenSearch, OpenSearch Dashboards, Prometheus) |
| `settings`     | edit                                                                                                                                     | User settings TUI editor                                                            |
| `skill`        | install, show, remove                                                                                                                    | Manage the clawker-support Claude Code plugin                                       |

**Top-level shortcuts**: `init` → `project init`, `build` → `image build`, `run`/`start` → `container run`/`start`, `generate`, `version`

Shared domain logic (container creation) lives in `shared/` subpackages within each command group — not in library packages.

## Package Dependency Graph

Packages follow a strict DAG with no cycles. Verified via `goda`.

### Leaf Packages (zero internal imports)

Importable by anyone. Depend only on stdlib or external libraries.

| Package     | Purpose                                                                                    |
| ----------- | ------------------------------------------------------------------------------------------ |
| `storage`   | Generic layered YAML store engine (`Store[T]`): discovery, merge, provenance, atomic write |
| `git`       | Git operations, worktree management (go-git)                                               |
| `logger`    | Struct-based zerolog (file rotation + optional OTEL bridge)                                |
| `text`      | Pure ANSI-aware text utilities (Truncate, PadRight, StripANSI)                             |
| `term`      | Terminal capabilities + raw mode (sole `x/term` gateway)                                   |
| `signals`   | OS signal utilities (SetupSignalContext, ResizeHandler)                                    |
| `build`     | Build-time metadata (version, date via ldflags)                                            |
| `update`    | Background GitHub release checker (24h cached)                                             |
| `keyring`   | Credential storage service                                                                 |
| `pkg/whail` | Reusable Docker engine library with label-based isolation                                  |

### Foundation Packages (import leaves only)

Universally imported infrastructure. Their imports are leaf-only.

| Package     | Imports    | Purpose                                                                                                 |
| ----------- | ---------- | ------------------------------------------------------------------------------------------------------- |
| `config`    | storage    | Config loading/validation, schema types, path resolution. Composes `Store[Project]` + `Store[Settings]` |
| `iostreams` | term, text | I/O streams, TTY detection, colors, styles, spinners, progress                                          |

### Domain Packages (import leaves + foundation)

Core business logic. Import leaves and foundation packages only.

| Package                                | Imports                                                                                                | Purpose                                                                                                                                                                                                                                                      |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `project`                              | config, git, logger, storage, text                                                                     | Project registration, worktree lifecycle, registry CRUD                                                                                                                                                                                                      |
| `bundler`                              | config + own subpkgs                                                                                   | Dockerfile generation, content hashing, semver, npm registry                                                                                                                                                                                                 |
| `tui`                                  | iostreams, text                                                                                        | BubbleTea models, viewports, panels, progress display                                                                                                                                                                                                        |
| `prompter`                             | iostreams                                                                                              | Interactive prompts with TTY/CI awareness                                                                                                                                                                                                                    |
| `storeui`                              | iostreams, storage, tui                                                                                | Generic TUI editor for `Store[T]` instances                                                                                                                                                                                                                  |
| `controlplane`                         | config, docker, logger, ory subprocess managers                                                        | CP daemon core: AdminService composition, Ory auth stack, startup orchestrator, agent watcher                                                                                                                                                                |
| `controlplane/agent`                   | auth, consts, dockerevents, overseer, logger                                                           | CP-side agent surface: Dialer, sqlite Registry, Register handler, IdentityInterceptor, session/agent events                                                                                                                                                  |
| `controlplane/overseer`                | logger                                                                                                 | Typed event bus + in-memory `State` worldview (containers + agents)                                                                                                                                                                                          |
| `controlplane/dockerevents`            | overseer, logger                                                                                       | Docker events feeder (reconnecting stream → typed events on overseer bus)                                                                                                                                                                                    |
| `controlplane/cpboot`                  | config, docker, logger (+ embedded clawkercp + ebpf-manager binaries)                                  | Host-side CP lifecycle: `EnsureRunning`/`Stop`/`CPRunning`                                                                                                                                                                                                   |
| `controlplane/adminclient`             | auth, consts                                                                                           | CLI-side AdminService gRPC dial (mTLS + auto-refreshing OAuth2 bearer)                                                                                                                                                                                       |
| `controlplane/firewall`                | config, docker, logger, storage, controlplane/firewall/ebpf                                            | Firewall `Handler` (13 RPCs), `Stack` (Envoy+CoreDNS lifecycle), `ActionQueue`, config generators, certificate PKI, rules store                                                                                                                              |
| `controlplane/firewall/ebpf`           | logger                                                                                                 | eBPF program loader/manager, `SyncRoutes` replaces global `route_map` atomically; break-glass `ebpf-manager` CLI under `cmd/`                                                                                                                                |
| `controlplane/firewall/ebpf/netlogger` | controlplane/firewall/ebpf, controlplane/overseer, controlplane/dockerevents, docker, logger, OTel SDK | Per-decision-point egress event emitter — drains the BPF `events_ringbuf`, enriches by cgroup ID with container/agent/project attribution via overseer enrollment events, emits OTLP log records via a `*sdklog.LoggerProvider` (`service.name=ebpf-egress`) |
| `dnsbpf`                               | controlplane/firewall/ebpf                                                                             | CoreDNS plugin that writes DNS resolutions to the BPF `dns_cache` map in real time (embedded in `cmd/coredns-clawker`)                                                                                                                                       |
| `clawkerd/embed`                       | (embed only)                                                                                           | embeds the compiled per-container daemon binary; bundler drops it into every per-project image at `/usr/local/bin/clawkerd`                                                                                                                                  |
| `hostproxy`                            | config, logger                                                                                         | Host proxy for container-to-host communication                                                                                                                                                                                                               |
| `socketbridge`                         | config, logger                                                                                         | SSH/GPG agent forwarding via muxrpc                                                                                                                                                                                                                          |
| `containerfs`                          | config, keyring, logger                                                                                | Host config preparation for container init                                                                                                                                                                                                                   |
| `monitor`                              | config                                                                                                 | Observability stack templates (OTel Collector, OpenSearch, OpenSearch Dashboards, Prometheus)                                                                                                                                                                |
| `docs`                                 | config, storage                                                                                        | CLI documentation generation                                                                                                                                                                                                                                 |

### Composite Packages (import domain packages)

Higher-level subsystems that compose domain packages.

| Package     | Key Imports                                                | Purpose                                                    |
| ----------- | ---------------------------------------------------------- | ---------------------------------------------------------- |
| `docker`    | bundler, config, pkg/whail, pkg/whail/buildkit             | Clawker middleware wrapping whail with labels/naming       |
| `workspace` | config, docker, logger                                     | Bind vs Snapshot strategies                                |
| `cmdutil`   | config, docker, iostreams, tui, + type imports for Factory | Factory struct (DI container), error types, arg validators |

### Import Rules

```
  OK:  foundation → leaf           (config → storage)
  OK:  domain → leaf               (firewall → storage)
  OK:  domain → foundation         (project → config)
  OK:  composite → domain          (docker → bundler)

  BAD: leaf → anything internal    (storage must never import config)
  BAD: foundation ↔ foundation     (config must never import iostreams)
  BAD: any cycle                   (A → B → A is always wrong)
```

## Configuration and Storage

Three packages form the configuration subsystem:

* **`storage`** (leaf) — Generic `Store[T]` engine. Handles file discovery (static paths + walk-up), YAML loading with migrations, N-way merge with provenance tracking, and atomic writes. Zero domain knowledge.
* **`config`** — Thin domain wrapper composing `Store[Project]` + `Store[Settings]`. Exposes the `Config` interface with schema types, path helpers, and \~40 accessor methods.
* **`project`** — Project domain layer. Owns the `registry.yaml` project registry via its own `Store[ProjectRegistry]`. Handles registration CRUD, path resolution, worktree lifecycle.

Commands access config through the `Config` interface and `ProjectManager` interface — never `storage` directly.

## Dependency Injection: The Factory Pattern

Follows the GitHub CLI's three-layer pattern:

1. **Wiring** (`internal/cmd/factory/`) — Creates `*cmdutil.Factory` with all deps as `sync.Once` closures. Called once at entry point. Tests never import this.

2. **Contract** (`internal/cmdutil/`) — `Factory` is a pure struct with closure fields. Eager: `Version`, `IOStreams`, `TUI`. Lazy: `Config`, `Client`, `ProjectManager`, `GitManager`, `HostProxy`, `SocketBridge`, `AdminClient`, `ControlPlane`, `HttpClient`, `Logger`, `Prompter`.

3. **Consumers** (`internal/cmd/*/`) — Cherry-pick Factory closures into per-command `Options` structs. Run functions accept `*Options` only.

```go theme={"dark"}
func NewCmdStop(f *cmdutil.Factory, runF func(*StopOptions) error) *cobra.Command {
    opts := &StopOptions{
        IOStreams: f.IOStreams,
        Client:   f.Client,  // closure, not call
    }
}

func stopRun(ctx context.Context, opts *StopOptions) error {
    client, err := opts.Client(ctx)  // resolved lazily here
}
```

## Key Abstractions

| Abstraction                          | Package                                         | Purpose                                                                                                                                                         |
| ------------------------------------ | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `storage.Store[T]`                   | `internal/storage`                              | Generic layered YAML store with merge, provenance, and atomic write                                                                                             |
| `config.Config`                      | `internal/config`                               | Typed config interface composing `Store[Project]` + `Store[Settings]`                                                                                           |
| `project.ProjectManager`             | `internal/project`                              | Project identity, registration CRUD, worktree orchestration                                                                                                     |
| `whail.Engine`                       | `pkg/whail`                                     | Reusable Docker engine with label-based resource isolation                                                                                                      |
| `docker.Client`                      | `internal/docker`                               | Clawker middleware (labels, naming) wrapping whail                                                                                                              |
| `cmdutil.Factory`                    | `internal/cmdutil`                              | DI struct (closure fields); constructor in `cmd/factory`                                                                                                        |
| `CreateContainer()`                  | `internal/cmd/container/shared`                 | Single entry point for container creation                                                                                                                       |
| `adminclient.Dial`                   | `internal/controlplane/adminclient`             | CLI-side AdminService gRPC dial (mTLS + OAuth2)                                                                                                                 |
| `firewall.Handler`                   | `internal/controlplane/firewall`                | 13-method AdminService firewall surface inside the CP daemon                                                                                                    |
| `firewall.Stack`                     | `internal/controlplane/firewall`                | Envoy + CoreDNS container lifecycle                                                                                                                             |
| `dnsbpf.Handler`                     | `internal/dnsbpf`                               | CoreDNS plugin populating the BPF `dns_cache` map in real time                                                                                                  |
| `ebpf.Manager`                       | `internal/controlplane/firewall/ebpf`           | BPF program loader; `SyncRoutes` replaces the global `route_map` atomically                                                                                     |
| `netlogger.Service`                  | `internal/controlplane/firewall/ebpf/netlogger` | Drains BPF `events_ringbuf`, enriches by `cgroup_id`, emits OTLP log records (`service.name=ebpf-egress`) on the trusted infra lane                             |
| `controlplane.NewOtelLoggerProvider` | `internal/controlplane`                         | Generic `*sdklog.LoggerProvider` factory (mTLS + infra cert, BatchProcessor, optional ExporterWrap) reused by netlogger and any future CP-side OTLP log emitter |
| `cpboot.Manager`                     | `internal/controlplane/cpboot`                  | Host-side CP container lifecycle (`EnsureRunning`/`Stop`/`CPRunning`)                                                                                           |
| `agent.Registry`                     | `internal/controlplane/agent`                   | sqlite-backed agent identity (CP is sole writer)                                                                                                                |
| `overseer.Overseer`                  | `internal/controlplane/overseer`                | Typed event bus + worldview state inside CP                                                                                                                     |
| `cmd/clawkercp`                      | `cmd/clawkercp`                                 | CP daemon entry point — PID 1 of the `clawker-controlplane` container                                                                                           |
| `cmd/clawkerd`                       | `cmd/clawkerd`                                  | Entrypoint for the per-container agent daemon — PID 1 of every agent container                                                                                  |
| `cmd/coredns-clawker`                | `cmd/coredns-clawker`                           | Custom CoreDNS entrypoint embedding `dnsbpf`; built into `clawker-coredns:latest` on demand                                                                     |
| `tui.TUI`                            | `internal/tui`                                  | Factory noun for presentation layer                                                                                                                             |

## Container Naming and Labels

**Container names**: `clawker.project.agent` (3-segment) or `clawker.agent` (2-segment when project is empty)

**Volume names**: `clawker.project.agent-purpose` (purposes: `workspace`, `config`, `history`)

**Labels** (all under `dev.clawker.*`):

| Label     | Purpose                                 |
| --------- | --------------------------------------- |
| `managed` | `true` — authoritative ownership marker |
| `project` | Project name (omitted when empty)       |
| `agent`   | Agent name                              |
| `version` | Clawker version                         |
| `image`   | Source image reference                  |

Labels are authoritative for resource ownership. Names are for human readability. Clawker refuses to operate on resources without `dev.clawker.managed=true`.

## Presentation Layer

Commands follow a 4-scenario output model:

| Scenario           | Description                     | Packages                 |
| ------------------ | ------------------------------- | ------------------------ |
| Static             | Print and done                  | `iostreams` + `fmt`      |
| Static-interactive | Output with y/n prompts         | `iostreams` + `prompter` |
| Live-display       | Continuous rendering, no input  | `iostreams` + `tui`      |
| Live-interactive   | Full keyboard input, navigation | `iostreams` + `tui`      |

**Import boundaries** (enforced):

* Only `iostreams` imports `lipgloss`
* Only `tui` imports `bubbletea`/`bubbles`
* Only `term` imports `golang.org/x/term`
