Repository navigation
fix(cli): client detection for OpenCode, Hermes, Claude (#1167, #1180) - #2468
Conversation
Three detection defects kept `codebase-memory-mcp install` from configuring agents people run, and made it configure one they never installed. OpenCode without a config file or a CLI on PATH (#1167, #1180). OpenCode was detected only from its global config file or directory, OPENCODE_CONFIG_DIR, or an `opencode` found on PATH. It now also counts as installed when its data directory exists: ~/.local/share/opencode on every OS, %USERPROFILE%\.local\share\opencode on Windows (opencode.ai/docs/troubleshooting, "Storage"; the same page names it as the global config location of older installs). The OpenCode CLI and the Desktop app both create it -- the Desktop's bundled opencode-cli server uses the same XDG paths (anomalyco/opencode packages/core/src/global.ts creates the config and data dirs at startup; packages/desktop/src/main/sidecar.ts only redirects XDG_STATE_HOME) -- so detection no longer depends on PATH. The install target ~/.config/opencode/opencode.json(c) -- %USERPROFILE%\.config\opencode on Windows per the same docs page -- is unchanged and right for CLI and Desktop alike. A PATH longer than 4 KB, which hides every CLI from find_in_path(), is handled separately by PR #2381. Hermes home on Windows (#1180). Native Windows Hermes -- the install.ps1 CLI, the MSIX package and the Desktop app -- defaults HERMES_HOME to %LOCALAPPDATA%\hermes and falls back to a legacy ~/.hermes only while that directory is absent (NousResearch/hermes-agent website/docs/user-guide/windows-native.md, "Data layout"; apps/desktop/electron/data-paths.mjs, resolveDesktopHermesHome). cbm probed and wrote ~/.hermes only, so a Desktop install was never detected and a Hermes found on PATH got its config.yaml and skill in a home it never reads. On Windows the home now resolves to <home>/AppData/Local/hermes unless only ~/.hermes exists, using the home-derived AppData convention of the existing Zed, goose, Kilo and VS Code probes; detection, install and uninstall all follow it. HERMES_HOME still wins, and macOS/Linux keep ~/.hermes. Claude Code from a bare ~/.claude (#1180). Any ~/.claude directory counted as a Claude Code install, so a user who only had the folder got hooks, skills and MCP entries for a client they never installed. Detection now needs what Claude Code itself leaves behind: settings.json in the config dir, .claude.json in the home (in CLAUDE_CONFIG_DIR when set), or the claude CLI. Proof on macOS against synthetic HOME/cache/runtime dirs with a minimal PATH (`install --dry-run --skip-binary`, then a config-only install): bare ~/.claude main: Claude-Code fix: none ~/.local/share/opencode only main: none fix: OpenCode In the OpenCode case the fixed install writes the codebase-memory-mcp entry to ~/.config/opencode/opencode.json; main writes nothing. Controls (a launched Desktop layout, a real Claude user) are detected by both. The Windows Hermes home is covered by a platform-parameterised resolver test that runs on every host plus a _WIN32-bound end-to-end detection and plan test. Tests (cli suite, 335 passed): seven new tests; five fail on main three times out of three (the _WIN32-bound Hermes test and the look-alike control are green on macOS by design). Reverting the Claude+Hermes half and the OpenCode data-dir probe separately turns exactly their own tests red. Nine existing Claude fixtures that used a bare ~/.claude as the install marker now write .claude.json; two Hermes tests and smoke-test 8x expect %LOCALAPPDATA%\hermes on Windows. Refs #1167 Fixes #1180 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The client-detection fix moved the Windows Hermes home to %LOCALAPPDATA%\hermes and stopped counting a bare ~/.claude directory as a Claude Code install. The smoke script followed only part of the way. Hermes: 8x and 8x-i read the new HERMES_HOME_DIR, but 8x-ii still looked for the pre_llm_call hook in ~/.hermes/config.yaml, and the uninstall absence checks 9m and 9n still named ~/.hermes. On Linux and macOS HERMES_HOME_DIR is ~/.hermes, so the stale paths pointed at the right directory and nothing showed. Only on Windows do the two differ: 8x-ii failed on a hook that install had written to the new home, and 9m and 9n passed without looking at any file install had produced. All three now use HERMES_HOME_DIR. The assertions are unchanged. Claude Code: the fixtures of 9b-2, 9b-3, 9b-8 and both Phase 13 legs created only an empty ~/.claude, which is no longer a Claude Code home. Wherever no claude executable is installed, 9b-2 then finds no .claude.json entry and 13e finds no agent config, and 9b-3, 9b-8 and the install.ps1 leg stop exercising the Claude paths without saying so. The Linux test container reproduces both failures. The Windows job never got that far, because 8x-ii stops it in Phase 8. The fixtures now seed the .claude.json user config through one helper, the same seed the unit tests use. 9b-1b pins the new rule end to end: where the empty-home control shows no Claude Code, a home with only a bare ~/.claude gets no Claude config. A venue that has a claude executable skips it, with the reason at the case. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
|
Checkpoint and handover (2026-10-03 UTC) Published head: Smoke-test portability update is published. Historical Linux evidence was 336 passing, 335 passing plus the owned regression failure on revert, then 336 passing after restoration. Windows validation remains unverified locally. Hosted snapshot at 2026-10-03 21:54:00 UTC: 1 queued, 3 skipped, 34 success. Confirm the required checks on this exact head before treating it as ready. No additional local build, test, lint, sanitizer, benchmark or CI runs were performed at this checkpoint, as requested. Earlier executed evidence remains historical; prepared tests and the newer source-reviewed changes must still be validated by the hosted gate. The campaign is paused at the maintainer’s request. Local monitoring has stopped; hosted jobs remain running. No merge was performed. Thanks for reviewing this change. |
Three detection defects kept
codebase-memory-mcp installfromconfiguring agents people run, and made it configure one they never
installed.
OpenCode without a config file or a CLI on PATH (#1167, #1180).
OpenCode was detected only from its global config file or directory,
OPENCODE_CONFIG_DIR, or an
opencodefound on PATH. It now also countsas installed when its data directory exists: ~/.local/share/opencode on
every OS, %USERPROFILE%.local\share\opencode on Windows
(opencode.ai/docs/troubleshooting, "Storage"; the same page names it as
the global config location of older installs). The OpenCode CLI and the
Desktop app both create it -- the Desktop's bundled opencode-cli server
uses the same XDG paths (anomalyco/opencode packages/core/src/global.ts
creates the config and data dirs at startup;
packages/desktop/src/main/sidecar.ts only redirects XDG_STATE_HOME) --
so detection no longer depends on PATH. The install target
~/.config/opencode/opencode.json(c) -- %USERPROFILE%.config\opencode
on Windows per the same docs page -- is unchanged and right for CLI and
Desktop alike. A PATH longer than 4 KB, which hides every CLI from
find_in_path(), is handled separately by PR #2381.
Hermes home on Windows (#1180). Native Windows Hermes -- the install.ps1
CLI, the MSIX package and the Desktop app -- defaults HERMES_HOME to
%LOCALAPPDATA%\hermes and falls back to a legacy ~/.hermes only while
that directory is absent (NousResearch/hermes-agent
website/docs/user-guide/windows-native.md, "Data layout";
apps/desktop/electron/data-paths.mjs, resolveDesktopHermesHome). cbm
probed and wrote ~/.hermes only, so a Desktop install was never detected
and a Hermes found on PATH got its config.yaml and skill in a home it
never reads. On Windows the home now resolves to
/AppData/Local/hermes unless only ~/.hermes exists, using the
home-derived AppData convention of the existing Zed, goose, Kilo and VS
Code probes; detection, install and uninstall all follow it. HERMES_HOME
still wins, and macOS/Linux keep ~/.hermes.
Claude Code from a bare ~/.claude (#1180). Any ~/.claude directory
counted as a Claude Code install, so a user who only had the folder got
hooks, skills and MCP entries for a client they never installed.
Detection now needs what Claude Code itself leaves behind: settings.json
in the config dir, .claude.json in the home (in CLAUDE_CONFIG_DIR when
set), or the claude CLI.
Proof on macOS against synthetic HOME/cache/runtime dirs with a minimal
PATH (
install --dry-run --skip-binary, then a config-only install):bare ~/.claude main: Claude-Code fix: none
~/.local/share/opencode only main: none fix: OpenCode
In the OpenCode case the fixed install writes the codebase-memory-mcp
entry to ~/.config/opencode/opencode.json; main writes nothing. Controls
(a launched Desktop layout, a real Claude user) are detected by both.
The Windows Hermes home is covered by a platform-parameterised resolver
test that runs on every host plus a _WIN32-bound end-to-end detection
and plan test.
Tests (cli suite, 335 passed): seven new tests; five fail on main three
times out of three (the _WIN32-bound Hermes test and the look-alike
control are green on macOS by design). Reverting the Claude+Hermes half
and the OpenCode data-dir probe separately turns exactly their own tests
red. Nine existing Claude fixtures that used a bare ~/.claude as the
install marker now write .claude.json; two Hermes tests and smoke-test
8x expect %LOCALAPPDATA%\hermes on Windows.
Refs #1167
Fixes #1180