Repository navigation
Description
Part of #2438 (a follow-up from the Claude Code end-to-end test).
Problem
When the Squad CLI is installed (npm global, a local node_modules, Homebrew or a dev build), squad init and squad upgrade write the squad_state MCP server as an absolute node <path>/cli-entry.js state-mcp:
resolveSquadStateMcpSpecinpackages/squad-cli/src/cli/core/mcp-spec.ts: resolution order is standalone launcher, then local entry (process.execPath+ the absolutecli-entry.js), then the pinnednpx -y @bradygaster/squad-cli@<version>.- The Claude hooks reuse the same launcher (
claude-hooks.ts: "the same launcher as thesquad_stateMCP server"), so every hook in.claude/settings.jsongets the same absolute paths.
Squad knows this is machine-specific: it marks the entry x-squad.machineSpecific: true and records the pinned npx form as fallback. But nothing uses the fallback, and the files are committed. .mcp.json and .claude/settings.json are project files that Claude Code reads from the repo.
What happens
The end-to-end test repo was published as https://github.com/bradygaster/brickbreak. Before publishing, its .mcp.json and all five hooks in .claude/settings.json pointed at /Users/<user>/.local/share/fnm/node-versions/v24.16.0/installation/bin/node and a dev checkout's dist/cli-entry.js. As committed, for anyone else who clones it, or for the same user on another machine or after a Node version change:
- The
squad_stateMCP server fails to start, so the coordinator's state handshake fails. - Every Squad hook fails (non-blocking, but governance and context injection silently stop).
- The commit also leaks the local username and directory layout.
I fixed that repo by hand, rewriting both files to the pinned npx form (commit 7fe5d51 there).
What needs to be done
Decide the shape, then implement it. Options to weigh:
- Commit the portable form, run the fast one locally. Write the pinned
npx -y @bradygaster/squad-cli@<version>form (or a baresquadon PATH) into the committed files, and keep machine-specific launchers out of them. Weighnpxstart-up latency against the hook timeouts (currently 15 s), especially on the first, uncached run. - Or keep the machine-specific form out of git, for example in
.claude/settings.local.jsonfor hooks (Claude Code's per-user, git-ignored settings), and document how a teammate regenerates it (squad upgrade --client claude). - Either way, the same applies to
.copilot/mcp-config.jsonand the other hosts' MCP files that shareresolveSquadStateMcpSpec. -
squad doctor(or the SessionStart hook) should detect a committed launcher that doesn't exist on this machine and say how to fix it, instead of failing silently. - Tests: init and upgrade from a local install produce committed files with no absolute paths; rollback stays byte-preserving.
Related: the published packages stop at 2.0.0-preview.3. Until a version with hook claude is on npm, the pinned form can't actually run the Claude hooks, so the release timing matters for whichever option is chosen.
Activity
github-actions commentedon Nov 10, 2026
📋 Assigned to cli-dev (CLI Engineer)
Issue: #2462 — squad init commits machine-specific node paths into .mcp.json and .claude/settings.json
cli-dev will pick this up in the next Copilot session.