Skip to content

Repository files navigation

Harmonia

A personal SDLC for Claude Code and OpenCode: thin lifecycle commands orchestrate a twelve-agent roster bound by the 4 Karpathy rules, hooks deterministically enforce everything a machine can check, and captured knowledge compounds across sessions and projects.

Why "Harmonia"

From the Portuguese word for harmony, and for Harmonia, the Greek goddess of harmony — the cosmos as ordered music and balance (the Music of the Spheres). The name evokes order, structure, and beauty: exactly what a good SDLC provides. It is instantly readable and pronounceable, and it feels classical and mythic.

Install

Claude Code

claude plugin marketplace add foliveira/harmonia
claude plugin install harmonia

Installs are pinned to a release, not to master: the marketplace entry names the exact commit a CalVer version was cut from, so claude plugin install and claude plugin update both give you that tree rather than whatever is on the branch. The current release is 2026.08.16.

Working on the engine itself is a different path — add the repo as a directory marketplace and the plugin runs from your working tree, so a change is live in the next session with no release step.

Disabling in a specific repo (client work)

Add to that repo's .claude/settings.local.json:

{ "enabledPlugins": { "harmonia": false } }

Emergency brake: set HARMONIA_DISABLE=1 in the environment — the session-start hook checks it first and stays silent.

OpenCode

The repo itself is the distribution artifact: clone it and run the installer.

git clone https://github.com/foliveira/harmonia
cd harmonia
bash bin/install-opencode.sh

The installer writes into your OpenCode config directory (--target <dir> beats OPENCODE_CONFIG_DIR, which beats the default ~/.config/opencode) and places two things:

  • commands/harmonia-<name>.md — one command file per skill. OpenCode command names carry no namespace separator, so every /harmonia:x in the tables below is typed /harmonia-x there.
  • harmonia/ — the engine home: a copy of bin/, core/, and skills/, with the plugin-root variable in prompt bodies rewritten to the engine home's absolute path.

The target path may contain only the characters [A-Za-z0-9._/-]: placed bodies embed the engine-home path in unquoted shell instructions, so the installer refuses whitespace and other shell metacharacters rather than splice a path that would break them.

Generated command files carry a marker comment, and that marker is the ownership boundary: every run re-creates the marked commands/harmonia-*.md files (stale ones left by removed skills included) and never touches unmarked files. If a file of your own sits at a name the run would generate, the installer aborts and lists it. To update:

git pull && bash bin/install-opencode.sh

Re-running converges to a fresh install. Uninstall is the two owned paths, marker-filtered so any harmonia-*.md files of your own survive:

rm -rf ~/.config/opencode/harmonia
grep -lF 'generated by harmonia install' ~/.config/opencode/commands/harmonia-*.md | xargs rm -f

Both paths assume the default ~/.config/opencode; adjust them if you installed elsewhere with --target or OPENCODE_CONFIG_DIR.

Two capabilities do not port to OpenCode; the installer prints both on every run:

  • Roster subagent dispatch: OpenCode has its own agent system (~/.config/opencode/agents/), and harmonia installs nothing into it. Where a stage says "dispatch the <agent>", an OpenCode session runs that stage's procedure in the main session, with the charters readable at <engine home>/core/charters/. A real roster port is the first candidate for a contributor (next section).
  • Session-start injection: no hook fires when a session opens. Every stage command reads core/RULES.md itself when the digest is not in context, so the working contract loads on first harmonia command use. Optional: add <engine home>/core/RULES.md to the instructions array of your opencode.json; the installer never edits that file.

Porting to another harness

