-
Notifications
You must be signed in to change notification settings - Fork 0
build and images
What harnessed build produces, in what order, and why the agent CLI installs last. This page used
to be the "First-run build" section of the README.
Images are built on the host with podman build the first time they are needed:
-
harnessed-base: fat toolchain image (mise, node@24, python, pnpm; no harness CLI). -
harnessed-<harness>-<stack>: the derived stack image, built byharnessed build <stack> <harness>. FROMharnessed-base, then the stack's recipe Dockerfiles concatenated, then the agent CLI installed last, then the supply-chain scan. -
harnessed-<agent>: FROMharnessed-base+ the agent CLI (harnessed-claude,harnessed-omp, …). Not the derived image's parent. It is the fallback image a run uses for a stack with no derived image yet.
Supporting image (not part of the base → agent → stack lineage):
-
hatago: the MCP hub. It aggregates a stack's MCP servers behind one HTTP endpoint, with the lightpnpm dlx/uvxservers baked in.
Assembly runs host-native in-process (no tool container). The host CLI emits the profile and the
Dockerfile.harnessed-<stack>, then drives podman build.
Agent CLI pins churn far faster than recipes. When the agent image was the derived image's FROM
parent, every agent bump changed the parent's id and so invalidated every recipe layer of every
stack on that harness. With the agent on top, an agent bump rebuilds only the agent layer and the
scan; the expensive recipe layers stay cached.
It also makes the recipe layers harness-independent. They hang off harnessed-base with identical
instructions, so a stack declaring harnesses: [claude, omp] builds its recipe layers once and both
harnesses share them.
A recipe that branches on ${HARNESS} in a RUN necessarily splits that cache from its own layer
onward, so keep such recipes late in a stack's recipes: list.
harnessed build # rebuild the shared images, then reconcile every stale stack
harnessed build -j1 # ... one stack at a time (default: half the cores, capped at 4)
harnessed build <stack> # build every harness in the stack's `harnesses:` list
harnessed build <stack> <harness> # assemble one stack for a harness: emit profile + build images (+ supply-chain scan)A bare harnessed build rebuilds the shared images once, then builds every stale stack
concurrently (--jobs / -j). Each build's output is prefixed with its own coloured
stack(harness) tag so the interleaved podman logs stay readable, and one stack failing does not
cancel the others. The failures are reported together at the end.
A stack may declare which harnesses it is built for:
name: my-stack
recipes: [superpowers, serena]
harnesses: [claude, omp] # build-time only — the harness is still a run-time argumentharnessed build <stack> then fans out to every name in that list, and bare harnessed build
includes those <stack> <harness> pairs in its sweep, so a freshly authored stack is provisioned
without naming it. A stack that declares no harnesses: is unchanged: build <stack> still
requires an explicit harness, and a bare build only reconciles it once it has been built at least
once.
harnessed build <stack> <harness> rebuilds the base (so base-image changes propagate), assembles
in-process, then builds the hatago, agent, and derived harnessed-<harness>-<stack> images. The
derived image's final layer runs an in-image, advisory supply-chain scan over what actually landed.
The profile is emitted to $XDG_DATA_HOME/harnessed/profiles/<stack>/<harness>/ (the clone stays
immutable source) plus an advisory scan-report.json alongside it. Expect first-run latency; later
runs are cache hits.
-
A/B two memory systems. Run
claude+hindsightandclaude+openbrainas separate stacks side by side; neither touches your host config or the other's state. -
Compare harnesses on equal footing. Point
claude+hindsightandomp+hindsightat the same service-scoped memory volume and judge which harness drives it better. Same data, different engine. -
Clean-room a flaky plugin.
harnessed container-run <harness> --stack <name> --freshreproduces from zero state, then tears down leaving no residue in~. -
Proof it built right.
harnessed test <stack> <harness>brings the instance up headless and asserts it exposes exactly the MCP servers, skills, and commands its manifest declares, rendered as a per-capability markdown report.
- Supply chain and security: what the in-image scan checks and why it does not fail the build.
-
Troubleshooting: the runtime table (podman, Docker, Apple
container) and first-run build issues.
Start Here
Guides
- Getting started
- Build and images
- Supply chain and security
- Alternatives
- Recipe authoring
- Service authoring
- Stacks
- Extending stacks (proposed)
- Recipe catalog
- System prompt & rules (proposed)
- Secrets
- AWS SSO
- Pulumi (host login forwarding)
- Egress & exposing services
- Container filesystem
- Git hooks
- Troubleshooting
- Pin management (harnessed update)
Codebase Map
Planning & Roadmap
- open work: GitHub Issues
Research & Prompts
- research/ (home-folder requirements per harness, browse in-repo)
- prompts/ (reusable prompt templates, browse in-repo)