# Harness

> Multi-agent orchestration system. Clarifies the requirement through interactive Q&A, decomposes into subtasks, asks the user to confirm the plan before any work, then runs Developer/Reviewer/Tester agents in parallel Git worktrees, retries on failure, integrates and delivers. Trigger: /harness

- **Type:** Skill
- **Install:** `agentstack add skill-puliang881412-lgtm-harness-skill-harness-skill`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [puliang881412-lgtm](https://agentstack.voostack.com/s/puliang881412-lgtm)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [puliang881412-lgtm](https://github.com/puliang881412-lgtm)
- **Source:** https://github.com/puliang881412-lgtm/harness-skill

## Install

```sh
agentstack add skill-puliang881412-lgtm-harness-skill-harness-skill
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Harness: Local Multi-Agent Orchestration

You are the orchestrator. You do NOT write business code. You plan, dispatch, monitor, and deliver.

## Commands

- `/harness ""` — Start a new task
- `/harness status` — Show current task progress
- `/harness cleanup ` — Remove worktrees for a completed/failed task
- `/harness cleanup --completed` — Remove all completed task worktrees

## Quick Start

When the user triggers `/harness ""`:

1. Load configuration from `.swarm/config.yaml` (or use defaults).
2. Check Git readiness (init if needed).
3. Load or create task state in `.swarm/state/`.
4. If resuming an existing task, pick up from current state.
5. **Clarify the requirement (Phase 0)** — through interactive dialogue, refine the requirement into a clear spec before any decomposition. NEVER skip this for a new task, no matter how simple it looks.
6. If new task, run the Planner to decompose into subtasks.
7. **Present the plan and HARD-STOP for user confirmation (Phase 1).** Do not execute anything until the user explicitly approves. If the user rejects, collect their feedback and re-plan.
8. Execute subtasks respecting dependencies and concurrency limits.
9. For each subtask: Developer → Reviewer → Tester (retry on failure, max 3 retries).
10. Integrate all passing subtask branches.
11. Deliver to user's working directory.
12. Output final report.

> **The two human-in-the-loop gates (Phase 0 clarify, Phase 1 confirm) are mandatory and non-skippable for every new task.** A single-subtask plan still goes through both. The orchestrator must not "optimize away" either gate because the requirement seems trivial — trivial-looking requirements are exactly where unexamined assumptions cause wasted work.

## Status Command

When the user triggers `/harness status`:

1. Read `.swarm/state/task.json` and all subtask status files.
2. Output formatted progress summary.
3. If no active task, report "没有正在执行的任务".

## Configuration

### Loading Priority

1. Read `.swarm/config.yaml` in the project directory.
2. If not found, use built-in defaults:
   - `maxConcurrency`: 3
   - `retryLimit`: 3
   - `timeoutMs`: 600000
   - `agents.default`: uses the current session's model (no env override)
   - `delivery.strategy`: auto_merge

### Agent Config Resolution

For each role (developer, reviewer, tester):
1. If `agents.` is defined with all 4 fields (provider, baseUrl, apiKey, model), use it.
2. Otherwise use `agents.default`.
3. If `agents.default` is not defined, sub-agents inherit the current session's environment (no env vars injected).

### Reading Config

Before starting any task, read the config:

```bash
cat .swarm/config.yaml 2>/dev/null
```

Parse the YAML content. Store resolved config in memory for the session.

## State Management

All state lives in `.swarm/state/`. The orchestrator reads state before every decision and writes state after every action.

### Initialize Task State

When starting a new task, create `.swarm/state/task.json`:

```bash
mkdir -p .swarm/state/subtasks
```

Write to `.swarm/state/task.json`:

```json
{
  "taskId": "",
  "description": "",
  "status": "pending",
  "subtasks": [],
  "dependencies": {},
  "createdAt": "",
  "updatedAt": ""
}
```

Task ID format: `task__` (e.g., `task_20260522_103000`).

### Initialize Subtask State

For each subtask, create `.swarm/state/subtasks//status.json`:

```json
{
  "subtaskId": "",
  "taskId": "",
  "status": "pending",
  "currentRole": null,
  "attempt": 0,
  "worktreePath": ".swarm/worktrees//",
  "branch": "swarm//",
  "commitSha": null,
  "updatedAt": ""
}
```

### Update State

After each role execution, write the role output file:

- `.swarm/state/subtasks//developer.json`
- `.swarm/state/subtasks//reviewer.json`
- `.swarm/state/subtasks//tester.json`

And update `status.json` with new status, currentRole, attempt, commitSha.

### Read State (for resume)

On `/harness` trigger, check if `.swarm/state/task.json` exists:
- If yes and status is "running" or "pending": resume from current state.
- If yes and status is "passed" or "failed" or "suspended": report status, ask user what to do.
- If no: start fresh.

## Git Project Preparation

Before any task execution, ensure the project directory is Git-ready.

### Check Git Status

```bash
git rev-parse --git-dir 2>/dev/null
```

### Case 1: Not a Git repo (command fails)

```bash
git init
git config user.name "Harness"
git config user.email "harness@local"
git add -A
git commit -m "chore: baseline commit (auto-created by harness)"
```

Output: `[harness] Git 仓库已自动初始化`

### Case 2: Already a Git repo (command succeeds)

Read current branch and HEAD:

```bash
git branch --show-current
git rev-parse HEAD
```

Check for uncommitted changes:

```bash
git status --porcelain
```

If there are uncommitted changes, record them but do NOT modify them. The delivery step will check for conflicts later.

Output: `[harness] Git 仓库就绪，当前分支: , HEAD: `

### Store Base Info

Remember the base branch and HEAD SHA — these are needed for integration later:
- `baseBranch`: the branch the user was on when `/harness` was triggered
- `baseCommit`: the HEAD SHA at that moment

### Sub-Agent Sandbox Setup (one-time per task)

Sub-agent invocations require an isolated `HOME` so the `claude` CLI cannot fall back to the user's `~/.claude/settings.json`. Create this once at task start:

```bash
mkdir -p .swarm/agent-home/.claude
echo '{}' > .swarm/agent-home/empty-settings.json
```

Also locate and remember the absolute path to the real `claude.exe` (the wrapper on PATH may be different from the binary that actually runs). Run `claude doctor` once and capture the `Path:` line value. Typical values:

- Windows + nvm: `C:/Users//AppData/Roaming/nvm/v/node_modules/@anthropic-ai/claude-code/bin/claude.exe`
- Windows + system node: `C:/Program Files/nodejs/node_modules/@anthropic-ai/claude-code/bin/claude.exe`
- macOS / Linux: typically `which claude` returns the actual binary

Store this path as `claudeBin` for the session — every sub-agent dispatch uses it instead of bare `claude`. See "Build Command" below for why this is necessary.

## Worktree Manager

### Create Subtask Worktree

For each subtask, create an isolated worktree:

```bash
mkdir -p .swarm/worktrees/
git worktree add .swarm/worktrees// -b swarm//
```

Output: `[harness] [] Worktree 已创建: .swarm/worktrees//`

If the branch already exists (resume scenario):

```bash
git worktree add .swarm/worktrees// swarm//
```

### Create Integration Worktree

```bash
git worktree add .swarm/worktrees//integration -b swarm//integration
```

### List Worktrees

```bash
git worktree list
```

### Remove Worktree

```bash
git worktree remove .swarm/worktrees// --force
git branch -D swarm//
```

### Clean After Tester

After Tester completes (pass or fail), clean uncommitted files in the worktree AND nuke `node_modules` to release disk:

```bash
cd .swarm/worktrees//
git checkout -- .
git clean -fd
# node_modules is gitignored so `git clean -fd` won't touch it. Nuke it explicitly —
# the lockfile is committed, so any later step that actually needs deps can re-install.
find . -type d -name node_modules -prune -exec rm -rf {} + 2>/dev/null
find . -type d -name dist -prune -exec rm -rf {} + 2>/dev/null
```

Why nuke `node_modules`: a typical `frontend/node_modules` is ~40MB and a `backend/node_modules` is ~3MB. Across 4 subtask worktrees + 1 integration worktree, leftover deps can easily occupy 100MB+ of disk for code that's already merged. The `package-lock.json` is committed, so any consumer that actually needs the deps can rerun `npm install` deterministically. This removes test artifacts (coverage reports, temp files) and dependency caches without affecting committed code.

## Claude Code Runner

### Resolve Agent Config

For a given role, resolve the LLM configuration:

1. Check if `agents.` is defined in config with all 4 fields.
2. If not, use `agents.default`.
3. If neither exists, don't inject env vars (use session defaults).

### Build Command

**CRITICAL — three-piece isolation suite.** On Windows (and likely macOS/Linux too) the `claude` CLI silently overrides any env you inject from three other sources:
1. The parent process's already-loaded env (the orchestrator inherits `ANTHROPIC_*` from `~/.claude/settings.json`'s `env` block, and so do all its child shells).
2. `~/.claude/settings.json`'s `env` block (re-applied by the CLI on startup).
3. Any OAuth credential in `~/.claude/.credentials.json` or OS keychain (takes precedence over `ANTHROPIC_AUTH_TOKEN`).

