integrate-harness
Goal: produce a production-quality XAdapter extends BaseAgentAdapter with full test coverage and documentation, matching the level of the existing 11 adapters (claude, codex, cursor, gemini, opencode, openclaw, copilot, hermes, pi, omp, adapters-remote).
Checklist
- Capability audit — read the harness's CLI docs. Fill in every
AgentCapabilities field. Unknown? Set conservatively (false) and note in PR.
- Create
packages/adapters/src/<name>-adapter.ts extending BaseAgentAdapter. Required: agent, displayName, cliCommand, minVersion, hostEnvSignals, capabilities, models[], defaultModelId, configSchema, buildSpawnArgs, parseEvent, detectAuth, getAuthGuidance, sessionDir, parseSessionFile, listSessionFiles, readConfig, writeConfig.
- Session parsing — if the harness stores JSONL sessions, delegate to
parseJsonlSessionFile; otherwise write a custom parser and unit-test each event shape.
- Hooks — if the harness supports native hooks, override
writeNativeHook and mirror into HookConfigManager. If not, rely on the base class's virtual hooks.
- Plugins — if it supports MCP servers under
mcpServers in its config JSON, flip supportsPlugins: true, add pluginFormats: ['mcp-server'], and delegate to mcp-plugins.ts (see cursor/gemini/opencode/openclaw for the pattern).
- Register — add to
packages/adapters/src/index.ts exports and to the default registry in packages/core/src/client.ts (if applicable).
- Tests — in
packages/adapters/tests/<name>-adapter.test.ts:
- capability shape
buildSpawnArgs for a few representative RunOptions
parseEvent for each JSONL type the harness emits
detectAuth for authenticated + unauthenticated states
- session file parsing from a real fixture (redacted)
- If plugins: add the adapter to
mcp-plugins-parity.test.ts.
- CLI audit test — ensure
packages/cli/tests/commands-audit.test.ts passes (it exercises every adapter via the built CLI).
- File-size limit — each source file must stay under 400 effective lines (
local/max-file-lines). Split helpers into sibling modules if you're close.
- Docs — add a row to the README capabilities matrix and a paragraph in
docs/02-agents/<name>.md.
- Changeset —
npm run changeset, pick minor (new adapter), summarize.
Verification
npm run typecheck
npm run lint
npm test
npx vitest run packages/adapters/tests/<name>-adapter.test.ts
All existing tests must continue to pass — no regressions in commands-audit.
Common pitfalls
- Forgetting to add the adapter to the default registry →
commands-audit.test.ts won't exercise it.
- JSONL parsers that assume a single event per line — some harnesses emit arrays.
- Auth detection that reads env vars synchronously at construction time instead of
detectAuth() — breaks testability.
buildSpawnArgs returning the string "undefined" for missing options — always gate with if (options.X != null).
- Hook writers that overwrite rather than merge — use
appendJsonHook or appendYamlHook.
1---2name: integrate-harness3description: Use when adding a new agent harness (CLI-based coding agent) adapter to adapters. Covers capability audit, adapter scaffold, session parsing, auth detection, hooks/plugins wiring, tests, and docs.4---56# integrate-harness78Goal: produce a production-quality `XAdapter extends BaseAgentAdapter` with full test coverage and documentation, matching the level of the existing 11 adapters (claude, codex, cursor, gemini, opencode, openclaw, copilot, hermes, pi, omp, adapters-remote).910## Checklist11121. **Capability audit** — read the harness's CLI docs. Fill in every `AgentCapabilities` field. Unknown? Set conservatively (`false`) and note in PR.132. **Create `packages/adapters/src/<name>-adapter.ts`** extending `BaseAgentAdapter`. Required: `agent`, `displayName`, `cliCommand`, `minVersion`, `hostEnvSignals`, `capabilities`, `models[]`, `defaultModelId`, `configSchema`, `buildSpawnArgs`, `parseEvent`, `detectAuth`, `getAuthGuidance`, `sessionDir`, `parseSessionFile`, `listSessionFiles`, `readConfig`, `writeConfig`.143. **Session parsing** — if the harness stores JSONL sessions, delegate to `parseJsonlSessionFile`; otherwise write a custom parser and unit-test each event shape.154. **Hooks** — if the harness supports native hooks, override `writeNativeHook` and mirror into `HookConfigManager`. If not, rely on the base class's virtual hooks.165. **Plugins** — if it supports MCP servers under `mcpServers` in its config JSON, flip `supportsPlugins: true`, add `pluginFormats: ['mcp-server']`, and delegate to `mcp-plugins.ts` (see cursor/gemini/opencode/openclaw for the pattern).176. **Register** — add to `packages/adapters/src/index.ts` exports and to the default registry in `packages/core/src/client.ts` (if applicable).187. **Tests** — in `packages/adapters/tests/<name>-adapter.test.ts`:19 - capability shape20 - `buildSpawnArgs` for a few representative `RunOptions`21 - `parseEvent` for each JSONL type the harness emits22 - `detectAuth` for authenticated + unauthenticated states23 - session file parsing from a real fixture (redacted)24 - If plugins: add the adapter to `mcp-plugins-parity.test.ts`.258. **CLI audit test** — ensure `packages/cli/tests/commands-audit.test.ts` passes (it exercises every adapter via the built CLI).269. **File-size limit** — each source file must stay under 400 effective lines (`local/max-file-lines`). Split helpers into sibling modules if you're close.2710. **Docs** — add a row to the README capabilities matrix and a paragraph in `docs/02-agents/<name>.md`.2811. **Changeset** — `npm run changeset`, pick `minor` (new adapter), summarize.2930## Verification3132```bash33npm run typecheck34npm run lint35npm test36npx vitest run packages/adapters/tests/<name>-adapter.test.ts37```3839All existing tests must continue to pass — no regressions in commands-audit.4041## Common pitfalls4243- Forgetting to add the adapter to the default registry → `commands-audit.test.ts` won't exercise it.44- JSONL parsers that assume a single event per line — some harnesses emit arrays.45- Auth detection that reads env vars synchronously at construction time instead of `detectAuth()` — breaks testability.46- `buildSpawnArgs` returning the string `"undefined"` for missing options — always gate with `if (options.X != null)`.47- Hook writers that overwrite rather than merge — use `appendJsonHook` or `appendYamlHook`.