Ports arrive as PRs. These are the repo-side facts a port must honor — bin/install-opencode.sh is the worked example, and other harnesses' internals are unverified here:

  1. Place bin/, core/, and skills/ somewhere stable, preserving the executable bits on bin/ (plain bash, invoked by path).
  2. Substitute the closed literal ${CLAUDE_PLUGIN_ROOT} in placed .md/.yaml files with the absolute path of the placed engine root. Never rewrite bin/*.sh — the scripts resolve their own location when that variable is unset.
  3. Surface each skills/<name>/SKILL.md body through the harness's user-typed command surface, re-heading the frontmatter in the harness's own vocabulary (every command is human-invoked by contract).
  4. Adapt or document the four Claude-specific capabilities: roster dispatch (agents/), session-start injection (hooks/hooks.json), plugin-root substitution, and /harmonia: namespacing.
  5. Ship an update act that converges — re-running it equals a fresh install — and copy the pattern in tests/install.bats to verify the port repo-locally against a scratch target.

Using it

Every session starts with the 4 rules and relevant learnings injected automatically. The lifecycle is seven explicit commands:

Command What runs
/harmonia:ideate ideator (+ rubber duck) widen the option space into ideas.md
/harmonia:discuss scoper pins scope — goal, boundaries, non-goals, run: success criteria
/harmonia:plan planner designs inside the scope boundary
/harmonia:implement red-green loop: test engineer leads, implementer follows, coverage gate feeds gap rounds
/harmonia:review review lead chairs the panel, dispatches triggered lenses, audits gates and receipts, writes one verdict
/harmonia:capture knowledge curator files learnings; committer ships structured commits
/harmonia:quick express lane: implementer + lead-solo review, gates still active

Each task lives in .harmonia/tasks/<task-id>/ in the target repo — a self-gitignoring workspace where stages pass artifacts by path. Entry stages mint it; later stages resolve it; interruption recovery is re-invoking a stage against the on-disk artifacts.

Touchpoints

Six commands act on a task outside the lifecycle stages: they record your decision on the built work, move learnings to and from memory, read the workspace state, and retire a task you are dropping. None of them advances a stage.

Command What it does
/harmonia:accept Records your acceptance of the built work so capture can proceed; supersedes a standing rejection.
/harmonia:reject Records that you rejected the built work, blocking capture until you re-accept or abandon the task; supersedes a standing acceptance.
/harmonia:abandon Retires the active task workspace so resolution skips it.
/harmonia:remember Captures a single learning into the right memory tier.
/harmonia:recall Surfaces relevant past learnings for the current repo mid-session.
/harmonia:status Read-only readout of the active task's stage, markers, and receipts.

Outside the lifecycle

Three more commands are neither stages nor touchpoints. One chains stages; two set a repo up before any task runs.

Command What it does
/harmonia:flow Runs an already-pinned task through plan, implement, and review in one unattended pass. It chains neither end: discuss stays manual because it is dialogic, and acceptance stays manual under the human-only gate.
/harmonia:onboard Captures an existing repo's canonical verify commands and its own coverage command into .harmonia/project.yaml.
/harmonia:trust Records your consent, on this machine, to run a repository's .harmonia/project.yaml coverage command. Until you do, that command is refused.

The gates

  • Criteria — implement refuses to start until the scope declaration carries machine-checkable - run: criteria; at review the criteria-run gate executes every one of them from the repo root, echoes the whole set it ran, and fails the review if any criterion fails.
  • Coverage — 100% line (and branch, where the format measures it) on changed code, soft block. Exemptions are in-code markers with a mandatory justification (// harmonia:exempt <why>), surfaced to the reviewer in the gate report's exemptions-honored section. Overrides append to a versioned audit log at .harmonia/coverage-exemptions.yaml. Unsupported languages exit as advisory cannot-measure, never a false pass.
  • Receipts — every gate run writes a receipt (task id, timestamp, diff digest); review fails work whose receipts are missing or stale, and a test-immutability hash violation is treated the same way.

Memory

Two tiers of learnings: a global tier under ~/.harmonia/learnings/ for cross-project patterns, summarized one line each in ~/.harmonia/index.md, and docs/learnings/ in each repo for the project tier. HARMONIA_HOME moves the global store. Writes go through capture: the knowledge curator files learnings at /harmonia:capture, and /harmonia:remember files a single one. Capture refuses two of them at the global tier — client-flagged content, which stays project-tier, and an entry carrying no recognized language tag, which the filter below could never surface. That second refusal is overridable, and an entry recorded that way says so in its body.

Recall reads three sources: both tiers, plus legacy docs/solutions/ entries, read-only, for continuity. Only the global tier is filtered, and it is filtered on language alone: an index line is kept when one of its tags matches a language detected in the repo you are in, read from that repo's tracked file extensions. Project and legacy entries are always relevant to their own repo, so nothing filters them. What is left is ordered newest first and cut at a line budget: 12 lines at session start, 30 when the script runs on its own. Run /harmonia:recall to pull more mid-session. Any roster agent or hook can run the underlying script directly:

bash ${CLAUDE_PLUGIN_ROOT}/bin/memory/recall.sh

Security

Pointing Harmonia at a repository runs some of that repository's own configuration, so the trust model is written down rather than implied. SECURITY.md states what is guarded — workspace containment, artifact provenance, and consent for a repository's coverage command — and, just as explicitly, which routes are deliberately still open. Report a vulnerability privately through the process it describes, never a public issue.

The roster

Twelve agents. Each has a charter in core/charters/ — the portable truth — and a thin Claude Code wrapper in agents/. A stage dispatches them, and each consumes named artifacts and produces named ones, so a handoff is a file on disk rather than a conversation.

Agent Runs at What it does
ideator ideate Widens the option space before Harmonia commits to one direction
rubber duck ideate, discuss A thinking partner: asks the questions that let you find the answer
scoper discuss, plan Pins the scope — goal, boundaries, non-goals, machine-checkable criteria
planner plan Designs how to build, strictly inside the scope declaration's boundary
test engineer implement, review Writes tests first: failing tests for behavior, covering tests at gaps
implementer implement, quick Makes failing tests pass, and never edits a test
reviewer review, quick Review lead: chairs the panel, dispatches lenses, audits gates and receipts, writes one verdict
simplifier review Challenges every abstraction and line that does not earn its keep
doc reviewer review Checks documentation against the code and the diff
knowledge curator capture Classifies and files learnings into the right memory tier
committer capture Organizes the work into single-concern commits that communicate intent
doc producer on request Writes documentation for shipped behavior. No stage dispatches it — invoke it when you want docs

The review panel is the test engineer, simplifier and doc reviewer, convened under the review lead. The lead arbitrates everything into one verdict; seats do not vote.

Lenses

Five files in core/lenses/. Each declares its own triggers in frontmatter, so dispatch follows the diff rather than a list the reviewer hardcodes.

Lens Fires On
security automatically auth, secrets, input parsing, network-facing
regression automatically markers, base-ref handling, receipts, shell quoting — checked against both learning tiers
adversarial the lead's call new abstractions, architectural changes, novel patterns
performance the lead's call hot paths, algorithmic complexity, large data, tight loops
blindspot not a review lens the scoper dispatches it once per task at first scope mint, to surface unknowns before the boundary is drawn

Developing the engine

Dev toolchain: bats, jq, yamllint, check-jsonschema, kcov, diff-cover (and gocover-cobertura for Go targets).

bats tests/                                  # the whole suite
bin/validate-core.sh                         # lifecycle schema + lens resolution
bin/coverage/gate.sh --self --base <ref>     # the gate, dogfooded on this repo

The engine is bash + YAML only, and it is held to its own coverage bar.

Credits

Harmonia systematizes my own workflow. It vendors nothing, but draws inspiration from: multica-ai/andrej-karpathy-skills · EveryInc/compound-engineering-plugin · Yeachan-Heo/oh-my-claudecode · addyosmani/agent-skills · mattpocock/skills

MIT licensed.

About

Thin lifecycle commands that orchestrate an agent roster bound by the Four Karpathy Rules, hooks that enforce everything a machine can check, and captured knowledge that compounds across sessions and projects.

Topics

Resources

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages