Skip to content

Epic: Claude Code as a first-class Squad 2.0 host, and the non-Copilot host that promotes the v0.2 profiles #2438

Open
2 of 4 issues completed

Description

@bradygaster

Problem

Squad 2.0 projects into seven hosts, and Claude Code is one of only two with live lab runs (LIVE_HOSTS in test/squad-20-host-feature-matrix.test.ts). But the Claude projection only uses what every host has in common:

  • One coordinator file. HOST_PROJECTIONS.claude (packages/squad-sdk/src/client/adapters/adapters.ts) writes .claude/agents/squad.md, a CLAUDE.md block, .mcp.json and a .gitignore line. Every member is spawned as a generic subagent with their charter pasted into the prompt.
  • The authoritative coordinator is the Copilot file. The Claude coordinator is told to read .github/agents/squad.agent.md, which is 80 KB.
  • native-hooks is advertised but never projected. PROJECTION_TOKENS.claude in capabilities.ts claims it, and no hook file is written.
  • Model selection is marked unsupported on a stale premise. The matrix (test-fixtures/spec/suite-v0.2/host-feature-matrix.json, model-selection.claude) says "Task has no per-call model". Claude Code's subagent tool is now Agent, and it takes model, run_in_background and isolation. Subagent definitions also take model and effort in their frontmatter.
  • squad watch --execute is degraded because no Claude preset exists for --agent-cmd.
  • Startup friction. Users must run claude --agent squad --mcp-config .mcp.json because project MCP servers need approval first. Headless runs without the flag halt on the state-backend handshake.

More importantly, both v0.2 profiles are blocked on work a Claude harness would do:

  • squad-client-harness-adapters/v0.2 §15.1 requires contract tests "against at least GitHub Copilot plus one non-Copilot host".
  • squad-client-backend-decoupling/v0.2 §14.4 requires "at least one real execution harness".
  • Today, "No HarnessAdapter implementation ships in the SDK or CLI" (harness-adapters §3), and the MCP bridge reports executionAvailable: false.

Goal

Make Claude Code a host where Squad uses Claude's own features (subagents, hooks, skills, plugins, the Agent SDK) rather than the shared minimum. In doing so, ship the first real HarnessAdapter and use Claude as the non-Copilot host that moves both v0.2 profiles toward promotion.

The spec stays the authority: every host-specific addition goes through the projection contract (harness-adapters §4–§5, §13) and the charter extension rules (charter §8), not around them.

Phases

Phase Scope Suggested owner Depends on
0 Spec/code agreement for Claude squad:docs-devrel, squad:architect none
1 Claude Agent SDK HarnessAdapter squad:sdk-runtime-dev, squad:agent-orchestration-dev 0
2 Charters compile to Claude member subagents squad:typescript-api-contract-designer, squad:cli-dev 0
3 Governance through Claude Code hooks squad:security-reviewer, squad:sdk-runtime-dev 2
4 Skills projection and coordinator slimming squad:agent-orchestration-dev 0
5 Distribution as a Claude Code plugin squad:plugin-platform-dev 2, 3, 4
6 Automation: watch preset and CI engines squad:cli-dev, squad:agentic-workflows-dev 0 (the preset runs the claude CLI, not the Phase 1 harness)
7 Host-neutral canonical coordinator (decision) squad:architect none, but informs 4

Phases 1, 2, 4 and 6 can run in parallel once 0 lands.

Waves

Wave Phases Starts when
1 0 (spec/code agreement), 7 (ADR only) now
2 1 (harness), 2 (member subagents), 4 (skills + slimming), 6 (watch preset), in parallel Phase 0 merged
3 3 (hooks) Phase 2 merged
4 5 (plugin) Phases 2, 3 and 4 merged

The critical path to promoting the v0.2 profiles is 0 → 1. Phases 2–5 make Claude a better host, but the profiles don't wait on them.

PR plan

