fix(orchestrators): register Chorus at Claude Code user scope#35
Closed
chrisayl wants to merge 1 commit into
Closed
fix(orchestrators): register Chorus at Claude Code user scope#35chrisayl wants to merge 1 commit into
chrisayl wants to merge 1 commit into
Conversation
`chorus init` was writing the Chorus MCP entry to `projects.<homedir>.mcpServers.chorus` in `~/.claude.json`, so it only surfaced when Claude Code was launched from the user's home directory — not from the project they actually ran `chorus init` in. Shell out to `claude mcp add ... --scope user` instead, matching the codex/gemini orchestrators. Entry lands at top-level `mcpServers` and is available from every project. Removes any stale entry first. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
Merged
4 tasks
chorus-codes
added a commit
that referenced
this pull request
May 14, 2026
…persedes #35, #36, #37) (#39) * fix(orchestrators): register Chorus at Claude Code user scope `chorus init` was writing the Chorus MCP entry to `projects.<homedir>.mcpServers.chorus` in `~/.claude.json`, so it only surfaced when Claude Code was launched from the user's home directory — not from the project they actually ran `chorus init` in. Shell out to `claude mcp add ... --scope user` instead, matching the codex/gemini orchestrators. Entry lands at top-level `mcpServers` and is available from every project. Removes any stale entry first. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(mcp): forward repoPath from create_chat to the daemon `create_chat` drops `repoPath` on the floor — the schema doesn't accept it and the daemonFetch body doesn't forward it. The daemon's `/chats` route already supports `repoPath`, but with nothing forwarded `prompt-builder.ts:45` falls back to the daemon's own `process.cwd()`, which is locked to packageRoot by `start.ts:324`. Two concrete effects: 1. Relative paths in `files: [...]` resolve against the chorus npm install dir, miss, and get silently skipped — so the inline-packed file contents the reviewers + doer see in their prompt are wrong (usually empty). 2. The DOER (only) gets cwd = scratch dir instead of the user's repo (`doer-driver.ts:170`: `repoPath ?? doerDir`), so it can't read project files via its own tools and can't make the real edits the ship phase would commit. Reviewers are NOT affected by this fix — they intentionally run in a per-round scratch dir regardless of repoPath (`reviewer.ts:84`, spelled out in `doer-driver.ts:165-168`). Fix: add `repoPath: z.string().optional()` to `CreateChatSchema`, default it to `process.cwd()` in `createChat`, forward in the POST body. MCP servers spawned by Claude Code / Codex / Gemini inherit the host's cwd (= the project), so the default lands at the right path automatically. Explicit callers can still override. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(windows): patch remaining spawn EINVAL call sites + audit fixes - Add shell: win32 to daemon/routes/system.ts (opencode models probe) - Add shell: win32 to cli/commands/update.ts (npm self-update spawn) - Relax SAFE_WIN_PATH regex: whitelist -> blacklist for Unicode paths - Add shell: isWindows to discoverNpmPrefixes (npm.cmd on Windows) - Remove shell: win32 from ship.ts (git/gh are native .exe, no EINVAL risk) Findings from multi-LLM code review (Gemini, DeepSeek, OpenCode). * fix(windows): normalize CRLF line endings in persona frontmatter parser Persona .md files checked out on Windows have CRLF line endings, but the frontmatter parser checks for '---\n' which fails with '---\r\n', throwing 'missing YAML frontmatter'. Adding .replace() normalizes to LF before parsing. Also adds pr-description.md documenting the full spawn EINVAL fix with tri-review V3 results. * fix: resolve spawn EINVAL error for Windows CLIs * fixup: drop stray pr-description.md + tighten SAFE_WIN_PATH (add ^ to blacklist) Adds tests for cmd.exe escape-char rejection and @-scoped npm package path acceptance. Without ^ in the blacklist, a path containing `^"& cmd` could break out of the shell-quoted wrap in buildVersionSpawn. * fixup(review): apply chorus self-review fixes Three convergent blocking findings from 8-reviewer panel: 1. claude.ts execFileAsync missing shell:win32 (caught by gemini-cli — the irony: this is the same EINVAL bug #37 fixes everywhere else). 2. SAFE_WIN_PATH missing ! (delayed expansion under setlocal enabledelayedexpansion). 6/8 reviewers flagged. 3. process.cwd() throwing ENOENT crashes createChat. 5/8 reviewers flagged — wrap in safeCwd() with homedir fallback. Plus: friendlier error message in claude.ts pointing at minimum Claude Code version when 'mcp add --scope user' is unsupported. --------- Co-authored-by: Chris Aylott <chris.aylott@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: João Pedro Magalhães <pedropeixotomagalhaes@gmail.com> Co-authored-by: chorus-codes <280607145+chorus-codes@users.noreply.github.com>
Owner
|
Thanks for this — bundled into #39 with full credit ( The bundle picked up four convergent findings from a chorus self-review on the combined diff:
Closing this PR — merged into main via #39. |
chorus-codes
added a commit
that referenced
this pull request
May 14, 2026
Bundles #39 (supersedes #35 chrisayl, #36 chrisayl, #37 magalz) — claude orchestrator user-scope MCP registration, repoPath plumbing through MCP create_chat, and Windows spawn EINVAL fix across 8 call sites. Plus chorus-self-review fixups: ! and ^ added to SAFE_WIN_PATH blacklist, shell:win32 on claude.ts execFileAsync, safeCwd() ENOENT fallback. Co-authored-by: chorus-codes <280607145+chorus-codes@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
chorus initregisters Chorus to Claude Code underprojects.<homedir>.mcpServers.chorusin~/.claude.json, so the MCP server only surfaces when Claude Code is launched from the user's home directory — not from the project they actually ranchorus initin. From any real project it silently does nothing.Root cause:
registerClaudeMcpServerdefaults the project key toos.homedir(), andrunOrchestratorAutoConnect(ininit.ts) never passes aprojectDir. The cwd is never read, so the entry always lands atprojects.<HOME>.Fix
Shell out to
claude mcp add chorus --scope user --env CHORUS_DAEMON_URL=… -- node <binPath> mcp, matching the codex and gemini orchestrators (which already register at user / global scope via their respective CLIs). The entry lands at top-levelmcpServersin~/.claude.jsonand is available from every project — which is the user expectation reflected in the README ("wires up MCP with every CLI / IDE it detects").Behaviour:
claude mcp add … --scope usercall.binPath: no-op ({ added: false }).binPath:claude mcp remove … --scope userthen re-add.projects.<dir>.mcpServers.chorusentries from older releases are ignored — left in place; the new user-scope entry takes precedence in Claude Code.Test plan
pnpm test— 756/756 pass (+6 new intests/claude-orchestrator.test.tscovering fresh install / idempotency / stale-entry remove-then-add / legacy-project-scope ignored /claude mcp addfailure path).pnpm typecheck— clean.pnpm lint— 45 warnings, same asmain(no new ones).chorus initfrom a non-home directory and confirmclaude mcp listshowschorus(run from any project dir).🤖 Generated with Claude Code