harnage
v0.5.0
Published
Describe an agent — own a Claude Code-level harness that amplifies your work on any model, even local, and consumes any MCP server. harnage augments your work, it never just automates it.
Maintainers
Readme
harnage
AI Model = Brain. Harness = Hands.
A good harness amplifies what a model can do — it doesn't automate the model away. Describe the agent you want; harnage builds you a fully-owned, Claude Code-level harness for it, tuned so even a small local model performs at its ceiling.
harnage is two things in one repo:
- The builder —
harnage init "<what you want>"turns a prompt into a complete, compiling TypeScript agent harness, bespoke to your domain: custom system prompt, tools, slash commands, and skills, generated by a build brain and verified with a compile-and-repair loop. - The reference harness — the chassis every generated harness ships with: a goal-driven loop engine, 9 tools, path-rule permissions, sandboxed bash, context compaction, layered long-term memory, eval-in-loop, audit trail, session resume (including mid-task crash recovery), sub-agents, and an Ink TUI with live slash-command menus.
You own everything it generates. No SaaS, no lock-in — the output is a plain Bun/TypeScript project that runs against your local Ollama model or your own API key.
Features
| Area | What you get |
|---|---|
| Builder pipeline | Interview → plan → generate → assemble → verify → repair. LLM-driven when a build brain is configured; falls back to a fully offline keyword pipeline when it isn't. |
| Per-model scaffolding | Generated harnesses resolve the plugged-in model to a profile (tier, loop mode, tool budget, edit format, decoding params) instead of assuming a frontier model. |
| Memory | Semantic + episodic facts/events (local bun:sqlite), procedural skills, working-memory compaction — nothing leaves the machine. |
| Eval-in-loop | Deterministic quality checks on every run, optional LLM-as-judge, a trace command over the local audit log — terminal-first LLMops. |
| Session resume | Transcripts survive restarts; an interrupted task is offered for continuation on next start. |
| Permissions + sandbox | Path-rule policy (~/.harnage/permissions.json) plus a command/path-blocklist sandbox for bash. |
| MCP dual-mode | The harnage CLI serves an MCP server (--mcp) and consumes external MCP servers today. Generated harnesses can serve MCP; external-MCP consumption in generated harnesses is in progress. |
| Ink TUI | Live slash-command menu, streaming output, plus a classic readline REPL fallback. |
Install
npm i -g harnage # or: bunx harnage@latest (no install, run once)Requires bun ≥ 1.1 on your PATH — the npm package ships TypeScript source and runs it via bun directly (no separate build step). Don't want bun installed? Grab a prebuilt binary (darwin-arm64, linux-x64) from the GitHub releases page instead — download, chmod +x, and run it directly, no runtime needed.
Building from source instead:
git clone https://github.com/PDgit12/harnage
cd harnage
bun install
bun run build
./harnage init "..."Quick Start
harnage init "an agent that reviews git diffs for bugs and posts a summary to Slack"The builder picks a build brain automatically (your configured API key, falling back to local
Ollama, falling back to a keyword pipeline that works fully offline). The generated harness
lands in .harnage-build-<name>/ — cd in, bun install, and run it.
Provider resolution on first run:
~/.harnage/config.json(created by the setup wizard; supports OpenRouter/Anthropic/OpenAI/Ollama + fallback models)ANTHROPIC_API_KEY/OPENAI_API_KEYenv vars- Running Ollama instance
- Nothing found → setup wizard
Usage
| Command | What it does |
|---------|--------------|
| harnage | Interactive REPL with the goal-driven loop |
| harnage init "<description>" | Build a bespoke harness from a prompt |
| harnage studio | Guided interview → harness build |
| harnage --mcp | Run as an MCP server (connect from Claude Code, Cursor, …) |
What a generated harness includes
- Loop engine tuned to the chosen model's tier: native tool-calling for strong models; grammar-forced constrained-JSON decisions and baked domain pipelines for small local models
- Bespoke layer: domain system prompt, custom tools, slash commands, and skills generated for your use case
- Layered memory: semantic + episodic store (bun:sqlite) with deterministic recall and post-run consolidation, plus procedural skills and working-memory compaction
- Eval-in-loop: deterministic checks on every run, optional LLM judge,
tracecommand over the local audit trail - Session resume: transcripts survive restarts; an interrupted task is offered for continuation on next start (
--resumepicks it up mid-task) - Permissions + sandbox: path-rule policy (allow/deny by tool + glob pattern), command/path-blocklist sandbox for bash — no OS-level container yet (see Status)
- Ink TUI with a live slash-command menu, plus a classic REPL and an MCP server mode
Slash commands (inside the REPL/TUI)
/help · /config · /cost · /clear · /model · /doctor · /exit — plus the bespoke commands the builder generated for your domain.
Demo
Coming soon — asciinema/GIF walkthrough of harnage init → generated harness → first run.
Development
bun run typecheck # tsc --noEmit
bun run test # vitest — 30 files, 203 tests passing
bun run lint # biome check src/
bun run build # compile binaryGenerated harnesses must themselves pass bun install && tsc --noEmit — the builder verifies this and runs an LLM repair loop on failures.
Status
Published: [email protected] on npm, MIT licensed, prebuilt binaries on GitHub releases. Working:
builder end-to-end (API + local + offline paths), reference harness (including MCP-server-consumer
mode), all 9 tools, path-rule permissions, memory, eval, TUI. In progress: external-MCP consumption
in generated harnesses (the harnage CLI itself already consumes MCP servers). No interactive
permission-approval dialog yet — a denied call surfaces as tool-result text the model adapts to.
No OS-level sandbox container yet — bash is confined by a command/path blocklist, not a VM/container.
Found something broken? Open an issue.