PR Contents Notes
1 (#2440) Phase 0 + the Phase 7 ADR (status Proposed) + the regression guards below Merges first. Adding the guards here means every later PR is checked against them. Merging does not approve the ADR.
2 (#2441) Phase 1 Kept on its own so spec reviewers can read it against harness-adapters §15 and decoupling §14.
3 (#2442) Phases 2, 3 and 4 + the Phase 6 watch preset ("Claude projection v2") One Claude projection version bump (§5) instead of three, one rollback suite, one upgrade diff. If it gets too big to review, split Phase 3 (hooks) into its own PR for the security review; hooks are opt-in and advisory, so they need no extra bump.
4 (#2443) Phase 5 After the plugin MCP-approval measurement. Its own projection version change.

PRs 2 and 3 can be developed in parallel once PR 1 merges; they don't touch the same files. Implementing Phase 7, if approved, is a separate later PR.

Additive by design: what this must not break

Almost all of this epic adds new files, new adapters or new opt-in behaviour. None of it changes what an existing Copilot install, or an existing --client claude install, gets until the user opts in. Each child issue states which category it is in.

Phase Category How existing behaviour is preserved
0 Docs and fixtures, plus one generated-text change Spec text, docs and matrix cells. The Task → Agent rename in client/adapters/coordinator.ts changes the generated .claude/agents/squad.md, so existing Claude installs see a small diff on squad upgrade. Copilot output is unchanged.
1 Purely additive A new HarnessAdapter behind the existing HarnessRegistry. The bridge only admits turns when a harness is registered; without one it keeps returning unavailable. The Claude Agent SDK is an optional peer dependency, loaded lazily. @github/copilot-sdk stays a hard dependency in this epic; making it optional is a separate, versioned change.
2 Additive with fallback Member files are written only when claude is in clients[]. If a user-authored, unmanaged .claude/agents/<id>.md already exists, Squad skips it and reports, never overwrites. Dispatch uses a named member when its file exists and falls back to today's generic subagent with the pasted charter otherwise.
3 Opt-in, then advisory, then enforcing Hooks are off by default (a .squad/config.json flag). The first release runs lockout in advisory mode (log and warn, never deny); enforcement is a later default change with its own CHANGELOG entry. The .claude/settings.json merge is additive and never touches user hooks.
4 Additive for Claude only Skills are projected into .claude/skills/, a new location. Slimming applies to the Claude coordinator only; the shared core digest and the Copilot .github/agents/squad.agent.md are not changed by this epic.
5 Additive The plugin ships alongside squad init --client claude, not instead of it. Both paths keep working.
6 Additive A new --agent-cmd preset; the default runner is unchanged.
7 Not additive Moving the canonical coordinator is a structural change. It stays a decision record in this epic, with no implementation, until it is approved separately. If approved, the generated Copilot file must be byte-identical to today's.

Regression guards every child PR keeps green:

  • The Copilot projection is byte-identical before and after (snapshot test over squad init / squad upgrade with --client copilot).
  • squad upgrade on a repo without claude in clients[] produces no diff.
  • squad upgrade --client claude on an existing Claude install changes only Squad-managed files, and rollback (uninstallClients) restores the pre-epic bytes.
  • The existing host-feature matrix tests and the G1–G9 golden trace pass unchanged for every host other than Claude.

Phase 0: spec/code agreement

ADR-001: where the code and the spec disagree, the code wins and the documents are corrected.

  • Harness-adapters §7.2 and the Claude dispatch section in client/adapters/coordinator.ts: rename Task to Agent, and describe its model, run_in_background and isolation: "worktree" parameters. Same rename in docs/src/content/docs/concepts/squad-2-0-architecture.md and in the matrix JSON that generates reference/host-feature-matrix.md (the model-selection and subagent-MCP-inheritance rows). The matrix already says Agent in background-agents.claude, so it currently contradicts itself.
  • Harness-adapters §13 says the Claude .gitignore uses <!-- SQUAD:claude:START --> / END markers. apply.ts writes # squad:claude (linesMarker). Correct the spec.
  • Re-evaluate the model-selection.claude cell against the current Agent tool and subagent frontmatter, and drop the expected-fail if the digest gains the section.
  • Add a Claude Code section to docs/src/content/docs/scenarios/client-compatibility.md, which today covers only Copilot surfaces.
  • Make the README platform badge and model fallback chains host-aware, or label them as Copilot-specific.
  • Add the regression-guard tests listed above (Copilot projection snapshot, no-diff upgrade without claude), so later PRs are checked against them.
  • State that the shared-digest gaps (gitlab-issues, azure-devops, monorepo-team-root, dual-root-remote-mode) are out of scope. They are unsupported for every host, not a Claude-specific gap.

Phase 1: Claude Agent SDK HarnessAdapter

  • Implement HarnessAdapter (packages/squad-sdk/src/backend/types.ts) on the Claude Agent SDK (TypeScript), with id claude-agent-sdk:
    • submit → query(); stream assistant and tool messages as message events, and subagent work as task events.
    • approval-requested → the canUseTool callback. The harness supplies the opaque hash (decoupling §8); suggested: SHA-256 of the canonical tool name and input.
    • respondApproval resolves the pending canUseTool promise, idempotently by operationId.
    • cancel(runId) → abort the query, idempotently by operationId.
    • Stamp every outbound event with the submission epoch (decoupling §9).
    • Declare extensionNamespaces: ['x-claude'].
  • Make @github/copilot-sdk an optional peer dependency, so a Claude-only install doesn't pull it in. Today packages/squad-sdk/package.json has it as a hard dependency.
  • Register the harness with squad state-mcp --experimental-backend when it is available, so squad_backend_send_message admits turns instead of returning unavailable.
  • Contract tests: run the same HarnessAdapter assertions against Copilot and Claude (harness-adapters §15.1, §15.5).
  • Golden trace: run test-fixtures/spec/suite-v0.2/golden-trace.json (G1–G9) against the real Claude harness (decoupling §14.4).
  • Approval traces: approve, deny, hash mismatch and replay round-trip through canUseTool (harness-adapters §15.3, decoupling §14.3).
  • Live tests run only when SQUAD_REAL_CLI_TESTS=1 is set, as test/clients-real-cli.test.ts already does. Unit tests use a fake SDK transport.
  • Auth: the harness takes an Anthropic API key, ANTHROPIC_BASE_URL, or Bedrock/Vertex settings, not a personal claude.ai login (check Anthropic's current terms for Agent SDK products).
  • Evidence: run the official contract, golden-trace and live-matrix runs against a direct Anthropic API, Bedrock or Vertex endpoint. A Copilot bridge serves the model from Copilot's backend and translates the protocol, so it isn't independent non-Copilot evidence and may drop thinking, effort or parallel tool calls. If a bridge is used, record it in the evidence string.

Phase 2: charters compile to Claude member subagents

Charter v0.1 §6 and Execution Preferences v0.1 §2 map onto Claude subagent frontmatter:

Charter field .claude/agents/<id>.md
Identity: ID name
Identity: Purpose description (plus routing ownership from routing.md)
Model: Preferred model, omitted when auto (charter §6: auto must not become a literal)
Model: Reasoning Effort effort: the portable low, medium, high, xhigh and max match Claude's scale
Model: Context Tier long-context model selection where available; report loss otherwise (exec-prefs §6)
  • Add a Claude target to agents/charter-compiler.ts, which today emits only SquadCustomAgentConfig for the Copilot SDK.
  • Carry host-only settings in a charter extension (charter §8): a tools allowlist (e.g. read-only Scribe and Fact Checker) and isolation: worktree for implementers. Register the namespace, since squad is reserved for the spec project. Per charter §13.1, these are runtime config, not authorization.
  • squad cast and squad upgrade --client claude write one managed .claude/agents/<id>.md per member, plus the built-ins (Scribe, Ralph, Rai, Fact Checker).
  • The Claude dispatch section routes to named members instead of generic subagents with pasted charters.
  • Extend harness-adapters §7.1 / §7.3 supportFiles with the member files, and bump the Claude projection version (§5: the anchor is unchanged, but the file set grows).
  • Byte-preserving rollback tests for the new files (harness-adapters §15.7).

Phase 3: governance through Claude Code hooks

  • PreToolUse: reviewer lockout per governance-review §6. An Edit/Write by an author in the review subject's lockout set is denied, with the reason taken from squad_state.
  • SessionStart: run the squad_state_health version/dir handshake (coordinator item 16) and inject roster and routing context.
  • SubagentStop / Stop: emit the coordination-handoff result envelope, trigger Scribe's inbox merge when the inbox is non-empty, and apply the Ralph circuit breaker.
  • Project the hooks into .claude/settings.json as a Squad-owned, additively merged block (same rules as .mcp.json; never clobber user hooks). This makes the advertised native-hooks token true.
  • Tests: lockout denial, an override recorded by an authority, the deadlocked state, and hook removal on rollback.

Phase 4: skills projection and coordinator slimming

  • Write templates/skills/* into .claude/skills/, so Claude loads them only when needed, instead of the coordinator scanning skill roots by hand (coordinator item 17).
  • Move on-demand sections (Ralph mode, PRD mode, ceremonies, Issues mode, casting) out of the always-loaded coordinator and into skills. Keep the core small.
  • Keep the skill-precedence semantics (.squad/skills/ first) and the untrusted-content rule.

Phase 5: distribution as a Claude Code plugin

  • Publish a Squad plugin and marketplace in github/squad, bundling the coordinator agent, member-agent generation, skills, hooks, the squad_state MCP server and slash commands (/squad:ralph, /squad:cast, /squad:ceremony, /squad:status).
  • Verify first: whether plugin-provided MCP servers remove the project .mcp.json approval step and the --mcp-config requirement in interactive and headless (claude -p) runs. Record the measurement in the matrix rather than assuming it.
  • Ship the team dashboard as /squad:dashboard (/squad:dashboard: ship the team dashboard in the Claude Code plugin #2460), on top of the live-session reader (Claude team dashboard: read live Claude Code sessions instead of captured stream-json #2459).
  • Moving the coordinator anchor into a plugin is a projection-version change (harness-adapters §5). Update §7 and keep squad init --client claude working for repos that don't use plugins.

Phase 6: automation

  • Add a built-in Claude preset for squad watch --execute, e.g. claude -p {prompt} --agent squad --mcp-config .mcp.json --output-format stream-json. Flip ralph-cli-triage-watch.claude from degraded.
  • Verify first: whether gh-aw supports a Claude engine. If it does, re-evaluate the gh-aw.claude cell, currently n/a ("Runs in GitHub Actions with the Copilot engine").

Phase 7: host-neutral canonical coordinator (needs decision)

  • Decide whether the canonical coordinator moves from .github/agents/squad.agent.md to a host-neutral source (e.g. under .squad/ or .squad-templates/), with Copilot's file generated from it like every other host's.

Follow-ups from the end-to-end test

A Claude Code end-to-end run built a game from an empty repo: casting, member subagents in parallel, the reviewer gate, Rai, decisions, and the SessionStart and Stop hooks all worked. These came out of it.

Findings

Team dashboard (prototype on squad/2443-claude-plugin, prototypes/claude-dashboard/)

Success criteria

  • At least one real HarnessAdapter (Claude Agent SDK) ships, and squad_backend_send_message admits turns when it is registered.
  • Contract tests and the G1–G9 golden trace pass against both Copilot and Claude, meeting harness-adapters §15.1/§15.5/§15.6 and decoupling §14.4 for the harness requirement.
  • In the host matrix, no Claude cell is unsupported or degraded where Claude Code has a native primitive for the feature (model selection, Ralph watch, hooks). Shared-digest gaps that affect every host are out of scope.
  • Reviewer lockout on Claude is enforced by a hook, not just by prompt text, with tests for deny, override and deadlock.
  • The documented Claude quick start is one command with no --mcp-config, if Phase 5 verification confirms that's achievable.
  • Spec and code agree on every Claude-specific fact (Phase 0 list).

Open questions

  1. Charter extension namespace for host settings: one per host (e.g. X-claude-*), or a single Squad-registered namespace?
  2. Does the Claude harness run subagents through the Agent SDK's agents option (one query per conversation), or one query per member run? This affects how task events map to broker run identity (harness-adapters §7.2).
  3. Should the plugin replace squad init --client claude, or ship alongside it?
  4. Phase 7: is moving the canonical coordinator off the Copilot path acceptable for the Copilot surfaces that auto-discover .github/agents/?

Activity

  1. added
    squadSquad triage inbox — Lead will assign to a member
    type:epicParent issue that decomposes into sub-issues
    squad:architectAssigned to architect (Lead Architect)
    on Nov 9, 2026
  2. github-actions commented on Nov 9, 2026

    @github-actions
    Contributor

    📋 Assigned to architect (Lead Architect)

    Issue: #2438 — Epic: Claude Code as a first-class Squad 2.0 host, and the non-Copilot host that promotes the v0.2 profiles

    architect will pick this up in the next Copilot session.

    For Copilot coding agent: If enabled, this issue will be worked automatically.
    Otherwise, start a Copilot session and say:
    architect, work on issue #2438

  3. bradygaster commented on Nov 9, 2026

    @bradygaster
    CollaboratorAuthor

    Research: does gh-aw support a Claude engine? (#2442 Phase 6)

    Yes. gh-aw has Claude Code as a built-in engine (engine: claude), alongside Copilot (the default), Codex, Pi and Agy. Source: gh-aw's reference/engines.md and the Claude engine reference.

    • Credentials: an ANTHROPIC_API_KEY, Anthropic workload identity federation, or Copilot-hosted Claude models through permissions: copilot-requests: write (billed through Copilot; no Anthropic key needed). Subscription OAuth tokens aren't supported.
    • Agent selection: Claude has no native engine.agent setting (only Copilot does). To run the Squad coordinator, pass engine.args: ["--agent", "squad"].
    • .claude/ files: gh-aw takes a copy of .claude/ from the trusted checkout and restores it after the agent's checkout, so projected agents and skills are available.
    • Permissions: the default is dontAsk. engine.permission-mode accepts default, auto, acceptEdits, plan and bypassPermissions.
    • Other features: MCP goes through gh-aw's gateway, and max-turns and session resume (--resume) are supported.
    • Caveat: "bare" mode turns off subagent delegation, so Squad would need bare: false.

    Conclusion: a Squad workflow on gh-aw with Claude looks feasible without changes to gh-aw. Not yet tried end to end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    go:needs-researchNeeds investigationsquadSquad triage inbox — Lead will assign to a membersquad:architectAssigned to architect (Lead Architect)type:epicParent issue that decomposes into sub-issues

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions