Architecture
For detailed method/type exploration, use Serena or your IDE’s Go tooling. This document provides the high-level picture.
System Layers
Clawker is organized in four layers, from user-facing CLI down to the Docker SDK:Package Dependency Graph
Packages follow a strict DAG (Directed Acyclic Graph) organized in four tiers:Tier 1: Leaf Packages (Pure Utilities)
Import only the standard library or external-only dependencies. Importable by anyone.build— Build-time metadata (version, date)logger— Zerolog setupterm— Terminal capabilities + raw mode (solex/termgateway)text— Pure ANSI-aware text utilitiessignals— OS signal utilitiesgit— Git operations, worktree management (stdlib + go-git only)docs— CLI documentation generation
Tier 2: Foundation Packages (Infrastructure)
Import leaves only. Universally imported as infrastructure.config— Config loading, validation, project registry + resolveriostreams— I/O streams, TTY detection, colors, styles, spinners, progresscmdutil— Factory struct (DI container), error types, arg validators
Tier 3: Middle Packages (Core Domain Services)
Import leaves + foundation.bundler— Dockerfile generation, content hashing, semver, npm registrytui— BubbleTea models, viewports, panels, progress displaycontainerfs— Host config preparation for container inithostproxy— Host proxy for container-to-host communicationsocketbridge— SSH/GPG agent forwarding via muxrpcprompter— Interactive prompts with TTY/CI awarenessproject— Project registration in user registry
Tier 4: Composite Packages (Subsystems)
Import all lower tiers. Imported by commands only.docker— Clawker middleware wrapping whail Engine with labels/namingworkspace— Bind vs Snapshot strategiesloop— Autonomous loop engine with circuit breaker
Import Rules
Dependency Injection: The Factory Pattern
Clawker follows the GitHub CLI’s three-layer Factory pattern:Layer 1: Wiring (internal/cmd/factory/default.go)
Creates *cmdutil.Factory with all dependencies wired as closures. Called once at entry point. Tests never import this package.
Layer 2: Contract (internal/cmdutil/factory.go)
Factory is a pure struct with closure fields — no methods. Defines what dependencies exist. Importable by all command packages without cycles.
Eager fields (set directly): Version, IOStreams, TUI
Lazy fields (closures with sync.Once): Config, Client, GitManager, HostProxy, SocketBridge, Prompter
Layer 3: Consumers (internal/cmd/*)
Commands cherry-pick Factory closures into per-command Options structs. Run functions accept *Options only — never see Factory.
Key Abstractions
| Abstraction | Package | Purpose |
|---|---|---|
whail.Engine | pkg/whail | Reusable Docker engine with label-based resource isolation |
docker.Client | internal/docker | Clawker middleware (labels, naming) wrapping whail |
config.Config | internal/config | Gateway type — lazy-loads Project, Settings, Resolution, Registry |
Factory | internal/cmdutil | DI struct (closure fields); constructor in cmd/factory |
WorkspaceStrategy | internal/workspace | Bind (live mount) vs Snapshot (ephemeral copy) |
CreateContainer() | internal/cmd/container/shared | Single entry point for container creation — workspace, config, env, create, inject |
tui.TUI | internal/tui | Factory noun for presentation layer |
tui.RunProgress | internal/tui | Generic progress display (BubbleTea TTY + plain text) |
hostproxy.HostProxyService | internal/hostproxy | Interface for host proxy operations; Manager is concrete impl |
shared.Runner | internal/cmd/loop/shared | Autonomous loop orchestrator with per-iteration containers and circuit breaker |
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 |
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 |
- Only
iostreamsimportslipgloss - Only
tuiimportsbubbletea/bubbles - Only
termimportsgolang.org/x/term
Host Proxy Architecture
The host proxy bridges container-to-host communication:- URL opening: Container script → POST to proxy → host browser
- OAuth: Intercepts auth URL, rewrites callback, captures redirect
- Git HTTPS: Container credential helper → proxy → host credential store
- SSH/GPG:
socketbridge.Manager→docker execmuxrpc → Unix sockets