Skip to content

STRUCTURE

Mike Crowe edited this page Aug 15, 2026 · 4 revisions

Codebase Structure

Analysis Date: 2026-08-15

Directory Layout

harnessed/                         # repo root (bare git dir at .bare/, canonical checkout at main/)
├── pyproject.toml                 # Python project: name=harnessed, scripts, deps
├── mise.toml                      # tool version pins (Python, Node, pnpm, …)
├── uv.lock                        # locked dependency tree
├── pnpm-workspace.yaml            # pnpm workspace (web/, hatago npm packages)
├── src/
│   └── harnessed/                 # the application — ALL Python source
│       ├── launcher.py            #   `harnessed` CLI (Typer): all user-facing commands
│       ├── cli.py                 #   `harnessed-tools` CLI (argparse): assemble/scan/persist
│       ├── backend.py             #   ExecutionBackend ABC + LaunchSpec + backend registry
│       ├── assemble.py            #   in-process assembler: stack+recipes → AssembleResult
│       ├── emit.py                #   profile file writer: .mcp.json, settings.json, hatago.config.json, …
│       ├── schema.py              #   typed models (Recipe, Stack, ServiceDef, Agent) + catalog loaders
│       ├── paths.py               #   single source of truth for all host/container paths + catalog roots
│       ├── hosthome.py            #   host home: materialize, scrub, credential rescue, settings propagation
│       ├── hostrun.py             #   host-run backend: installs, inits, setups, mise env, tool shims
│       ├── mounts.py              #   container mount argument construction (auth, MCP remote, keyring)
│       ├── volumes.py             #   podman volume management: config/tools volumes, fingerprinting, installs
│       ├── launchenv.py           #   launch secrets/env resolution: varlock, env-file parsing
│       ├── credmounts.py          #   credential mount helpers (claude, omp)
│       ├── aoe.py                 #   Agent of Empires session mirror (optional integration)
│       ├── capability.py          #   capability test runner (the integration oracle)
│       ├── capmatrix.py           #   capability matrix display
│       ├── report.py              #   capability test report formatting
│       ├── svcstate.py            #   service lifecycle: start/stop/query sidecars
│       ├── svcguards.py           #   service guard conditions (port conflict, health checks)
│       ├── dynstack.py            #   dynamic stack minting from --recipe flags
│       ├── lastrun.py             #   --last run tracking (record + replay)
│       ├── staleness.py           #   stack staleness checks (image age, recipe fingerprint)
│       ├── update.py              #   harnessed self-update and pin management
│       ├── persist.py             #   persist entry management (workspace/in-repo/project scopes)
│       ├── persist_gc.py          #   persist garbage collection
│       ├── scan.py                #   volume scanner (installed capabilities inventory)
│       ├── synclinks.py           #   symlink sync (catalog-local DX links)
│       ├── catalogseed.py         #   catalog seeding helpers
│       ├── attachcmd.py           #   container attach command construction
│       ├── ctrquery.py            #   container query helpers (podman inspect wrappers)
│       ├── jsonmerge.py           #   JSON merge utilities
│       ├── layout.py              #   container layout helpers
│       ├── proc.py                #   subprocess helpers + timeout audit
│       ├── toollock.py            #   tool lock management (prevent concurrent installs)
│       ├── setupenv.py            #   setup script environment construction
│       ├── console.py             #   console output (rich wrappers)
│       └── catalog -> ../../catalog   # symlink: setuptools follows it → catalog ships in the wheel
├── catalog/                       # authored content: agents, recipes, services, stacks (SHIPPED IN WHEEL)
│   ├── agents/                    #   AI harness definitions
│   │   ├── claude/                #     Claude Code harness (agent.yaml + Dockerfile)
│   │   ├── omp/                   #     oh-my-pi harness (github:can1357/oh-my-pi)
│   │   ├── codex/                 #     Codex harness
│   │   ├── opencode/              #     opencode harness
│   │   └── antigravity/           #     antigravity harness
│   ├── base/                      #   shared base Dockerfiles, pnpm policy, egress script
│   ├── recipes/                   #   composable capability bundles
│   │   ├── default/               #     baseline recipe (every stack extends this)
│   │   ├── gsd-core/              #     core GSD recipe
│   │   ├── superpowers/           #     superpowers bundle
│   │   ├── serena/                #     Serena MCP
│   │   ├── codebase-memory-mcp/   #     codebase memory MCP server
│   │   ├── context-mode/          #     context-mode plugin
│   │   ├── repowise/              #     repowise recipe
│   │   ├── rtk/                   #     RTK token killer
│   │   └── …                      #     (13 others — 21 recipes total)
│   ├── services/                  #   sidecar service definitions
│   │   ├── agentmemory/           #     agent memory service
│   │   ├── gbrain/                #     gbrain sidecar
│   │   └── ping/                  #     ping/health service
│   ├── stacks/                    #   harness-free stack compositions
│   │   ├── default/               #     baseline (every dynamic stack extends this)
│   │   ├── gsd-core_repowise/     #     gsd-core + repowise
│   │   ├── hostmcp/               #     host MCP stack
│   │   └── …                      #     (others)
│   └── recipes.backlog/           #   WIP recipes not yet published
├── catalog-local/                 # gitignored DX symlinks → ~/.config/harnessed/catalog overlay
├── tests/                         # pytest unit + podman-gated integration tests
│   ├── conftest.py                #   shared fixtures (catalog mocking, tmp stack setup)
│   ├── support.py                 #   test support utilities
│   ├── fixtures/                  #   file fixtures for schema/catalog tests
│   └── test_*.py                  #   ~100 test modules (see Testing)
├── tools/                         # dev tooling (not shipped)
│   ├── run-tests.sh               #   canonical test runner (use this, not bare pytest)
│   ├── lint-findings.py           #   lint finding analysis
│   ├── gauntlet-1ao.sh            #   full quality gauntlet
│   ├── mutants_capmatrix.py       #   mutation test helpers
│   └── wiki-links.py              #   wiki link checker
├── .agents/                       # Claude-side skills/commands/plans for repo contributors
│   ├── skills/                    #   agent skills used during development of this repo
│   ├── commands/                  #   slash commands
│   └── plans/                     #   implementation plans
├── .claude/                       # Claude Code profile for developing harnessed itself
├── schemas/                       # JSON schemas for catalog YAML validation
├── systemd/                       # systemd unit files (optional service integration)
├── web/                           # web assets (hatago UI, if any)
├── docs/                          # GitHub wiki (separate git repo: harnessed.wiki.git)
│   └── codebase/                  #   generated codebase docs (this file lives here)
├── ARCHITECTURE.md                # authoritative vocabulary + design decisions (READ FIRST)
├── AGENTS.md                      # operational rules for agents working on this repo
├── CONTRIBUTING.md                # how to author recipes, services, stacks
└── CLAUDE.md                      # repo-specific Claude instructions

