Skip to content
Conduit

mcp server

harnesses

Metadata registry for AI coding harnesses: binaries, configs, sessions, and capabilities.

agntn/harnessescommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • Node.js 20 or newer
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "harnesses": {
      "command": "npx",
      "args": [
        "-y",
        "@agntn/harnesses"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 26, 2026

@agntn/harnesses

npm version npm downloads license Ask DeepWiki

🧭 Thirteen coding CLIs, one map. You ask where Claude keeps skills, you get the path.

[!WARNING] @agntn/harnesses is pre-1.0. Paths follow upstream CLIs that still move. Building on it now means pinning the version.

Why?

Claude stores transcripts under a mangled copy of your cwd. Codex keeps TOML with comments you wanted to keep. Ask a model where Codex lives and it invents .claude/. So this is one registry: thirteen harnesses, same object, paths for your machine.

The rest of it sits on harnesses.agntn.dev.

✨ Features

  • 🧩 Thirteen harnesses, one class. Same fields on Claude, Codex, Pi and the rest.
  • 📂 Every path has a receipt. Scope, evidence level, and a platform tag when the OS actually differs.
  • 🔎 Detects which CLI you're inside. Environment variables first. Two project markers in one directory is null, not a guess.
  • ▶️ Headless runs with real modes. Advisor without tools, full agent, or a native read-only sandbox. A mode the CLI cannot enforce is rejected.
  • 🔌 MCP across the dialects. One master list at ~/.config/agntn/mcp.jsonc. TOML edits keep the comments.
  • 🔗 One AGENTS.md behind the global files. Symlinks, so an edit through Claude or Gemini is the same bytes.
  • 🗂️ One prompt folder, supported harnesses. Markdown lives under XDG data; Gemini TOML is generated from it.
  • 📜 Session types when the format is stable. JSONL, SQLite, JSON. Unstable shapes stay unknown.
  • 🤖 Eleven tools, three doors. MCP, Pi and OMP call the same executors.

📦 Install

pnpm add @agntn/harnesses

Node.js 26 or newer.

🚀 First call

npx @agntn/harnesses detect
  System Scan

    ● antigravity     Google Antigravity CLI  v1.2.14   agent
    ● claude          Anthropic Claude Code   v2.1.289  advisor · readOnly · agent
    ● codex           OpenAI Codex CLI        v0.160.0  readOnly · agent
    ○ cursor          Cursor
    ● freebuff        Freebuff                v0.0.204  no headless mode
    ○ gemini          Google Gemini CLI
    ○ github-copilot  GitHub Copilot
    ● grok            xAI Grok CLI            v1.0.41   readOnly · agent
    ● mastracode      Mastra Code             v0.10.2   no headless mode
    ● omp             OMP (oh-my-pi)          v18.6.1   agent
    ● opencode        OpenCode CLI            v2.0.22   agent
    ● prime-agent     Prime Agent             v0.9.5    advisor · agent
    ● pi              Pi Coding Agent         v1.0.2    advisor · readOnly · agent

No key, no config. No network either. detect looks at PATH. Filled dot is installed, hollow is not. The tail says how run can drive it: advisor without tools, readOnly behind the harness's own read-only lock, agent with everything. Codex has no advisor, and now you learn that here, not from a refused run. After pnpm add, the same command is pnpm exec harnesses, or install it once with pnpm add -g @agntn/harnesses.

Same binary, more commands:

harnesses list
harnesses info claude
harnesses paths pi
harnesses models pi gpt-5.4 --json
harnesses run claude "review this design"
harnesses run codex --read-only "review this"
harnesses mcp-servers list
harnesses agents sync --check
harnesses prompts sync --check
harnesses skills sync --check

run without --tools is the advisor. --tools is the full agent. --read-only asks the CLI for a sandbox and implies tools, so pairing it with --no-tools is an error. Timeouts, --cwd, --model and --effort sit in the CLI guide.

Commands

CommandWhat it doesExample
listEvery known harness, id and nameharnesses list
detectWhich ones are installed, and how each one runsharnesses detect
infoRegistry entry: modes, capabilities, path templatesharnesses info claude
pathsThose templates expanded for this machineharnesses paths pi
modelsModels the harness can use, through its native listingharnesses models pi
runOne prompt through headless modeharnesses run claude "review this design"
mcp-serversMCP servers across the config dialectsharnesses mcp-servers list
agents syncLink global instructions files to one masterharnesses agents sync --check
prompts syncSync one Markdown prompt directory across harnessesharnesses prompts sync --check
skills syncLink every skills directory to one shared folderharnesses skills sync --check
mcpThe MCP server on stdioharnesses mcp

list, detect, info, paths and models take --json or --toon. run --json is different: that one is the harness's own structured output.

🧠 Library

import { getHarness, detectHarness } from "@agntn/harnesses";

const claude = getHarness("claude");
const paths = claude.resolve({ platform: "linux", homeDir: "/home/dev" });
console.log(paths.skills);
console.log(paths.temp, claude.envOverrides);

const active = detectHarness();
if (active) console.log(active.id);

await getHarness("codex").invoke("Review this patch", { readOnly: true, effort: "low" });
getHarness("grok").readOnlyNetwork(); // false on Linux, so no web for its MCP servers under readOnly

const agy = getHarness("antigravity");
const [model] = (await agy.listModels({ search: "gemini" })).models;
if (model) await agy.invoke("Review this patch", { tools: true, model: agy.modelSelector(model) });

temp is where a harness drops its own temp files, and envOverrides names the variables that move its directories. claude.resolve().temp follows CLAUDE_CODE_TMPDIR when it's set, which is handy when /tmp is tmpfs and Claude's scratchpads are quietly eating RAM.

That's most of it, really. getHarness wants an exact id. detectHarness uses env vars first, then a single project marker. invoke() talks to the CLI, and effort decides how hard it thinks for that one run. listModels() asks it what it can run, and modelSelector() turns one of those into what model takes, since Pi wants provider/id while Antigravity and Codex want the bare id. A mode the CLI cannot run comes back as an error, not a quieter one. An advisor that writes a tool call as text anyway comes back with toolCallsAsText: true, because nothing ran it. The rest: Registry, Invoke, MCP servers, Instructions files.

MCP servers

One list in ~/.config/agntn/mcp.jsonc, every harness synced to it:

{
  "keep": { "codex": ["node_repl"] },
  "mcpServers": {
    "harnesses": { "command": "npx", "args": ["-y", "@agntn/harnesses", "mcp"] },
  },
}
import { getHarness, syncMcpServers } from "@agntn/harnesses";

syncMcpServers([getHarness("codex")]).targets[0]?.results;
// [{ name: "harnesses", action: "added" }, { name: "node_repl", action: "kept" }]

Anything not on the list gets removed. That's the point. But what about a server only one harness can run? Name it under keep and it stays. And a server that has to get past the global excludes? Give it its own. The rest is in the MCP servers guide.

Prompt templates

Put canonical Markdown templates in $XDG_DATA_HOME/agntn/prompts/, or ~/.local/share/agntn/prompts/ when XDG_DATA_HOME is unset. Then sync every supported harness:

harnesses prompts sync --check
harnesses prompts sync

For a Markdown harness, the whole prompt directory becomes one symlink to that directory, so a template added through any harness shows up in all of them. Gemini gets generated TOML commands, with $ARGUMENTS translated to {{args}}, and its commands directory keeps nothing else. Whatever was there before is backed up under the same XDG data tree first.

getHarness("pi").promptTemplates still lists every verified reusable prompt location. promptTemplateSyncTarget is the single stable user destination the sync owns for that harness. Formats, frontmatter and CLI limits are in the registry guide.

Skills

Skills live in $XDG_DATA_HOME/agntn/skills/, next to the prompts, one folder with a SKILL.md per skill:

harnesses skills sync --check
harnesses skills sync
import { getAllHarnesses, syncSkills } from "@agntn/harnesses";

const report = syncSkills(getAllHarnesses(), true);
console.log(report.skills, report.targets);

Every harness's user skills directory, ~/.claude/skills/, ~/.agents/skills/ for Codex, ~/.pi/agent/skills/ and the rest, becomes one symlink to that folder. A skill written through Claude is already there when Pi looks. Old setups with a symlink per skill get replaced without ceremony, and a directory with real skills in it is backed up to diverged/skills/ first. Already keep skills in a dotfiles repo? Make the XDG folder a symlink to it. The sync leaves a harness directory alone if the source points into it, instead of moving your only copy away. skillsSyncTarget names the directory it links for each harness, null for Copilot and Freebuff, which have no user skills directory in the registry.

🗺️ Harnesses

IDNameProject skills
antigravityGoogle Antigravity CLI.agents/skills/
claudeAnthropic Claude Code.claude/skills/
codexOpenAI Codex CLI.codex/skills/
cursorCursor.cursor/skills/
freebuffFreebuff.agents/skills/
geminiGoogle Gemini CLI.gemini/skills/
github-copilotGitHub Copilot.github/skills/
grokxAI Grok CLI.grok/skills/
mastracodeMastra Code.mastracode/skills/
ompOMP (oh-my-pi).omp/skills/
opencodeOpenCode CLI.opencode/skills/
prime-agentPrime Agent.prime/agent/skills/
piPi Coding Agent.pi/skills/

That's the project directory. Most of them also keep a copy under your home directory, and a few read someone else's skills folder on purpose. Sessions, hooks, audio, video, the whole sheet: Harnesses.

🤖 Agents

harnesses mcp
pi install npm:@agntn/harnesses
omp install @agntn/harnesses
{
  "mcpServers": {
    "harnesses": { "command": "npx", "args": ["-y", "@agntn/harnesses", "mcp"] }
  }
}

Eleven tools, the same eleven on MCP, Pi and OMP. harnesses_detect, harnesses_info and harnesses_mcp_list only read. harnesses_run is the one that can spend tokens. tools is required, so the model has to pick advisor or agent. What each call returns is on the Agents page.

🚫 What this does not do

It does not install skills, drive a browser, or run a sandbox of its own. invoke() is the harness CLI plus process cleanup. The wide, thin agent list is unagent.

🧩 Adding a harness

Want a fourteenth? One class extending Harness, then registerHarness. getHarness, the CLI and the tools pick it up. How to write that class: Custom harnesses.

🛠️ Development

pnpm install     # docs/ too: one workspace, one lockfile
pnpm lint        # builds first, then vp lint and vp fmt --check
pnpm lint:fix
pnpm typecheck
pnpm test:run
pnpm build       # obuild
pnpm run docs    # the Docus site; plain `pnpm docs` is a pnpm 12 builtin

💛 Thanks

Anthropic and OpenAI both run programs this package was built with. Claude for Open Source and Codex for Open Source. Thank you <3

📄 License

MIT

↑↓ navigate openesc close