Skip to content

install/update ignore $CLAUDE_CONFIG_DIR; writes always go to ~/.claude #320

@halindrome

Description

@halindrome

Summary

codebase-memory-mcp install and codebase-memory-mcp update ignore the CLAUDE_CONFIG_DIR environment variable and unconditionally write Claude Code skills, MCP entries, hook scripts, and settings.json under $HOME/.claude/.

Users who keep their Claude Code config under a non-default location (e.g. CLAUDE_CONFIG_DIR=$HOME/.config/claude-code, the location Claude Code itself uses on macOS when configured that way) end up with:

  1. A new ~/.claude/ tree silently created by the installer.
  2. Their real Claude Code config dir untouched — so the skills/MCP entry/hooks the installer claims it wrote are not visible to Claude Code at runtime.
  3. cbm_detect_agents() checking $HOME/.claude (not CLAUDE_CONFIG_DIR) and reporting Claude Code as "detected" or "not detected" based on the wrong path.

This was first observed during a 0.6.0 → 0.6.1 upgrade.

Reproduce

export CLAUDE_CONFIG_DIR="$HOME/.config/claude-code"
mkdir -p "$CLAUDE_CONFIG_DIR"

codebase-memory-mcp install -y

# Expected: writes under $CLAUDE_CONFIG_DIR
# Actual:   writes under $HOME/.claude
ls -la ~/.claude/skills          # populated (wrong)
ls -la "$CLAUDE_CONFIG_DIR/skills"   # empty / missing (should be populated)

Affected paths

All hardcoded in src/cli/cli.c:

Line Path written Function
cli.c:981 ${HOME}/.claude cbm_detect_agents (detection)
cli.c:1466 ~/.claude/hooks/cbm-code-discovery-gate CMM_HOOK_COMMAND macro
cli.c:1650 ${HOME}/.claude/hooks cbm_install_hook_gate_script
cli.c:1687,1694 ~/.claude/hooks/... session-reminder hook
cli.c:2629 ${HOME}/.claude/skills install_claude_code_config
cli.c:2640 ${HOME}/.claude/.mcp.json install MCP
cli.c:2654 ${HOME}/.claude/settings.json install hooks
cli.c:2949..2967 same paths uninstall_claude_code

Same bug at the shell layer: scripts/setup.sh:212,218, scripts/security-install.sh:124.

Note: hooks installed into ~/.claude/hooks/ already read CLAUDE_CONFIG_DIR correctly at runtime — only the install/uninstall path ignores it.

Proposal

Add a small helper:

static void cbm_claude_config_dir(const char *home, char *out, size_t out_sz) {
    const char *env = getenv("CLAUDE_CONFIG_DIR");
    if (env && env[0]) {
        snprintf(out, out_sz, "%s", env);
    } else {
        snprintf(out, out_sz, "%s/.claude", home);
    }
}

…and route every "%s/.claude..." install/uninstall write through it. Replace CMM_HOOK_COMMAND / CMM_SESSION_COMMAND macro literals with strings composed at install time so settings.json records the actual hook path.

Bundle a one-line stderr migration hint: when the resolved dir differs from $HOME/.claude and a stale ~/.claude install is detected, list legacy artifacts so users can remove them. Bundling this with the fix avoids a two-release rollout where users upgrade, find their config silently moved, and have no nudge to clean up the old tree.

Mirror the change in scripts/setup.sh and scripts/security-install.sh (CLAUDE_HOME="${CLAUDE_CONFIG_DIR:-$HOME/.claude}").

Add a smoke-test case (scripts/smoke-test.sh) asserting that with CLAUDE_CONFIG_DIR set the artifacts land there, not in $FAKE_HOME/.claude.

Out of scope

  • Adding a project-local --scope=project install flag (separate feature gap, future work).
  • The Phase-07 plan in some downstream forks targeting a Go installer — that installer is no longer the install path; only the C install subcommand is in use.

Environment

  • macOS, codebase-memory-mcp 0.6.1
  • CLAUDE_CONFIG_DIR=$HOME/.config/claude-code (Claude Code's own configured location)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingux/behaviorDisplay bugs, docs, adoption UX

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions