@viper-ai/harness
v0.2.2
Published
VIPER Harness Format (VHF) — schemas and per–agent-tool transformers
Readme
@viper-ai/harness
VIPER Harness Format (VHF) — schemas, validators, and per–agent-tool transformers. Maps your HarnessArtifact[] (content + metadata) to repo-local paths each coding agent reads. VIPER’s bundled skills/agents/MCP live in @viper-ai/core (loadViperBundle); the CLI loads them and passes artifacts into this library.
v1 scope: four agent tools
This release implements transformers for four agent tools only:
| ID | Product |
| ------------- | ----------- |
| claude-code | Claude Code |
| cursor | Cursor |
| opencode | OpenCode |
| pi | Pi |
Nine additional tools (Copilot IDE/CLI, Antigravity, Codex, Junie, etc.) are documented in the investigation support matrix but out of scope for v1. Use availableTransformers() to see which targets ship in this package.
agentskills.io alignment
Skills are the only VHF artifact kind that maps to an industry standard. VIPER aligns with the Agent Skills specification:
- One directory per skill with a
SKILL.mdfile. - YAML frontmatter with required
nameanddescriptionfields validated bySkillFrontmatterSchemainsrc/schema/skill.ts. - Optional agentskills.io fields (
license,compatibility,metadata,allowed-tools) pass through when present.
All other VHF kinds — subagent, hook, mcp, rule, instruction, command, plugin — are VIPER-defined schemas in src/schema/. They extend the harness picture where no open standard exists yet. Transformers map VHF canonical shapes to each tool's native on-disk format.
Supported targets (v1)
| Target | Transformer | Skills | Subagents | MCP | Hooks | Notes |
| ------------- | ----------------------- | ------------------- | ------------------- | ------------------------ | ----------------------------- | ------------------------------------------------ |
| claude-code | claudeCodeTransformer | .claude/skills/ | .claude/agents/ | .mcp.json merge | .claude/settings.local.json | Parity with legacy install.ts |
| cursor | cursorTransformer | .cursor/skills/ | .cursor/agents/ | .cursor/mcp.json merge | .cursor/hooks.json v1 | Compat .agents/skills/ when paired with Claude |
| opencode | opencodeTransformer | .opencode/skills/ | .opencode/agents/ | opencode.json → mcp | — | Hooks via OpenCode plugins |
| pi | piTransformer | .pi/skills/ | not installed | not installed | not installed | Partial emit; see below |
Pi (piTransformer) — partial support
Pi reads project skills from .pi/skills/<id>/SKILL.md and repo-wide guidance from AGENTS.md (and optionally SYSTEM.md). VIPER v1 installs skills only for Pi:
- Installed: all six phase skills plus the master
viperskill under.pi/skills/. - AGENTS.md: a marked VIPER block is merged into repo-root
AGENTS.md(append or replace between<!-- viper:harness:start/end -->markers) so Pi agents discover the workflow without duplicating skill bodies. - Not installed (gaps):
- Subagents (
viper-ideator,viper-investigator,viper-executor) — Pi has no first-class subagent files in the repo; delegation profiles require a Pi extension or another agent tool (Claude Code, Cursor, OpenCode). - MCP — the VIPER MCP server entry is not written for Pi; configure MCP via a Pi extension or use Claude/Cursor/OpenCode targets for
viper_record_event/viper_merge_executionduring Execute. - Hooks — validate-on-edit and other hook artifacts are extension-only on Pi.
- Subagents (
For full VIPER Execute (JSONL events + merge), use a target that ships MCP and subagents, or wire Pi extensions manually.
API
getTransformerForTarget(target)— resolve transformer; throws if the target is not registered.availableTransformers()— list target IDs with a registered transformer in this release.applyTargetWrites(root, writes, force)— applyTargetWrite[]with merge policies (mcp-viper,claude-post-tool-use,agents-md-viper).shouldEmitAgentsCompatSkills(targets)— when bothclaude-codeandcursorare selected, emit.agents/skills/once.
Multi-target overlap
Agent tools do not use isolated namespaces. A multi-target viper init must avoid writing the same skill ID to every path each tool can read.
| Situation | Behavior |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| claude-code + cursor only | Skills once under .agents/skills/; Cursor skips .cursor/skills/; Claude still gets .claude/skills/ (Claude’s native tree). |
| pi or opencode also selected | No .agents/skills/ compat layer — Pi and OpenCode already index that tree and would report skill collisions. Each tool gets its own skill directory. |
| Claude in a git subfolder | Claude walks up to the repo root and loads every .claude/skills/ on the path. Installing into tmp/ while the parent repo already has VIPER skills can look like “duplicates” in the UI. |
| OpenCode slash commands | OpenCode loads skills via the skill tool (and /skills in the TUI). /viper style commands need separate .opencode/commands/<name>.md files — not generated in v1. |
| Pi startup “skill conflicts” | Harmless when .agents/skills/ was present; compat is now omitted whenever Pi is a target. The “No models available” line is unrelated to VIPER (Pi provider login). |
Install (npm consumers)
npm install @viper-ai/harnessOnly @viper-ai/harness is required for VHF schemas and transformers. VIPER’s default skills/agents ship inside @viper-ai/cli / @viper-ai/mcp (via viper init), not as a separate templates package.
import { getTransformerForTarget, applyTargetWrites, type HarnessArtifact } from '@viper-ai/harness';
const artifacts: HarnessArtifact[] = [
/* ... */
];
const writes = getTransformerForTarget('cursor')(artifacts, {
root: process.cwd(),
target: 'cursor',
force: false,
});
await applyTargetWrites(process.cwd(), writes, false);Building, packaging, and tests (monorepo)
npm run package:libs # build harness + copy templates into dist/files
npx nx test @viper-ai/harnessPublish folder: libs/harness/ — tarball is dist/, README.md, and package.json only (no VIPER template markdown).
npm run link:harness # local adoption in another repo
npm run release:publish # nx release publish (with cli + mcp)Conformance specs under src/transformers/*.conformance.spec.ts compare transformer output to checked-in golden trees in src/transformers/__golden__/.