Key Locations

What Where
Primary CLI entry point src/harnessed/launcher.py:main
Secondary CLI entry point src/harnessed/cli.py:main
Backend contract src/harnessed/backend.pyExecutionBackend, LaunchSpec
Catalog models + loaders src/harnessed/schema.pyRecipe, Stack, ServiceDef, Agent, load_*
All path constants src/harnessed/paths.pycatalog_roots(), harnessed_home(), profile_dir(), …
In-process assembler src/harnessed/assemble.py:assemble()
Profile file writer src/harnessed/emit.pywrite_mcp_json, write_hatago_config, write_settings_json
Container mounts src/harnessed/mounts.py_build_mount_args
Container volumes src/harnessed/volumes.py_ensure_stack_volumes, _ensure_config_volume
Host home management src/harnessed/hosthome.py_materialize_host_home, _share_host_claude_state
Host-run backend src/harnessed/hostrun.py_host_run_installs, _host_run_inits, _host_run_setups
Launch env/secrets src/harnessed/launchenv.py_resolve_launch_secrets, _resolve_launch_env
Service lifecycle src/harnessed/svcstate.py
Agent of Empires bridge src/harnessed/aoe.py
Capability test oracle src/harnessed/capability.py
Authored agents catalog/agents/<name>/agent.yaml
Authored recipes catalog/recipes/<name>/recipe.yaml
Authored services catalog/services/<name>/service.yaml
Authored stacks catalog/stacks/<name>/stack.yaml
User overlay (not in repo) ~/.config/harnessed/catalog/
Generated stacks (not in repo) $XDG_DATA_HOME/harnessed/generated/
Assembled profiles (not in repo) $XDG_DATA_HOME/harnessed/profiles/<stack>/<harness>/
Test runner tools/run-tests.sh
Tests tests/test_*.py

Naming Conventions

  • Python files: snake_case.py
  • Python functions: snake_case; private helpers prefixed _
  • Dataclasses: PascalCase (Recipe, Stack, LaunchSpec, AssembleResult)
  • Catalog directories: kebab-case for recipe/service/stack names; underscore joins multiple recipe names in a stack name (gsd-core_repowise)
  • Podman volumes: harnessed-cfg-<harness>-<stack> (config) and harnessed-tools-<harness>-<stack> (tools)
  • Podman images: harnessed-<harness>-<stack> (derived), harnessed-base, harnessed-<harness>

Where to Add New Code

Task Location
New harnessed CLI command Add @app.command("<name>") in src/harnessed/launcher.py
New harnessed-tools subcommand Add a handler and wire into _build_parser() in src/harnessed/cli.py
New path constant or resolver src/harnessed/paths.py
New recipe catalog/recipes/<name>/recipe.yaml (+ optional Dockerfile, install.sh, setup.sh)
New agent harness catalog/agents/<name>/agent.yaml + Dockerfile
New service sidecar catalog/services/<name>/service.yaml + Dockerfile + server
New stack catalog/stacks/<name>/stack.yaml (or user overlay ~/.config/harnessed/catalog/stacks/)
New execution backend Subclass ExecutionBackend in a new file, decorate with @register
New test tests/test_<topic>.py; run via tools/run-tests.sh
New dev tooling script tools/
New DX recipe symlink (local only) catalog-local/ (gitignored)

Module Boundaries

src/harnessed/backend.py imports nothing from launcher.py — the boundary is enforced by tests/test_module_boundaries.py. Both backend implementations (ContainerBackend at launcher.py:2783, HostBackend at launcher.py:2167) live in launcher.py and reference backend.py, so the dependency points one way: into the contract, never out of it. That co-location is deliberate — the two classes sit next to the private helpers they call, which is why naming the seam added no import cycle.

paths.py is imported by almost every module; it imports only stdlib. schema.py imports paths.py; assemble.py imports both. emit.py imports only schema.py types and stdlib. This layering keeps the composition layer testable without podman.

Clone this wiki locally