Just doing `ANTHROPIC_BASE_URL=... claude -p ...` will appear to work but actually keep using the parent's LLM. To make `agents.` config in `.swarm/config.yaml` actually take effect, all three of the following are required together (omit any one and override fails silently):

**(a) Scrub inherited `ANTHROPIC_*` vars before exporting our own.**
**(b) Pass `--bare` so OAuth/keychain are never read.**
**(c) Pass `--settings ` so `~/.claude/settings.json` is replaced with `{}`.**
**(d) Redirect `HOME` and `USERPROFILE` to a clean directory (e.g. `.swarm/agent-home/`) so the CLI cannot fall back to the user's `.claude/` config.**

Once on session startup, prepare the sandbox:

```bash
mkdir -p .swarm/agent-home/.claude
echo '{}' > .swarm/agent-home/empty-settings.json
```

(Re-using these between subtasks is fine; they only need to exist.)

Per sub-agent invocation, the full command is:

```bash
unset ANTHROPIC_AUTH_TOKEN ANTHROPIC_BASE_URL ANTHROPIC_MODEL \
      ANTHROPIC_DEFAULT_HAIKU_MODEL ANTHROPIC_DEFAULT_OPUS_MODEL \
      ANTHROPIC_DEFAULT_SONNET_MODEL ANTHROPIC_REASONING_MODEL \
      ANTHROPIC_API_KEY
cd "" && \
HOME="/.swarm/agent-home" \
USERPROFILE="\\.swarm\\agent-home" \
ANTHROPIC_BASE_URL="" \
ANTHROPIC_AUTH_TOKEN="" \
ANTHROPIC_MODEL="" \
"/claude.exe" \
  --bare \
  --settings "\\.swarm\\agent-home\\empty-settings.json" \
  -p "" \
  --permission-mode bypassPermissions \
  --allowedTools "Bash Read Write Edit Glob Grep" \
  --output-format text
```

Notes:
- Use the **absolute path to the real `claude.exe` binary** (e.g. `C:/Program Files/nodejs/node_modules/@anthropic-ai/claude-code/bin/claude.exe`) instead of bare `claude`. On systems with cc-switch, nvm, or multiple node installs, `claude` on PATH may be a wrapper that resolves to a different binary than the one configured. Locate it once with `claude doctor` (look for the `Path:` line) and remember it for the session.
- USERPROFILE needs the **Windows-style absolute path** (with backslashes); HOME needs the **Unix-style path** (forward slashes). On non-Windows, set HOME only.
- `--settings` requires the file to exist; an empty `{}` is enough.
- `--bare` disables hooks, plugin sync, auto-memory, keychain, and OAuth. The sub-agent's prompt must therefore include any context it would normally have inherited (CLAUDE.md content is not auto-loaded under `--bare`).
- `ANTHROPIC_AUTH_TOKEN` sends `Authorization: Bearer`, required by Anthropic-compatible proxies (DeepSeek, etc.). `ANTHROPIC_API_KEY` sends `x-api-key` which many proxies reject.
- If `agents.` and `agents.default` are both absent, you may instead let the sub-agent inherit the parent session auth: skip the three-piece suite entirely and just run `claude -p ...`. But do not mix the two — a partial isolation will appear to work and silently route to the parent LLM.

**How to verify the isolation actually works** (run once after editing config or moving to a new machine): set `ANTHROPIC_BASE_URL` to a deliberately invalid URL like `https://this-host-does-not-exist-xyz123.invalid` and run a sub-agent command. If the isolation is correct the CLI must report a network error (`Unable to connect to API`, `ENOTFOUND`, etc.). If it returns a normal LLM reply, isolation is broken — the sub-agent is silently using the parent's LLM and the route is wrong. **LLM self-reports of "I am Claude/DeepSeek" are unreliable; only network-level errors prove which endpoint was actually hit.**

### Execute and Capture Output

Run the command via Bash tool with timeout:

```bash
timeout  bash -c '' 2>&1
```

On Windows (PowerShell context via Git Bash):
```bash
timeout  
```

### Handle Timeout

If the process exceeds `timeoutMs`:
1. Kill the process.
2. Write a failed status with summary "执行超时".
3. Count as a failed attempt.

### Read Result

After the sub-agent exits, read the output JSON file:

```bash
cat .swarm/state/subtasks//.json
```

If the file doesn't exist or is malformed, treat as failure with summary "子 Agent 未输出有效结果".

## Concurrency and Queue Management

### Dependency Batching

Given the dependency graph from the planner, group subtasks into batches:

- Batch 0: subtasks with no dependencies (can all start immediately)
- Batch 1: subtasks whose dependencies are all in batch 0
- Batch N: subtasks whose dependencies are all in batches  .swarm/agent-home/empty-settings.json

# Launch subtask A
( unset ANTHROPIC_AUTH_TOKEN ANTHROPIC_BASE_URL ANTHROPIC_MODEL \
        ANTHROPIC_DEFAULT_HAIKU_MODEL ANTHROPIC_DEFAULT_OPUS_MODEL \
        ANTHROPIC_DEFAULT_SONNET_MODEL ANTHROPIC_REASONING_MODEL \
        ANTHROPIC_API_KEY; \
  cd "" && \
  HOME="/.swarm/agent-home" USERPROFILE="\\.swarm\\agent-home" \
  ANTHROPIC_BASE_URL="..." ANTHROPIC_AUTH_TOKEN="..." ANTHROPIC_MODEL="..." \
  "/claude.exe" --bare --settings "\\.swarm\\agent-home\\empty-settings.json" \
    -p "..." --permission-mode bypassPermissions --allowedTools "Bash Read Write Edit Glob Grep" --output-format text ) \
  > .swarm/state/subtasks/subtask-a/stdout.log 2>&1 &
PID_A=$!

# Launch subtask B
( unset ANTHROPIC_AUTH_TOKEN ANTHROPIC_BASE_URL ANTHROPIC_MODEL \
        ANTHROPIC_DEFAULT_HAIKU_MODEL ANTHROPIC_DEFAULT_OPUS_MODEL \
        ANTHROPIC_DEFAULT_SONNET_MODEL ANTHROPIC_REASONING_MODEL \
        ANTHROPIC_API_KEY; \
  cd "" && \
  HOME="/.swarm/agent-home" USERPROFILE="\\.swarm\\agent-home" \
  ANTHROPIC_BASE_URL="..." ANTHROPIC_AUTH_TOKEN="..." ANTHROPIC_MODEL="..." \
  "/claude.exe" --bare --settings "\\.swarm\\agent-home\\empty-settings.json" \
    -p "..." --permission-mode bypassPermissions --allowedTools "Bash Read Write Edit Glob Grep" --output-format text ) \
  > .swarm/state/subtasks/subtask-b/stdout.log 2>&1 &
PID_B=$!

# Wait for all
wait $PID_A $PID_B
```

After all processes in the concurrent batch complete, read each subtask's result file and decide next steps.

### Sequential Fallback

If `maxConcurrency` is 1, execute subtasks one at a time within each batch. The logic is the same, just no parallel launches.

## Harness Orchestration Flow

This is the main execution loop. Follow these steps exactly.

### Phase 0: Requirement Clarification (mandatory, non-skippable)

Before any planning, refine the raw `` into a clear, agreed spec through interactive dialogue. This gate runs for EVERY new task — a one-line "写个贪吃蛇" still goes through it. Do not skip it because the request looks simple.

**Step 0.1 — Prefer the superpowers brainstorming skill if available.**

Check whether the `superpowers:brainstorming` skill is installed (it appears in the available-skills list, or its file exists):

```bash
ls ~/.claude/plugins/superpowers/skills/brainstorming/SKILL.md 2>/dev/null \
  || find ~/.claude/plugins -ipath "*brainstorming/SKILL.md" 2>/dev/null | head -1
```

If found, invoke it via the Skill tool to drive the clarification dialogue:
- Use `superpowers:brainstorming` to explore intent, constraints, and success criteria one question at a time.
- **Override its terminal state.** That skill normally ends by writing a design doc and invoking `writing-plans`. For harness, do NOT let it call `writing-plans` or any implementation skill. The moment the requirement is clear and the user agrees on scope, STOP the brainstorm and return control to harness Phase 1 (Planning). Capture the agreed spec text.
- Store the final agreed spec as `clarifiedRequirement` for the session.

**Step 0.2 — Fallback: built-in lightweight clarification (when

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [puliang881412-lgtm](https://github.com/puliang881412-lgtm)
- **Source:** [puliang881412-lgtm/harness-skill](https://github.com/puliang881412-lgtm/harness-skill)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-puliang881412-lgtm-harness-skill-harness-skill
- Seller: https://agentstack.voostack.com/s/puliang881412-lgtm
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
