Skip to main content

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 Overview

Clawker is a CLI tool plus two long-lived daemons — clawker-cp (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/clawker-cp, 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  │
                                               └──────────┬─────────────────┘
                                                          │ 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 for the user-facing CP guide and Firewall for the firewall guide.

CLI Command Structure

Commands are organized under internal/cmd/ with subpackages per subcommand:
Command GroupSubcommandsPurpose
containerlist, run, start, stop, kill, exec, attach, logs, inspect, cp, pause, unpause, restart, rename, remove, stats, top, update, wait, createDocker container management
imagelist, build, inspect, remove, pruneImage lifecycle
volumelist, create, inspect, remove, pruneVolume management
networklist, create, inspect, remove, pruneNetwork management
projectinit, register, list, info, edit, removeProject registration and config
worktreeadd, list, prune, removeGit worktree management
firewallstatus, list, add, remove, reload, up, down, enable, disable, bypass, rotate-caEgress firewall control (all RPCs route through f.AdminClient to the CP daemon)
controlplaneup, down, status, agentsBreak-glass control plane lifecycle + registered agent listing
authrotateCLI-side auth material (CA, server certs, OAuth2 signing key)
monitorinit, up, down, statusObservability stack (OTel Collector, OpenSearch, OpenSearch Dashboards, Prometheus)
settingseditUser settings TUI editor
skillinstall, show, removeManage the clawker-support Claude Code plugin
Top-level shortcuts: initproject init, buildimage build, run/startcontainer 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.
PackagePurpose
storageGeneric layered YAML store engine (Store[T]): discovery, merge, provenance, atomic write
gitGit operations, worktree management (go-git)
loggerStruct-based zerolog (file rotation + optional OTEL bridge)
textPure ANSI-aware text utilities (Truncate, PadRight, StripANSI)
termTerminal capabilities + raw mode (sole x/term gateway)
signalsOS signal utilities (SetupSignalContext, ResizeHandler)
buildBuild-time metadata (version, date via ldflags)
updateBackground GitHub release checker (24h cached)
keyringCredential storage service
pkg/whailReusable Docker engine library with label-based isolation

Foundation Packages (import leaves only)

Universally imported infrastructure. Their imports are leaf-only.
PackageImportsPurpose
configstorageConfig loading/validation, schema types, path resolution. Composes Store[Project] + Store[Settings]
iostreamsterm, textI/O streams, TTY detection, colors, styles, spinners, progress
ebpfloggereBPF program loader/manager (cilium/ebpf) — pins maps and programs, attaches to container cgroups, SyncRoutes replaces the global route_map atomically

Domain Packages (import leaves + foundation)

Core business logic. Import leaves and foundation packages only.
PackageImportsPurpose
projectconfig, git, logger, storage, textProject registration, worktree lifecycle, registry CRUD
bundlerconfig + own subpkgsDockerfile generation, content hashing, semver, npm registry
tuiiostreams, textBubbleTea models, viewports, panels, progress display
prompteriostreamsInteractive prompts with TTY/CI awareness
storeuiiostreams, storage, tuiGeneric TUI editor for Store[T] instances
controlplaneconfig, docker, logger, ory subprocess managersCP daemon core: AdminService composition, Ory auth stack, startup orchestrator, agent watcher
controlplane/agentauth, consts, dockerevents, overseer, loggerCP-side agent surface: Dialer, sqlite Registry, Register handler, IdentityInterceptor, session/agent events
controlplane/overseerloggerTyped event bus + in-memory State worldview (containers + agents)
controlplane/dockereventsoverseer, loggerDocker events feeder (reconnecting stream → typed events on overseer bus)
controlplane/cpbootconfig, docker, logger (+ embedded clawker-cp + ebpf-manager binaries)Host-side CP lifecycle: EnsureRunning/Stop/CPRunning
controlplane/adminclientauth, constsCLI-side AdminService gRPC dial (mTLS + auto-refreshing OAuth2 bearer)
controlplane/firewallconfig, docker, logger, storage, controlplane/firewall/ebpfFirewall Handler (13 RPCs), Stack (Envoy+CoreDNS lifecycle), ActionQueue, config generators, certificate PKI, rules store
controlplane/firewall/ebpfloggereBPF program loader/manager, SyncRoutes replaces global route_map atomically; break-glass ebpf-manager CLI under cmd/
dnsbpfcontrolplane/firewall/ebpfCoreDNS plugin that writes DNS resolutions to the BPF dns_cache map in real time (embedded in cmd/coredns-clawker)
clawkerd(embed only)//go:embed assets/clawkerd — exports the per-container daemon binary; bundler drops it into every per-project image at /usr/local/bin/clawkerd
hostproxyconfig, loggerHost proxy for container-to-host communication
socketbridgeconfig, loggerSSH/GPG agent forwarding via muxrpc
containerfsconfig, keyring, loggerHost config preparation for container init
monitorconfigObservability stack templates (OTel Collector, OpenSearch, OpenSearch Dashboards, Prometheus)
docsconfig, storageCLI documentation generation

Composite Packages (import domain packages)

Higher-level subsystems that compose domain packages.
PackageKey ImportsPurpose
dockerbundler, config, pkg/whail, pkg/whail/buildkitClawker middleware wrapping whail with labels/naming
workspaceconfig, docker, loggerBind vs Snapshot strategies
cmdutilconfig, docker, iostreams, tui, + type imports for FactoryFactory 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 projects.yaml 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, Firewall, Logger, Prompter.
  3. Consumers (internal/cmd/*/) — Cherry-pick Factory closures into per-command Options structs. Run functions accept *Options only.
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

AbstractionPackagePurpose
storage.Store[T]internal/storageGeneric layered YAML store with merge, provenance, and atomic write
config.Configinternal/configTyped config interface composing Store[Project] + Store[Settings]
project.ProjectManagerinternal/projectProject identity, registration CRUD, worktree orchestration
whail.Enginepkg/whailReusable Docker engine with label-based resource isolation
docker.Clientinternal/dockerClawker middleware (labels, naming) wrapping whail
cmdutil.Factoryinternal/cmdutilDI struct (closure fields); constructor in cmd/factory
CreateContainer()internal/cmd/container/sharedSingle entry point for container creation
adminclient.Dialinternal/controlplane/adminclientCLI-side AdminService gRPC dial (mTLS + OAuth2)
firewall.Handlerinternal/controlplane/firewall13-method AdminService firewall surface inside the CP daemon
firewall.Stackinternal/controlplane/firewallEnvoy + CoreDNS container lifecycle
dnsbpf.Handlerinternal/dnsbpfCoreDNS plugin populating the BPF dns_cache map in real time
ebpf.Managerinternal/controlplane/firewall/ebpfBPF program loader; SyncRoutes replaces the global route_map atomically
cpboot.Managerinternal/controlplane/cpbootHost-side CP container lifecycle (EnsureRunning/Stop/CPRunning)
agent.Registryinternal/controlplane/agentsqlite-backed agent identity (CP is sole writer)
overseer.Overseerinternal/controlplane/overseerTyped event bus + worldview state inside CP
cmd/clawker-cpcmd/clawker-cpCP daemon entry point — PID 1 of the clawker-controlplane container
cmd/clawkerdcmd/clawkerdPer-container agent daemon — PID 1 of every agent container
cmd/coredns-clawkercmd/coredns-clawkerCustom CoreDNS entrypoint embedding dnsbpf; built into clawker-coredns:latest on demand
tui.TUIinternal/tuiFactory 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.*):
LabelPurpose
managedtrue — authoritative ownership marker
projectProject name (omitted when empty)
agentAgent name
versionClawker version
imageSource 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:
ScenarioDescriptionPackages
StaticPrint and doneiostreams + fmt
Static-interactiveOutput with y/n promptsiostreams + prompter
Live-displayContinuous rendering, no inputiostreams + tui
Live-interactiveFull keyboard input, navigationiostreams + tui
Import boundaries (enforced):
  • Only iostreams imports lipgloss
  • Only tui imports bubbletea/bubbles
  • Only term imports golang.org/x/term