Skip to content

Claude Code installer writes personal config to team-shared files; add --personal flag for gitignored variants #243

@steven-pribilinskiy

Description

@steven-pribilinskiy

Summary

The Claude Code installer (codegraph install -t claude -l local) writes three files into the project, and two of the three go to the team-shared variant when they should default to the personal/gitignored variant. This silently turns a personal install choice into a team mandate every time the user runs git add .claude/ after install.

Proposing a --personal flag (name TBD — --gitignored or --isolated also fine) that routes every write to the gitignored / personal-scope variant so the install leaves zero footprint in the team-tracked tree.

What the installer writes today (v0.8.0, -l local)

File written Tracked by git? Should be personal?
./.mcp.json (MCP entry) ✅ committed Arguable — see below
./.claude/settings.json (permissions, if --auto-allow) ✅ committed Yes — this is the bug
./.claude/CLAUDE.md (instructions) ✅ committed Yes — this is the bug

-l local currently means "write to the project," but it conflates two orthogonal axes — project-scope vs user-scope and team-shared vs personal. Claude Code actually has three relevant scopes:

  1. Global / user-scope: ~/.claude.json, ~/.claude/settings.json, ~/.claude/CLAUDE.md — every project sees it
  2. Project-scope, team-shared: ./.mcp.json, ./.claude/settings.json, ./.claude/CLAUDE.md — committed
  3. Project-scope, personal: ./.claude/settings.local.json, ./CLAUDE.local.md — gitignored by Claude Code's default scaffolding

The installer only models (1) vs (2). Option (3) is missing.

Why each write is wrong by default

1. Permissions in settings.json — personal trust, not team policy

--auto-allow is fundamentally a personal trust decision ("I personally trust the codegraph binary on my machine"), not a team policy ("everyone on this repo must auto-allow codegraph"). Yet by writing to settings.json it becomes the latter the moment someone runs git add .claude/settings.json.

Worse case (and what happened to me): the project's settings.json already contained legitimately shared hooks config from a teammate. The installer appended permissions into the same file, so the resulting diff co-mingles personal trust grants with team-shared hook config — un-tangling them later requires manual surgery.

Correct destination: ./.claude/settings.local.json. Claude Code's .gitignore scaffolding includes settings.local.json by default; it's exactly the file for this case.

2. Instructions in .claude/CLAUDE.md — committed shared memory

./.claude/CLAUDE.md is loaded into every Claude Code session at startup, costing ~720 tokens forever even for sessions that never query a symbol. That's an acceptable cost for the installing user, but it shouldn't get pushed onto every teammate's session budget — especially teammates who don't have codegraph installed and would have the section claim a codegraph_* MCP server exists when it doesn't.

Correct destination: ./CLAUDE.local.md (project-root, gitignored by default in Claude Code's scaffolding). Claude Code auto-loads it the same way as the shared CLAUDE.md, just for the local user.

(Separately, a .claude/skills/codegraph/SKILL.md would be even better for Claude Code specifically — skills are lazy-loaded only when the LLM decides they're relevant — but that's a deeper change. The CLAUDE.local.md move is the minimum fix.)

3. MCP entry in .mcp.json — borderline

.mcp.json is also committed by default. Argument for keeping it shared: it's a declaration, not a trust grant — Claude Code's enabledMcpjsonServers (in settings.local.json) lets each teammate opt in individually, so a committed .mcp.json entry doesn't auto-activate for teammates who don't add it to their personal opt-in list.

Argument for routing it to a personal variant under --personal: if only the installing user has the codegraph binary on PATH, the entry in .mcp.json is dead weight for everyone else, and the teammate-opt-in-via-enabledMcpjsonServers story isn't documented anywhere in this installer's flow.

A --personal flag could add codegraph to the user's personal enabledMcpjsonServers list in settings.local.json so the project-shared .mcp.json declaration only activates for them — net effect: declaration is in the repo (any teammate who installs codegraph just adds it to their enabledMcpjsonServers and they're set), but it doesn't activate by default for anyone else.

What --personal should do

codegraph install -t claude -l local --personal

Routes writes to:

Concern Default (today) --personal
MCP entry .mcp.json .mcp.json (unchanged — declaration only) + add codegraph to settings.local.json's enabledMcpjsonServers
Permissions (--auto-allow) .claude/settings.json .claude/settings.local.json
Instructions .claude/CLAUDE.md CLAUDE.local.md (project root)

And on codegraph uninstall --personal, reverse the same files. The current uninstall only knows about the shared paths, so a --personal install would also need a --personal uninstall to clean up correctly.

Why a flag instead of just changing the default

I'd argue --personal should be the default for -l local (and the current behavior should require an explicit --shared flag), because:

  • Solo developer: no difference, files go to gitignored paths nobody else sees
  • Team repo: doesn't silently mandate codegraph for everyone
  • Open-source contributor: cloning the repo doesn't inherit upstream's install choices

But changing the default is a breaking change for anyone already shipping codegraph as team policy, so a flag is the safer first step.

Existing related issues

Reproduction

Fresh project with an existing shared .claude/settings.json containing a team hook:

echo '{"hooks":{"PreToolUse":[{"matcher":"Write","hooks":[{"type":"command","command":"./hook.sh"}]}]}}' > .claude/settings.json
git add .claude/settings.json && git commit -m "team hook"

npx @colbymchenry/codegraph@latest
# (choose: claude, just-this-project, auto-allow yes)

git diff .claude/settings.json
# Shows codegraph permissions added INTO the team-shared file,
# now indistinguishable from the team's hook config in the same JSON document.

cat .claude/CLAUDE.md
# 34-line codegraph section, will be loaded into every session for every teammate
# the moment this file is committed.

Environment

  • codegraph: 0.8.0
  • Claude Code: latest
  • OS: Linux (WSL2, Ubuntu)
  • Node: 22.x

Happy to send a PR if there's interest in the --personal flag design above — would want to confirm the flag name and uninstall semantics first.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions