Skip to content

feat(codegraph): optional codegraph MCP integration (mirrors engram)#165

Merged
jraicr merged 1 commit into
devfrom
feat/codegraph-overlay
Jun 28, 2026
Merged

feat(codegraph): optional codegraph MCP integration (mirrors engram)#165
jraicr merged 1 commit into
devfrom
feat/codegraph-overlay

Conversation

@jraicr

@jraicr jraicr commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Make the codegraph code-graph MCP server usable inside the container when it is installed on the host, mirroring the optional engram integration (INV-4-style optional feature).

The host's ~/.local/bin/codegraph symlink is already visible via the base ~/.local mount, but its target — ~/.codegraph, the versioned install dir — was never mounted, so the symlink dangled and codegraph serve --mcp could not start. This change mounts ~/.codegraph so the symlink resolves.

What changed

Area Change
lib/compose.sh codegraph_usable() gate (command -v codegraph && host_is_linux); COMPOSE_CODEGRAPH constant; overlay included in compose_files() gated on codegraph_usable && [ -d ~/.codegraph ] (ccstatusline-style, no export_compose_env change)
docker-compose.codegraph.yml (new) Mounts ${HOME}/.codegraph:${HOME}/.codegraph:rw so the symlink resolves. The per-repo index <repo>/.codegraph already reaches the container via PROJECT_DIR — no separate data mount (simpler than engram: no shared/isolated, no sentinel)
lib/commands.sh _refresh_container_claude_json() generalized from engram-only to a per-tool delete-set: strips the mcpServers entry of each optional tool not usable in the container in one jq del() pass, with a cp -a verbatim fast path when the set is empty. Per-tool notes unified behind _note_mcp_unusable(). doctor/status report codegraph
docs CHANGELOG + README (engram parity)

codegraph lives at top-level ~/.claude.json mcpServers.codegraph (not a mcp/*.json file), so the engram-only rm -f/rsync-exclude/find-prune belt-and-suspenders are not needed.

Invariants

  • INV-2 (container state split)Container mounts MUST point at container-specific state, never host ~/.claude* / ~/.engram. This change adds a new host-path mount (~/.codegraph). It does not violate INV-2: ~/.codegraph is read-mostly install tooling — parallel to ~/.local, already host-mounted rw — not Claude/engram session state. None of INV-2's four hazards apply (no ~/.claude.json clobber, no .credentials.json OAuth race, no MCP-filter mutation, no SQLite engram.db). The overlay header documents this in full.
  • INV-8 (container hardening defaults) — intact. The overlay adds only a volumes: entry: no cap_add, no security_opt change, no privileged. Zero new Linux capabilities.

rw vs ro (deliberate)

Mounted rw, matching the base ~/.local mount. ro would be least-privilege but risks EROFS if codegraph serve --mcp writes install-dir metadata (update cache / lockfile) at startup, and the security gain is marginal since ~/.local is already rw. The overlay header names the residual (new write surface, bounded under threat model A + single-user trust) and records ro as a documented future hardening once codegraph's serve-time write behavior is confirmed.

Verification

  • Full bats suite green (1261 ok, 0 failures); shellcheck / shfmt / lint-commits all clean.
  • Two fresh adversarial reviews (risk + readability) incorporated.
  • Live test passed: in a fresh drydock session the overlay activates and codegraph --version1.1.2 — proving the mount + symlink resolve and the (statically linked) binary executes in the container.

Size

~420 changed lines (> 400 budget) → size:exception. ~206 of those are tests (inseparable under TDD) and ~18 are docs; the actual lib/overlay code is ~159 lines. Splitting a cohesive engram-mirror into chained PRs would harm review focus rather than help.

Make the codegraph code-graph MCP server usable inside the container when it
is installed on the host, mirroring the optional engram integration.

The host's ~/.local/bin/codegraph symlink is already visible via the base
~/.local mount, but its target (~/.codegraph, the versioned install dir) was
never mounted, so the symlink dangled and `codegraph serve --mcp` could not
start. A new docker-compose.codegraph.yml mounts ~/.codegraph so the symlink
resolves; it is gated in compose_files() on `codegraph_usable && [ -d ~/.codegraph ]`.
The per-repo index <repo>/.codegraph already reaches the container via the
project mount, so no separate data mount is needed (unlike engram's DB).

The MCP-config filter is generalized from engram-only to a per-tool delete-set:
_refresh_container_claude_json() now strips the mcpServers entry of each optional
tool not usable in the container (engram and/or codegraph) in one jq del() pass,
keeping a cp -a verbatim fast path when nothing must be stripped. Per-tool
"not usable" notes are unified behind _note_mcp_unusable(); doctor/status report
codegraph.

Verification: full bats suite green (1261 ok), shellcheck/shfmt clean. The live
MCP startup — codegraph serve --mcp coming up and codegraph_explore answering in
a fresh drydock session — is not covered by the unit suite and remains to be
confirmed in a live session.
@jraicr jraicr added type:feat Feature work size:exception Over 400 lines, pre-approved by maintainer labels Jun 28, 2026
@jraicr jraicr merged commit c7d7a33 into dev Jun 28, 2026
4 checks passed
@jraicr jraicr deleted the feat/codegraph-overlay branch June 28, 2026 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:exception Over 400 lines, pre-approved by maintainer type:feat Feature work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant