-
Notifications
You must be signed in to change notification settings - Fork 0
STRUCTURE
Analysis Date: 2026-08-15
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
| 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.py — ExecutionBackend, LaunchSpec
|
| Catalog models + loaders |
src/harnessed/schema.py — Recipe, Stack, ServiceDef, Agent, load_*
|
| All path constants |
src/harnessed/paths.py — catalog_roots(), harnessed_home(), profile_dir(), … |
| In-process assembler | src/harnessed/assemble.py:assemble() |
| Profile file writer |
src/harnessed/emit.py — write_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 |
-
Python files:
snake_case.py -
Python functions:
snake_case; private helpers prefixed_ -
Dataclasses:
PascalCase(Recipe,Stack,LaunchSpec,AssembleResult) -
Catalog directories:
kebab-casefor recipe/service/stack names; underscore joins multiple recipe names in a stack name (gsd-core_repowise) -
Podman volumes:
harnessed-cfg-<harness>-<stack>(config) andharnessed-tools-<harness>-<stack>(tools) -
Podman images:
harnessed-<harness>-<stack>(derived),harnessed-base,harnessed-<harness>
| 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) |
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.
Start Here
Guides
- 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)