Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0ed1ba0
chore(prototype): Claude Code team dashboard from the end-to-end test
bradygaster Nov 10, 2026
cde6ab4
test(matrix): record the Claude plugin MCP approval measurement (#2443)
bradygaster Nov 10, 2026
cf28a47
feat(claude): Claude projection v3, plugin mode (#2443)
bradygaster Nov 10, 2026
d16a60f
feat(claude): Squad Claude Code plugin and marketplace (#2443)
bradygaster Nov 10, 2026
a71ecb4
feat(dashboard): read Claude Code session transcripts (#2459)
bradygaster Nov 10, 2026
969c8e9
fix(dashboard): start a member once when its meta file comes first (#…
bradygaster Nov 10, 2026
75b667e
feat(dashboard): local dashboard server, `squad dashboard` and /squad…
bradygaster Nov 10, 2026
f99c386
docs(claude): install the Squad plugin and use the dashboard (#2443, …
bradygaster Nov 10, 2026
0836895
fix(claude): keep the help budget and the retired-term gate green (#2…
bradygaster Nov 10, 2026
0e18df7
docs(changelog): Claude Code as a first-class host (#2438)
bradygaster Nov 10, 2026
f8017ab
docs(changelog): plan the Claude Code notes as the preview.5 headline…
bradygaster Nov 10, 2026
ffb5970
fix(ci): spell-check word and CodeQL test-code alerts (#2463)
bradygaster Nov 10, 2026
b3f599b
fix(claude): ship the plugin's bin/ launchers (#2443)
bradygaster Nov 10, 2026
8f0d155
fix(claude): commands call the plugin launcher; launcher skips an old…
bradygaster Nov 10, 2026
f51257f
test(claude): keep the retired-term gate green in launcher test names…
bradygaster Nov 10, 2026
07d7131
fix(claude): address plugin and dashboard Copilot review feedback
bradygaster Nov 10, 2026
92055ad
fix(dashboard): start over when a transcript is rewritten shorter (#2…
bradygaster Nov 10, 2026
55a9837
fix(dashboard): one dashboard per directory, even when started twice …
bradygaster Nov 10, 2026
17ed2b5
fix(claude): dashboard runs only its three commands; Ralph's scope is…
bradygaster Nov 10, 2026
503f838
docs(skills): gh-auth-isolation pushes without a token in the URL
bradygaster Nov 10, 2026
4beb5e5
fix(claude): the launcher's npx fallback is opt-in (SQUAD_ALLOW_NPX=1…
bradygaster Nov 10, 2026
e98cb8d
fix(claude): /squad:cast and /squad:ceremony pass their arguments as …
bradygaster Nov 10, 2026
f51ae72
fix(claude): /squad:ralph takes only fixed argument words (#2443)
bradygaster Nov 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/claude-code-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@bradygaster/squad-sdk": minor
"@bradygaster/squad-cli": minor
---

Squad ships as a Claude Code plugin (`claude plugin marketplace add github/squad`, then `claude plugin install squad@squad`). The plugin carries the coordinator, the `squad_state` MCP server (no `.mcp.json` approval or `--mcp-config`), skills, advisory hooks and the `/squad:ralph`, `/squad:cast`, `/squad:ceremony`, `/squad:status` and `/squad:dashboard` commands. `squad init --client claude --claude-plugin` (or `upgrade`) records `claudePlugin` in `.squad/config.json` and then writes only the member subagents, the `CLAUDE.md` block and the `agent` and `disabledMcpjsonServers` settings.

Preserve user settings and former project MCP ownership across plugin-mode transitions, support plugin-mode watch sessions and direct init callers, skip disabled plugin hooks before CLI startup, and safely forward launcher and mesh-sync arguments. Dashboard tails preserve split UTF-8 characters, reconnects reset replayed state, and unused servers shut down after five minutes. The launcher's `npx` fallback is opt-in (`SQUAD_ALLOW_NPX=1`); without it, a missing CLI fails with install instructions. Starting a dashboard is serialized per directory, and a transcript rewritten shorter starts the page over.
5 changes: 5 additions & 0 deletions .changeset/claude-dashboard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bradygaster/squad-cli": minor
---

New `squad dashboard` (and `/squad:dashboard` in the Claude Code plugin): a live local page of the coordinator and each member at work, read from the Claude Code session transcripts for the directory (or `--stream` stream-json logs). It listens on 127.0.0.1 only, rejects other Host headers, sends a CSP with no inline script, and runs one instance per directory (`stop`, `status`, `--detach`, `--open`, `--session`, `--port`). No dependencies beyond Node.js.
20 changes: 20 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "squad",
"owner": {
"name": "Brady Gaster",
"url": "https://github.com/bradygaster"
},
"metadata": {
"description": "The Squad plugin for Claude Code."
},
"plugins": [
{
"name": "squad",
"source": "./plugins/squad",
"description": "Squad for Claude Code: a coordinator that routes work to a team of specialist subagents, with shared team state in the squad_state MCP server.",
"version": "2.0.0-preview.4",
"homepage": "https://github.com/github/squad",
"license": "MIT"
}
]
}
11 changes: 8 additions & 3 deletions .copilot/skills/distributed-mesh/sync-mesh.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,18 @@ for squad in $(jq -r '.squads | to_entries[] | select(.value.zone == "remote-opa
auth=$(jq -r ".squads.\"$squad\".auth // \"\"" "$MESH_JSON")

mkdir -p "$target"
auth_flag=""
curl_args=(--silent --fail)
header=""
if [ "$auth" = "bearer" ]; then
token_var="$(echo "${squad}" | tr '[:lower:]-' '[:upper:]_')_TOKEN"
[ -n "${!token_var:-}" ] && auth_flag="--header \"Authorization: Bearer ${!token_var}\""
token=$(printenv "$token_var" || true)
if [ -n "$token" ]; then
curl_args+=(--header @-)
header="Authorization: Bearer $token"
fi
fi

eval curl --silent --fail $auth_flag "$source" -o "$target/SUMMARY.md" 2>/dev/null \
printf '%s\n' "$header" | curl "${curl_args[@]}" --url "$source" -o "$target/SUMMARY.md" 2>/dev/null \
|| echo "# ${squad} — unavailable ($(date))" > "$target/SUMMARY.md"
done

Expand Down
7 changes: 6 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,9 @@ Dockerfile.* text eol=lf

# Charter conformance binds exact document bytes across platform checkouts.
docs/specification/charter-v0.1.md text eol=lf
scripts/release/manifest.schema.json text eol=lf
scripts/release/manifest.schema.json text eol=lf
# Squad: the Claude Code plugin is generated by scripts/build-claude-plugin.mjs and
# checked byte-for-byte by test/claude-plugin.test.ts; bin/squad has a shebang and
# no extension. Pin LF so Windows checkouts neither break it nor drift (#2443).
plugins/** text eol=lf
.claude-plugin/** text eol=lf
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ docs/tests/screenshots/

# .NET build output
bin/
# ...but the Claude plugin's launchers ship in the repo (marketplace installs clone it)
!plugins/squad/bin/
obj/
artifacts/

Expand Down
11 changes: 8 additions & 3 deletions .squad-templates/skills/distributed-mesh/sync-mesh.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,18 @@ for squad in $(jq -r '.squads | to_entries[] | select(.value.zone == "remote-opa
auth=$(jq -r ".squads.\"$squad\".auth // \"\"" "$MESH_JSON")

mkdir -p "$target"
auth_flag=""
curl_args=(--silent --fail)
header=""
if [ "$auth" = "bearer" ]; then
token_var="$(echo "${squad}" | tr '[:lower:]-' '[:upper:]_')_TOKEN"
[ -n "${!token_var:-}" ] && auth_flag="--header \"Authorization: Bearer ${!token_var}\""
token=$(printenv "$token_var" || true)
if [ -n "$token" ]; then
curl_args+=(--header @-)
header="Authorization: Bearer $token"
fi
fi

eval curl --silent --fail $auth_flag "$source" -o "$target/SUMMARY.md" 2>/dev/null \
printf '%s\n' "$header" | curl "${curl_args[@]}" --url "$source" -o "$target/SUMMARY.md" 2>/dev/null \
|| echo "# ${squad} — unavailable ($(date))" > "$target/SUMMARY.md"
done

Expand Down
28 changes: 13 additions & 15 deletions .squad-templates/skills/gh-auth-isolation/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ gh auth token --user corpalias_enterprise
The most common scenario: your shell defaults to the EMU account, but you need to push to a personal GitHub repo.

```bash
# 1. Extract the personal token
$token = gh auth token --user personaluser

# 2. Push using token-authenticated HTTPS
git push https://personaluser:$token@github.com/personaluser/repo.git branch-name
# Push as the personal account for this one command: gh's credential helper hands git the
# token from GH_TOKEN, so it never appears in a URL, a remote or the command line
GH_TOKEN="$(gh auth token --user personaluser)" \
git -c credential.helper= -c 'credential.helper=!gh auth git-credential' \
push https://github.com/personaluser/repo.git branch-name
```

**Why this works:** `gh auth token --user` reads from `gh`'s credential store without switching the active account. The token is used inline for a single operation and never persisted.
**Why this works:** `gh auth token --user` reads from `gh`'s credential store without switching the active account. The token lives only in that one command's environment: `credential.helper=` clears the stored (EMU) helper for this command, and `gh auth git-credential` answers git's credential request with `GH_TOKEN`. Never put a token in a git URL: it shows up in shell history, process listings, tool logs and `.git/config`.

### Create PRs on Personal Forks

Expand Down Expand Up @@ -128,12 +128,9 @@ alias ghe='gh'
# Agent needs to push to personaluser.github.io (personal repo)
# Default gh auth is corpalias_enterprise (EMU)

$token = gh auth token --user personaluser
git remote set-url origin https://personaluser:$token@github.com/personaluser/personaluser.github.io.git
git push origin main

# Clean up — don't leave token in remote URL
git remote set-url origin https://github.com/personaluser/personaluser.github.io.git
$env:GH_TOKEN = gh auth token --user personaluser
git -c credential.helper= -c 'credential.helper=!gh auth git-credential' push origin main
Remove-Item Env:GH_TOKEN # the token never touches the remote URL
```

### ✓ Correct: Agent creates a PR from personal fork to upstream
Expand Down Expand Up @@ -167,9 +164,10 @@ git push https://personaluser:ghp_xxxxxxxxxxxx@github.com/personaluser/repo.git
```bash
# Always verify which account has access before operations
gh auth status
# If wrong account, use token extraction:
$token = gh auth token --user personaluser
git push https://personaluser:$token@github.com/personaluser/repo.git main
# If wrong account, hand git the personal token for this one push:
GH_TOKEN="$(gh auth token --user personaluser)" \
git -c credential.helper= -c 'credential.helper=!gh auth git-credential' \
push https://github.com/personaluser/repo.git main
```

## Anti-Patterns
Expand Down
56 changes: 56 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,62 @@ All notable changes to this project will be documented in this file.
- `squad upgrade --self --dry-run` reports the planned upgrade without installing it. `squad upgrade --state-backend orphan --dry-run` also avoids backend migration, source deletion, config changes and hook installation (#2303, #2295). Available in `v2.0.0-preview.2` and later previews, not stable `v1.1.0`.
- `squad memory` and `memory.*` share the backend-aware governed store (#2317, #2316), so CLI writes and MCP searches use the same storage. Available in `v2.0.0-preview.3` and later previews, not stable `v1.1.0`. Transactional existing-memory backend migration (#2425, #2439) is available in `v2.0.0-preview.4`.

### Claude Code as a first-class host (#2438)

Planned as the headline of `v2.0.0-preview.5`.

Claude Code is the first host after GitHub Copilot where Squad uses the host's own features (subagents, hooks, skills, plugins and the Claude Agent SDK) instead of the shared minimum. Every addition goes through the host projection contract in `squad-client-harness-adapters/v0.2` (§4–§5, §13) and the charter extension rules, and the same `.squad/` team still drives Copilot and the other hosts unchanged. It also ships the SDK's first real `HarnessAdapter`, which makes Claude the non-Copilot host that the two v0.2 profiles (harness-adapters §15.1, backend-decoupling §14.4) need before they can be promoted. Promoting them is still pending.

#### Added

- **Squad plugin for Claude Code** (#2443, #2463). Install it with `claude plugin marketplace add github/squad`, then `claude plugin install squad@squad --scope project`. The plugin is generated from the SDK (`plugins/squad/`, by `scripts/build-claude-plugin.mjs`, with a `--check` gate in tests) and published through `.claude-plugin/marketplace.json`. It carries:
- the coordinator, as the `squad:squad` agent
- the `squad_state` MCP server. It needs no `.mcp.json` approval and no `--mcp-config`, including in headless `claude -p` runs; a recorded measurement in the host feature matrix backs this.
- the coordinator's on-demand skills and Squad's template skills, as `/squad:<skill>`
- the slash commands `/squad:ralph`, `/squad:cast`, `/squad:ceremony`, `/squad:status` and `/squad:dashboard`
- the advisory governance hooks
- a launcher that the slash commands, hooks and MCP server call by path, also on the Bash tool's PATH as `squad`. It runs, in order, `SQUAD_CLI`, the project's `@bradygaster/squad-cli` or a `squad` on PATH, and skips a project or PATH install older than the plugin. With none, it fails with install instructions. It runs the plugin's pinned version through `npx` only when `SQUAD_ALLOW_NPX=1` is set, because that downloads and runs code.
- **Plugin mode for the Claude projection** (#2443, #2463). `squad init --client claude --claude-plugin` (or `squad upgrade --claude-plugin`) records `"claudePlugin": true` in `.squad/config.json`. Squad then writes only the per-repository files: the member subagents, the `CLAUDE.md` block, and two keys in `.claude/settings.json`:
- `agent`, so a plain `claude` starts the coordinator
- `disabledMcpjsonServers`, so the project's `.mcp.json` copy of `squad_state` neither prompts nor duplicates the plugin's tools

`--no-claude-plugin` switches back to the full projection. The Claude projection is now version 3 (`CLAUDE_PROJECTION_VERSION`).
- **`squad dashboard` and `/squad:dashboard`** (#2459, #2460, #2463). A live local page shows the coordinator and every member at work: who was dispatched and why, which members run in the background and in parallel, each member's tool calls, summaries and results, hook events, and each prompt of a `--continue` session.
- **What it reads.** The Claude Code session transcripts for the current directory, including each member's own subagent transcript. It reads them incrementally, follows the newest session and moves to a new one when it starts. `--session <id>` pins one, and `--stream <file>` reads `claude -p --output-format stream-json` logs instead. Unknown transcript line types are skipped and their content is never shown.
- **Local only.** It listens on `127.0.0.1` only (from port 4280; `--port` picks one) and rejects any other `Host` header, which protects against DNS rebinding. It sends a Content Security Policy that allows no inline script and no other origin, and transcript text is always rendered as text, never markup.
- **One per directory.** `stop`, `status`, `--detach`, `--open` and `--json` manage it, and running it again shows the instance already running. Its state lives in `~/.squad/dashboards/` (or under `SQUAD_HOME`), so `/squad:dashboard` inside Claude Code and `squad dashboard` in a terminal find the same instance.
- **Safe from the plugin.** `/squad:dashboard` may run only `squad dashboard`, and never passes your words to the shell.
- **No new dependencies.** It needs only Node.js. It replaces the prototype that was used during the end-to-end test.
- **Member subagents** (#2450). Each team member, built-ins included, is projected from its charter as its own subagent in `.claude/agents/<member>.md`.
- Model, reasoning effort and the new `X-squad-host-claude` charter extension (`Tools`, `Isolation`) map onto the subagent's frontmatter.
- The coordinator routes to named members and selects a model per spawn through Claude Code's `Agent` tool, using `run_in_background` and `isolation: "worktree"`.
- `squad cast` refreshes member files, and the files of removed members are deleted.
- A user-authored file at a member path is never overwritten; it is reported as `skipped`.
- **Native skills and a smaller coordinator** (#2450). Squad's template skills are projected into `.claude/skills/`, except where a team skill of the same name exists. Init Mode, Ralph mode, ceremonies, GitHub Issues mode and PRD mode now load on demand from generated `squad-coordinator-*` skills instead of sitting in the always-loaded prompt.
- **Advisory governance hooks** (#2450). They're opt-in, with `"claudeHooks": "advisory"`. They:
- give the coordinator session context
- warn a locked-out member who edits work under review
- add a handoff summary after each member finishes
- remind the coordinator to run Scribe

They never block a tool call. New commands: `squad lockout` records reviewer lockouts in `.squad/governance/lockouts.json`, and `squad hook claude <Event>` runs the hooks.
- **Claude Code runner for `squad watch --execute`** (#2450). `--agent-preset claude` (or `watch.agentPreset: "claude"`) runs each round as `claude -p … --agent squad --output-format stream-json`.
- It uses a private, `squad_state`-only MCP config, never the repository's `.mcp.json`.
- It checks for the coordinator and the `claude` CLI before starting, and treats an error result as a failed round.
- `watch.claudeFlags` is limited to model, permission-mode, effort and turn-limit flags.
- **First real execution harnesses** (#2441, #2451), experimental, in `@bradygaster/squad-sdk/backend`:
- `ClaudeAgentSdkHarness` runs conversation turns on the Claude Agent SDK. Broker approvals go through `canUseTool`: each is bound to a hash, they arrive one at a time, and a deny ends the turn. `@anthropic-ai/claude-agent-sdk` is an optional peer dependency.
- `CopilotSdkHarness` does the same on `@github/copilot-sdk`.
- Both share an approval queue and a turn lifecycle, and their state survives restarts. Approval records hold a redacted summary, never the tool input.
- `squad state-mcp --experimental-backend` registers the Claude harness only when its SDK is installed. `SQUAD_BACKEND_HARNESSES` selects the harnesses or turns them off.
- New docs: [Squad for Claude Code (plugin)](docs/src/content/docs/features/claude-code-plugin.md). The README, CLI reference, multi-client scenario and adapter spec link to it.

#### Changed

- The Claude coordinator names Claude Code's `Agent` subagent tool (formerly `Task`). The Claude Code spec, docs and host feature matrix now match the code, and host-projection regression guards keep them that way (#2440, #2445).
- Every generated Claude Markdown file states its projection version. Files from earlier projections are still recognised as Squad's and upgraded in place, and rolling back the `CLAUDE.md`, `AGENTS.md` and `GEMINI.md` blocks restores the original bytes exactly (#2450).
- Copilot output, `.github/agents/squad.agent.md` and the projections for other hosts are unchanged.

## [2.0.0-preview.4] - 2026-11-09

Fourth Squad 2.0 preview. This release completes the repository migration to `github/squad` across published npm and NuGet package metadata, runtime links, templates, documentation, and `gh-aw` workflow package identity, adds transactional governed-memory backend migration with source-branch casting ownership, and includes memory lock coordination and Copilot SDK runtime compatibility fixes. npm continues to use `insider` as the canonical dist-tag with `preview` as a compatibility alias; `latest` remains on 1.1.0.
Expand Down
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,17 @@ squad init --client claude,opencode # or: --client all
squad upgrade --client codex # add a host later; refreshes every configured host
```

Each host gets a native coordinator file plus MCP wiring; your own settings in `.mcp.json`, `opencode.json` and the like are never clobbered. See [Using Squad across clients](docs/src/content/docs/scenarios/using-squad-across-clients.md), [Squad 2.0 architecture](docs/src/content/docs/concepts/squad-2-0-architecture.md), and the [multi-client quickstart](docs/tutorials/multi-client-quickstart.md).
Each host gets a native coordinator file plus MCP wiring; your own settings in `.mcp.json`, `opencode.json` and the like are never clobbered.

In Claude Code, Squad also installs as a plugin that carries the coordinator, `squad_state`, skills, hooks and slash commands, including `/squad:dashboard`, a live local page of the team at work (also `squad dashboard`):

```bash
claude plugin marketplace add github/squad
claude plugin install squad@squad --scope project
squad init --client claude --claude-plugin
```

See [Squad for Claude Code (plugin)](docs/src/content/docs/features/claude-code-plugin.md). See [Using Squad across clients](docs/src/content/docs/scenarios/using-squad-across-clients.md), [Squad 2.0 architecture](docs/src/content/docs/concepts/squad-2-0-architecture.md), and the [multi-client quickstart](docs/tutorials/multi-client-quickstart.md).

---

Expand Down Expand Up @@ -193,6 +203,7 @@ Say **"squad commands"** in chat to see a categorized menu of common operations
| `squad upstream add\|remove\|list\|sync` | Manage upstream Squad sources |
| `squad nap` | Context hygiene — compress, prune, archive; use `--deep` for aggressive compression, `--dry-run` to preview changes |
| `squad aspire` | Open Aspire dashboard for observability |
| `squad dashboard` | Live local page of the team's Claude Code sessions on 127.0.0.1; `stop`, `status`, `--detach`, `--open`, `--session <id>`, `--stream <file>` |
| `squad scrub-emails [directory]` | Remove email addresses from Squad state files (default: `.squad/`) |

---
Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
],
"words": [
"aadnesd",
"Mcpjson",
"ADO",
"AKIA",
"affordances",
Expand Down
Loading
Loading