npm package: @tanagram/harness
Description: Full feature lifecycle for Claude Code — worktrees, dev stack, real testing, PRs.
Author: Tanagram
Latest version: 0.1.4

# tanagram-harness

A Claude Code plugin that gives you the full feature lifecycle in one command — isolated worktrees, dev stack orchestration, real testing, and PR creation.

```
/harness start fix-auth-flow
/harness test
/harness pr
/harness cleanup
```

Inspired by [OpenAI's Harness Engineering](https://openai.com/index/building-with-codex/) — the idea that every feature should be developed in an isolated, bootable environment with mechanical enforcement and real validation.

## Install

```
/plugin install ./tanagram-harness --scope user
```

Or from the marketplace:

```
/plugin marketplace add tanagram/harness
/plugin install tanagram-harness
```

## Quick Start

1. Generate a `harness.json` for your project:
   ```
   npx @tanagram/harness init
   ```
   This detects your project structure and walks you through setup interactively. (Optional — works without one for simple single-service projects.)

2. Run `/harness start my-feature`
3. Develop your feature in the isolated worktree
4. Run `/harness test` to verify against real running services
5. Run `/harness pr` to create a pull request
6. Run `/harness cleanup` to remove the worktree and free ports

## `harness.json` Reference

```json
{
  "baseBranch": "origin/main",
  "envFiles": ["**/.env"],
  "services": [
    {
      "name": "api",
      "directory": "backend",
      "install": "poetry install --with dev",
      "start": "poetry run uvicorn main:app --port ${PORT}",
      "port": 8000,
      "health": "/health",
      "test": "poetry run pytest -x",
      "dependsOn": []
    },
    {
      "name": "web",
      "directory": "frontend",
      "install": "pnpm install",
      "start": "PORT=${PORT} pnpm dev",
      "port": 3000,
      "health": "/",
      "test": "pnpm test && pnpm typecheck",
      "dependsOn": ["api"],
      "env": {
        "VITE_API_BASE_URL": "http://localhost:${ports.api}"
      }
    }
  ],
  "portOffset": 10,
  "browser": { "entry": "web" }
}
```

### Top-Level Fields

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `baseBranch` | string | `"origin/main"` | Branch to create worktrees from |
| `envFiles` | string[] | `["**/.env", "**/.env.local"]` | Glob patterns for env files to copy into worktrees |
| `services` | Service[] | auto-detected | Services to start |
| `portOffset` | number | `10` | Port offset multiplier per worktree slot |
| `browser.entry` | string | first service | Which service to open in browser for verification |

### Service Fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | yes | Service identifier |
| `directory` | string | yes | Subdirectory relative to project root |
| `install` | string | no | Dependency install command |
| `start` | string | yes | Start command (`${PORT}` is substituted with the allocated port) |
| `port` | number | yes | Base port number |
| `health` | string | no | Health check endpoint path (e.g. `"/health"`) |
| `test` | string | no | Test command |
| `dependsOn` | string[] | no | Services that must start before this one |
| `env` | object | no | Env vars to set when starting. Values support `${ports.SERVICE}` to reference another service's allocated port |

## Without `harness.json`

For simple single-service projects, the plugin auto-detects:

- **Node.js** (`package.json`): `npm install` → `npm run dev` on port 3000
- **Python** (`pyproject.toml`): `poetry install` → `poetry run uvicorn` on port 8000

No config needed.

## Commands

### `/harness start [feature-name]`

Creates an isolated git worktree, copies env files, installs dependencies, starts all services with auto-allocated ports, and enters plan mode to begin development.

### `/harness test [feature-name]`

Runs service tests per `harness.json`, verifies in-browser via Chrome DevTools MCP, and checks stack logs for errors. All tests run against real services — no mocks.

### `/harness pr [feature-name]`

Stages changes, commits, pushes, and creates a GitHub PR with summary and test plan.

### `/harness cleanup [feature-name]`

Stops all services, frees ports, removes the worktree, and optionally deletes the remote branch.

### `/harness status`

Lists active worktrees, running stacks, and port allocations across all features.

## Port Allocation

Each concurrent worktree gets a slot. Ports are offset by `slot * portOffset`:

| Service | Base | Slot 1 | Slot 2 | Slot 3 |
|---------|------|--------|--------|--------|
| api     | 8000 | 8010   | 8020   | 8030   |
| web     | 3000 | 3010   | 3020   | 3030   |

Port assignments are tracked in `~/.claude/stack-registry.json`.

## Example Configs

### Next.js App

```json
{
  "services": [
    {
      "name": "web",
      "directory": ".",
      "install": "npm install",
      "start": "PORT=${PORT} npm run dev",
      "port": 3000,
      "health": "/",
      "test": "npm test"
    }
  ]
}
```

### Django + React

```json
{
  "baseBranch": "origin/main",
  "services": [
    {
      "name": "api",
      "directory": "api",
      "install": "pip install -r requirements.txt",
      "start": "python manage.py runserver 0.0.0.0:${PORT}",
      "port": 8000,
      "health": "/api/health/",
      "test": "python manage.py test"
    },
    {
      "name": "web",
      "directory": "web",
      "install": "npm install",
      "start": "REACT_APP_API_URL=http://localhost:8010 PORT=${PORT} npm start",
      "port": 3000,
      "health": "/",
      "test": "npm test",
      "dependsOn": ["api"]
    }
  ],
  "browser": { "entry": "web" }
}
```

### Rails + Sidekiq

```json
{
  "services": [
    {
      "name": "web",
      "directory": ".",
      "install": "bundle install",
      "start": "PORT=${PORT} bin/rails server",
      "port": 3000,
      "health": "/up",
      "test": "bin/rails test"
    },
    {
      "name": "worker",
      "directory": ".",
      "start": "bundle exec sidekiq",
      "port": 7433,
      "dependsOn": ["web"]
    }
  ]
}
```

## How It Works

1. **Worktree isolation** — Each feature gets its own git worktree branched from your base branch. The main repo stays clean.
2. **Port allocation** — A registry at `~/.claude/stack-registry.json` tracks which ports are in use across all active features. Each worktree gets a unique slot so services never collide.
3. **Config-driven services** — `harness.json` declares your services, their start commands, health checks, and test commands. The plugin handles dependency ordering, parallel installs, and health check polling.
4. **Real testing** — The skill explicitly instructs Claude to test against real running services, never mocks. Browser verification uses Chrome DevTools MCP.
5. **State tracking** — Each worktree gets a `.feature-meta.json` and `.stack/` directory for PIDs, logs, and port assignments.

## License

MIT