Fixes#1578.
## What was wrong
Bootstrapping CodeGraph in a fresh environment — the issue's case is a throwaway container per AI session — took two commands, `codegraph install --yes` and then `codegraph init`, and the second one could still stop on a prompt (the gitignored-child-repos offer, the watch-fallback offer on WSL/`/mnt`). There was no way to wire agents and build the project's index in one non-interactive line.
The installer's "never index implicitly" rule is deliberate (a surprise index of `$HOME` is exactly what `init` refuses), so the gap is an explicit opt-in, not a change in default behavior.
## What this does
- **`codegraph install -i, --init`** — after wiring the agents, runs the `init` flow in the current directory. It also runs when nothing was wired (`--target none`, no agents detected), since the installer returns normally in that case. Every `init` guard applies: a home directory / filesystem root / parent of home is **refused with exit code 1** (no implied `--force`), and an already-initialized project just reports that and exits 0. `--print-config` and `--refresh` return before the install, so `--init` is a no-op with them.
- **`codegraph init -y, --yes`** — non-interactive: the ignored-repos offer prints its one-line `includeIgnored` opt-in snippet instead of prompting (the existing non-TTY behavior), and the watch-fallback offer takes its `yes` default. `install --init` passes `--yes` through, so `codegraph install --yes --init` is a fully unattended bootstrap.
- The `init` action body becomes `runInit()`, shared by both commands. The plain `init` path is behavior-identical (same refusal, already-initialized notice, supervised index, telemetry, offers, outro).
- The post-install "Next: index a project" note gains one line mentioning `--init`; README gets the flag row and a `--yes --init` example.
On the reporter's other observation — `install --yes` skipping the "install the CLI on your PATH" step: that's by design for scripted use (it assumes the CLI is already present), and the `bunx @colbymchenry/codegraph serve --mcp` MCP entry they found is the self-contained alternative. Not changed here.
## Tests
`__tests__/cli-install-init.test.ts` — end-to-end against the built binary with stdin closed (a blocking prompt would fail), always `--target none` so the suite never touches an agent config on the host:
- `install --yes --target none --init` → exit 0, installer reports nothing to wire, `Initialized in <tmp>`, `.codegraph/codegraph.db` exists;
- the same on an already-initialized project → `Already initialized`, exit 0;
- the same at the filesystem root → exit 1, `Refusing to initialize`, nothing written;
- `init --yes` with stdin closed → exit 0, index built;
- `init --help` lists `-y, --yes`, `install --help` lists `-i, --init`.
`npx vitest run __tests__/installer-targets.test.ts __tests__/upgrade.test.ts` → 283 passed, 3 skipped. Full `npm test` → see the checks on this PR / below.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01LxZj6W6Y1SHXwvpT3uwJpK
Codex CLI has a first-class project config layer — `.codex/config.toml`
is layer 4 of the loader stack, above the user config at layer 6
(`codex-rs/config/src/loader/README.md` in openai/codex), and it landed
in openai/codex#8354 on 2025-12-22. The CodexTarget's "Codex has no
project-local config concept" note was therefore never accurate, and
`supportsLocation('local') === false` made Codex the one agent that
forces a machine-wide MCP install.
`mcp_servers` is not on the project layer's denylist (which strips base
URLs, model providers, `notify`, profiles and otel — settings repo
contents shouldn't choose), so a project-scoped `[mcp_servers.codegraph]`
is honored.
- Path helpers take a `Location`: global keeps `~/.codex/config.toml` +
`~/.codex/AGENTS.md`; local writes `<cwd>/.codex/config.toml` and the
project-root `<cwd>/AGENTS.md` — the same split the gemini and
opencode targets already use for their local layout.
- Drops the five `loc !== 'global'` early returns from detect, install,
uninstall, printConfig and describePaths.
- Local install returns a note that Codex only applies a project layer
in a project marked trusted; untrusted projects load the layer but
leave it disabled, so a silent success would be misleading.
- Refreshes the two doc comments that used Codex as the example of a
global-only target (now the Copilot CLI).
Tests: two new cases covering the local write layout, the trust note,
global config staying untouched, and local uninstall leaving the global
entry intact. Both fail against the previous implementation. The generic
per-target contract suite now also exercises codex at location=local.
Adds three new installer targets so `codegraph install` can wire the
MCP server into GitHub Copilot surfaces:
- copilot-vscode: .vscode/mcp.json (local) or the VS Code User-dir
mcp.json (global), JSONC-surgical edits, `--path` pinned via
${workspaceFolder} for global installs
- copilot-cli: ~/.copilot/mcp-config.json
- copilot-jetbrains: github-copilot config dir (XDG / %LOCALAPPDATA%)
Detection, install, uninstall, and --print-config are covered for all
three in installer-targets.test.ts, including platform-specific path
resolution.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One-time, strictly opt-in prompt at the end of codegraph install and
codegraph upgrade to join the CodeGraph Pro beta waitlist (same list as
the getcodegraph.com homepage form). Nothing is sent unless the user
answers yes AND enters an email; either answer is recorded machine-wide
so no later install or upgrade re-asks, and --yes / non-interactive / CI
runs never see the prompt.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(uninstall): remove the CLI binaries too, not just agent configs (#1071)
`codegraph uninstall` swept agent configurations and stopped — every
installed binary stayed behind, so `codegraph` still ran afterward. Three
disconnected paths each removed a fraction of an installation (uninstall:
configs; install.sh --uninstall: the bundle; npm preuninstall: configs +
npm's own package), and none cleared a shadowed second install — the
uninstall edition of the #1071 PATH shadow.
The uninstall now PLANS every install present on the machine — the bundle
layout(s) (running binary's own, the platform default, a custom
CODEGRAPH_INSTALL_DIR), the npm global package (found by asking
`npm root -g`, so nvm/fnm/volta prefixes resolve correctly), and the
bin-dir launcher link (only when it verifiably points into a detected
install) — confirms with the user, then removes them all. `--yes` skips
the prompt; the new `--keep-cli` flag keeps the old configs-only behavior.
Safety rules: a source checkout is reported, never deleted; a
project-local npm install is left to the project; on unix the default
install dir doubles as the machine state dir, so only the install
artifacts (versions/, current) are removed there — telemetry choice and
daemon records survive. Windows can't delete a running exe but can rename
it (the in-place upgrade's trick): a locked node.exe is renamed aside and
surfaced as a one-file leftover instead of failing the removal, and npm
is routed through cmd.exe (a direct .cmd spawn EINVALs on modern Node).
Planner/executor are split with injected side effects (the upgrade
orchestrator's convention) and unit-tested across the shadow case,
state-dir preservation, custom dirs, foreign-shim protection, and the
locked-exe dance; validated end-to-end on macOS against a fake HOME.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(uninstall): key path math on the target platform, not the host
Real-Windows validation caught it: the planner/executor used the host
path module, so win32 fixtures were meaningless on a POSIX host and
POSIX fixtures failed on the Windows VM. Same convention as
detectInstallMethod now — path.win32/path.posix chosen by the injected
platform.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(upgrade): route npm through cmd.exe on Windows — a direct npm.cmd spawn EINVALs on modern Node
Found while validating the uninstall change on the Windows VM: upgradeNpm
spawned npm.cmd without a shell, which every current Node rejects with
EINVAL (the CVE-2024-27980 hardening) — so `codegraph upgrade` on a
Windows npm install failed before doing anything. Verified live on the VM:
spawnSync('npm.cmd') → EINVAL; cmd.exe /d /s /c npm → works.
npmInvocation moves into the upgrade orchestrator (remove-binary imports
it from there — same direction as its existing imports, no cycle), and the
win32 test now pins the WORKING invocation instead of the broken one.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(upgrade): refresh installer-written agent surfaces after a binary upgrade
codegraph upgrade swapped the binary but never revisited what earlier
installs wrote into CLAUDE.md / AGENTS.md / GEMINI.md and the agent
configs, so sections written by a pre-1.0 installer kept teaching agents
a multi-tool surface (including tools that no longer exist) months of
releases later. The install path already self-heals everything it owns,
but nothing ever called it on upgrade.
- codegraph install --refresh: non-interactive sweep that re-runs
install() for already-configured targets only — never a first
install; permissions and prompt-hook choices are preserved.
- codegraph upgrade spawns it via the freshly-installed binary after a
successful swap (the still-running old process would only rewrite its
own stale template). Gated on PATH resolution and the
CODEGRAPH_NO_INSTALL_REFRESH=1 kill-switch; never fatal to the
upgrade.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(installer): clarify refresh change reporting
---------
Co-authored-by: xuing <np2v9bvbbs@privaterelay.appleid.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Colby McHenry <me@colbymchenry.com>
extraction/index.ts bounds every git call it makes; worktree.ts,
git-hooks.ts, and the installer's npm install -g did not, so a stuck
subprocess blocked the caller indefinitely. Worst case was the daemon:
gitWorktreeRoot/gitCommonDir run (memoized) on the main event loop while
serving MCP clients, where an unbounded git hang would trip the 60s
liveness watchdog and SIGKILL a healthy daemon. git calls get 5s, the
interactive npm install 120s. Regression tests assert the option through
a mocked child_process plus a per-file call-site sweep.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
`codegraph install` no longer indexes the current directory — it wires up agents
only, and building a project's graph is always the explicit `codegraph init` /
`index`. Removes the global-vs-local inconsistency (a local install silently
indexed, a global one didn't) and the docs/behavior mismatch (#826). README
updated to match; the stale `init --index` note (indexing is default now) fixed.
Adds an opt-in Claude Code front-load hook: a `UserPromptSubmit` hook that runs
the new hidden `codegraph prompt-hook`, which injects codegraph_explore context
for structural ("how / where / trace / impact") prompts so the agent answers
from the graph instead of grepping to rebuild it. Prompted at install
(default-yes; Claude-only — the only agent with prompt hooks), removed on
uninstall, and `codegraph upgrade` self-heals it onto an already-configured
global Claude install. Strictly additive + degradable: non-structural prompts,
un-indexed projects, and any failure are silent no-ops. Disable without
uninstalling via CODEGRAPH_NO_PROMPT_HOOK=1.
7 new installer-targets contract tests (write / idempotent / opt-out round-trip /
sibling-preserved / uninstall / legacy-independent). Full suite green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Running the installer or `codegraph init`/`index` from $HOME auto-indexed the
entire home tree (installer indexes process.cwd() with no guard), producing a
multi-GB ~/.codegraph/codegraph.db; the install dir sharing the ~/.codegraph
name then made every home subdir resolve its root to $HOME. On pre-1.0 macOS the
per-file watcher over that tree exhausted kern.maxfiles and crashed the machine
(#845; the fd blowup was fixed in 1.0.0, this fixes the root cause).
Add unsafeIndexRootReason() and refuse the home dir, a parent of home, and
filesystem roots at the installer auto-index, `init`, and `index`. Overridable
with --force. Closes#845.
Adds anonymous usage statistics (commands/tools used, languages indexed,
connecting agents) with a strict, auditable allowlist. Never code, paths,
file/symbol names, queries, or IPs.
- src/telemetry/: zero-dep client — consent resolution (DO_NOT_TRACK >
CODEGRAPH_TELEMETRY > stored choice > default-on), random machine UUID,
in-memory counters → capped JSONL buffer → completed-day rollups; sync
exit-append (survives process.exit) + opportunistic bounded sends; the
first-run notice gates the first SEND, never local buffering, so the
installer's consent toggle always precedes it. Off is off: no recording,
no socket, buffered data deleted.
- codegraph telemetry status|on|off; per-command counting via preAction hook.
- MCP: tool counting after the reply is on the wire (session + proxy
in-process fallback), agent attribution from initialize clientInfo,
unref'd daemon flush interval. Zero hot-path cost, zero stdout.
- Installer: visible default-on consent toggle (asked once, never re-asked),
install/index/uninstall lifecycle events.
- telemetry-worker/: public Cloudflare Worker behind telemetry.getcodegraph.com
— allowlist validation, IP stripping, per-machine rate limit, forwards to
PostHog as anonymous events. Ships nowhere with the npm package.
- TELEMETRY.md (field-by-field contract) + README section + design doc.
- 20 unit tests; suite-wide CODEGRAPH_TELEMETRY=0 guard so tests never
pollute real telemetry. Full suite: 1448 passing.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Two environments that share one working tree — most concretely Windows
and WSL — can't safely share a single `.codegraph/`: the daemon lockfile
records a platform-specific pid + socket (named pipe vs Unix socket), and
SQLite locking across the WSL2/Windows filesystem boundary is unreliable,
so two daemons over one index risks corruption.
Add a `CODEGRAPH_DIR` env var (default `.codegraph`) that overrides the
per-project data directory name, so each environment keeps its own index
in the same tree (e.g. `CODEGRAPH_DIR=.codegraph-win` on Windows). The
name is resolved live and validated (rejects separators / `..` / absolute,
falling back to the default with a one-time stderr warning). Indexing and
file-watching now skip ANY `.codegraph-*` sibling so neither side trips
over the other's data.
Routes the previously-hardcoded `.codegraph` literals (db path, lockfile,
error log, watcher ignore, file-scan skip, installer) through the
resolver. No extraction-version bump — index content is unchanged.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The installer wrote a `## CodeGraph` usage block into each agent's
instructions file (CLAUDE.md / AGENTS.md / GEMINI.md / .cursor/rules /
Kiro steering) that duplicated, almost verbatim, the guidance the MCP
server already emits in its `initialize` response — so agents that
surface MCP instructions (Claude Code) read the same playbook twice
every turn.
All 6 instruction-writing targets (claude, cursor, codex, opencode,
gemini, kiro) now stop writing the block. install self-heals by
stripping a block a previous version wrote (uninstall already did), so
the next `codegraph install`/`uninstall` cleans up existing installs;
upgrading the package alone does not (the leftover block is harmless).
server-instructions.ts is now the single source of truth — the two
steers unique to the old template ("trust codegraph, don't re-verify
with grep" and the not-initialized -> `init -i` hint) are ported there.
Removes the now-dead INSTRUCTIONS_TEMPLATE / CLAUDE_MD_TEMPLATE,
claude-md-template.ts, writeClaudeMd / hasClaudeMdSection, and the
Cursor-only wireProjectSurfaces bootstrap. The install log learned a
"Removed" verb. Tests rewritten to the new contract + self-heal
coverage (140/140 installer tests pass).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On Windows, v0.9.5's detached shared daemon (#411) has no inherited console,
so any console-subsystem child it spawns gets a fresh visible console window
unless the spawn passes `windowsHide: true`. The fix adds the flag to all
ten `spawnSync` / `execFileSync` / `execSync` call sites across extraction,
sync, installer, and the WASM-flags relaunch. macOS/Linux ignore the option,
so this is a no-op elsewhere.
Fixes#485, #510, #530.
Co-authored work:
- #498 (csw-chen) — full sweep across extraction, sync, installer, and wasm-runtime. **This is the change being merged.**
- #505 (yushengruohui) — independently identified and fixed the 7 git execFileSync sites. Superseded by #498's broader sweep; same diagnosis.
- #521 (JirA44) — independently identified and fixed the WASM-runtime spawnSync re-exec. Superseded by #498's broader sweep; same diagnosis.
Validated on Windows 11 ARM64 (Parallels): a detached parent's 15 git spawns produce 15 visible black flash-windows without the fix and 0 with it.
`codegraph install` now detects and configures Kiro alongside the
existing seven agents. Writes `mcpServers.codegraph` to
`~/.kiro/settings/mcp.json` (global) or `./.kiro/settings/mcp.json`
(local), plus a dedicated `~/.kiro/steering/codegraph.md` /
`./.kiro/steering/codegraph.md` instruction file — Kiro's steering
system loads every `*.md` file in `steering/` as agent context, so a
dedicated file is the natural surface (no marker-based merging needed).
Sibling MCP servers in `mcp.json` and unrelated steering files
(`product.md`, `tech.md`, etc.) are preserved across install and
uninstall. Validated end-to-end on macOS, Linux (Docker node:22-bookworm
arm64), and Windows 11 (Parallels VM, Node 24): full installer-targets
suite passes (132 tests) on all three platforms, and live install /
idempotent re-run / uninstall round-trip works as expected.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`codegraph install` now detects and configures two more agents:
- Gemini CLI / Antigravity CLI — `~/.gemini/settings.json` (or
`./.gemini/settings.json`) + `~/.gemini/GEMINI.md` (or project-root
`./GEMINI.md`). Preserves pre-existing top-level settings like
`security.auth` and sibling MCP servers.
- Antigravity IDE — writes to Antigravity's unified MCP config at
`~/.gemini/config/mcp_config.json` (post-migration, detected via
the `.migrated` marker Antigravity drops). Falls back to the
legacy `~/.gemini/antigravity/mcp_config.json` on pre-migration
builds; install migrates a stale legacy entry, uninstall sweeps
both. Antigravity-managed sibling fields (e.g. the `disabled` flag
added when users disable a server through the UI) survive re-install.
Two Antigravity-specific quirks the target handles:
1. Entries with `type: "stdio"` are silently rejected by
Antigravity's MCP scanner; we omit the field for this target.
2. macOS GUI apps launched from Dock/Finder get a stripped PATH
that excludes nvm — a bare `codegraph` command name fails to
spawn even when `which codegraph` works in the user's shell.
The target resolves `codegraph` to its absolute path at install
time on macOS. Linux + Windows are unaffected.
End-to-end validated:
- macOS: real Gemini CLI v0.43 via tmux — `/mcp` shows codegraph with
all 10 tools, `codegraph_status` executes and returns real index
state. Real Antigravity IDE shows codegraph under Customizations
after restart.
- Linux (Docker node:22-bookworm) + Windows (Parallels Win11): 116
installer tests pass; CLI install + uninstall round-trip verified.
Test coverage: the new targets inherit the existing parameterized
contract (idempotent install, sibling preservation, install/uninstall
round-trip). Plus 14 target-specific tests covering migration-marker
detection, legacy→unified entry migration, `disabled` flag
preservation, the `type` field omission, gemini+antigravity
coexistence in the same `~/.gemini/`, and macOS-only path resolution.
Full suite: 972 passing.
Closes#399.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a cross-channel uninstall that removes CodeGraph from every agent it's
configured on (Claude Code, Cursor, Codex CLI, opencode, Hermes). Prompts
global-vs-local up front (no flags required) and reports which providers it
actually hit; --location / --target / --yes supported for non-interactive use.
Removes only what install wrote; leaves the .codegraph/ index to `uninit`.
Also fixes Cursor uninstall leaving an orphaned .cursor/rules/codegraph.mdc
(its description: CodeGraph frontmatter lingered); the dedicated rules file is
now deleted outright while user content outside our markers is preserved.
Validated end-to-end on macOS and Docker Linux (global + local sweeps clean).
Adds 8 tests; full suite 730 passing. Bumps to 0.9.3 with CHANGELOG entry.
Resolves#313.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds Hermes Agent (Nous Research) as a CodeGraph installer target. Writes mcp_servers.codegraph and ensures platform_toolsets.cli includes mcp-codegraph in $HERMES_HOME/config.yaml, with full installer contract-test coverage.
Recursive fs.watch on a WSL2 /mnt NTFS/9p mount walks the directory tree
with every readdir/stat crossing the Windows boundary, stalling the event
loop long enough to blow past opencode's 30s MCP handshake timeout so the
tools never appear. This is the file-watcher half of the #172 fix, which
moved the DB/WASM open off the handshake but left the watcher on the
critical path.
- Add watchDisabledReason() policy: CODEGRAPH_NO_WATCH (off) >
CODEGRAPH_FORCE_WATCH (force on) > WSL2 + /mnt auto-detect (off).
FileWatcher.start() and the MCP server both honor it; the server now
logs why watching is off and how to refresh.
- Add `codegraph serve --mcp --no-watch`.
- When watching is off, init/install offer git sync hooks (post-commit,
post-merge, post-checkout) that run `codegraph sync` in the background,
or fall back to manual sync; either way the user is told the index
stays frozen until re-synced. uninit removes the hooks.
- Tests: watch-policy + git-hooks (idempotency, user-content preservation,
core.hooksPath).
Root-cause analysis and workaround by @mengfanbo123.
Closes#199
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The shimmer progress renderer writes from a worker thread via
`fs.writeSync(1, ...)` to keep the animation smooth while the main
thread is busy in SQLite. That path bypasses Node's TTY-aware
UTF-8->codepage conversion on Windows, so glyphs like `|`/`<>`/`-`
were emitted as raw UTF-8 bytes and reinterpreted by the console's
OEM codepage (CP437, CP936, ...), producing strings like
`鋍?[0m 鉒?[0m Scanning files 鈥?N found`.
Add `src/ui/glyphs.ts` with `supportsUnicode()` detection plus
matched Unicode + ASCII glyph sets, and route all CLI/shimmer
output through `getGlyphs()`. Defaults: ASCII on Windows and on
Linux kernel consoles (`TERM=linux`), Unicode everywhere else.
`CODEGRAPH_UNICODE=1` and `CODEGRAPH_ASCII=1` are escape hatches.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(installer): multi-target — Claude Code, Cursor, Codex CLI, opencode
Closes the Claude-locked installer behind issue #137. The runtime MCP
server was already agent-agnostic (stdio); only the installer was
locked. After this refactor, `codegraph install` can write per-agent
MCP config + instructions for any combination of supported agents.
## What ships
Four agent targets, each implementing the new `AgentTarget` interface:
- **Claude Code** — `~/.claude.json`, `~/.claude/settings.json`,
`~/.claude/CLAUDE.md` (or local equivalents). Behavior preserved
from the original installer; existing installs upgrade in place.
- **Cursor** — `~/.cursor/mcp.json` (g) or `./.cursor/mcp.json` (l)
+ project-local `./.cursor/rules/codegraph.mdc`.
- **Codex CLI** — `~/.codex/config.toml` with `[mcp_servers.codegraph]`
+ `~/.codex/AGENTS.md`. Global only. Hand-rolled TOML serializer
scoped to the table we own — siblings + array-of-tables preserved.
- **opencode** — `~/.config/opencode/opencode.json` (XDG) or
`./opencode.json`.
Adding a 5th agent is a new file in `src/installer/targets/` plus
one entry in `registry.ts`.
## CLI changes
```
codegraph install # interactive multi-select
codegraph install --yes # auto-detect, install global
codegraph install --target=cursor,claude --yes # explicit list
codegraph install --target=auto --location=local # detected, project-local
codegraph install --target=none # skip agent writes entirely
codegraph install --print-config codex # dump snippet, no writes
```
## Backwards compat
Every export from the old `config-writer.ts` (`writeMcpConfig`,
`writePermissions`, `writeClaudeMd`, `hasMcpConfig`, `hasPermissions`,
`hasClaudeMdSection`) is preserved as a `@deprecated` shim that
delegates to per-file helpers in `targets/claude.ts`. Existing Claude
users see byte-identical on-disk layout — `detect()` reports
`alreadyConfigured: true`, re-running is a no-op.
## Tests
+47 new tests in `__tests__/installer-targets.test.ts`:
- Parameterized contract test across all 4 targets × supported
locations (install → unchanged on re-run, sibling preservation,
uninstall reverses install, printConfig writes nothing).
- Codex partial-state recovery, locked-block contract for the
codegraph table, full TOML serializer suite.
- Registry: getTarget, resolveTargetFlag (auto/all/none/csv).
`__tests__/installer.test.ts` relaxed one assertion: the new code
returns `unchanged` for byte-identical re-runs instead of `updated`;
the surrounding-custom-content contract is unchanged.
## Uninstall behavior change
`bin/uninstall.ts` now loops `ALL_TARGETS.uninstall('global')` on
`npm uninstall -g`. A user who manually configured
`~/.codex/config.toml` with our block will have only that block
removed on package uninstall — we only touch the dotted-key table
we own.
Based on andreinknv/codegraph@c5165e4. Issue #137.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(scripts): add local-install.sh for hands-on branch testing
Builds the current branch and `npm link`s it as the global
`codegraph` binary. `--undo` unlinks and reinstalls the published
version. Mirrors the style of scripts/release.sh.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(installer): move agent picker to the first prompt
Reorders runInstallerWithOptions so the multi-select for agents
(Claude / Cursor / Codex / opencode) is step 1 — before the
global-npm-install confirm and before the location prompt. Bare
`npx @colbymchenry/codegraph` now opens with "Which agents should
CodeGraph configure?", which is the answer most users want first.
Side effects of the reorder:
- Early exit if zero targets selected — skips global-install and
location prompts entirely, exits with "nothing to do."
- Multiselect labels drop the per-location "will skip" hint (location
isn't known yet) and replace it with a static "global only" badge
for targets like Codex that have no project-local config concept.
- If every selected target is global-only, the location prompt is
skipped and global is forced (no point asking).
- Detection probes the user-provided location if known via flag,
else 'global' as the most common default — labels are a hint
about what's installed locally, not load-bearing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(installer): disambiguate "global" wording in install prompts
Two prompts both said "global" but meant different things — users
read them as duplicates. Renamed for clarity:
- Step 2 (npm install -g): "Install codegraph globally?" →
"Install the codegraph CLI on your PATH? (Required so agents can
launch the MCP server)". Spinner messages match.
- Step 3 (config location): "Where would you like to install?" with
"Global"/"Local" → "Apply agent configs to all your projects, or
just this one?" with "All projects" (~/.claude, ~/.cursor, etc.)
/ "Just this project" (./.claude, ./.cursor, etc.).
- All-global-only fallback: "Using global install" → "Writing
user-wide configs (selected agents have no project-local config)."
Underlying `Location` values ('global' / 'local') unchanged; only
the UI strings shift, so no test or flag breakage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(installer/cursor): inject --path so workspace-aware queries work
Cursor launches MCP-server subprocesses with cwd != workspace root,
AND does not pass rootUri or workspaceFolders in the MCP initialize
call. The codegraph MCP server's process.cwd() fallback misses the
workspace's .codegraph/ and reports "not initialized" on every tool
call. Codex and Claude don't have this issue (Codex launches with
cwd=workspace, Claude passes rootUri).
Fix: inject `--path` into the args we write for Cursor.
- local install (./.cursor/mcp.json): hardcode the absolute project
path — known at install time.
- global install (~/.cursor/mcp.json): use `${workspaceFolder}` so
Cursor expands it per-workspace. One global config now drives
every project the user opens, without per-project re-install.
No test breakage — the parameterized contract tests check
idempotency / sibling preservation, not the exact args content.
File-header comment documents the rationale so the next person
doesn't strip the arg as boilerplate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(init): auto-wire project-local agent surfaces
Closes the global-Cursor UX gap: `~/.cursor/mcp.json` registers the
MCP server, but Cursor's agent only learns to *prefer* codegraph
over native grep when it sees `.cursor/rules/codegraph.mdc` — a
project-local file that global install can't write. Previously the
user had to re-run `codegraph install --target=cursor --location=local`
for every new project. Now `codegraph init` does it automatically.
## What changed
- New optional `AgentTarget.wireProjectSurfaces()` returning a
WriteResult of project-local files to drop. Most targets omit
it (their global config is complete). Cursor implements it to
write the rules file.
- New `wireProjectSurfacesForGlobalAgents()` orchestrator in
installer/index.ts — iterates ALL_TARGETS, detects which are
configured globally, calls their wireProjectSurfaces, returns
what was written.
- `codegraph init` calls the orchestrator in both branches:
- Fresh init: write surfaces after CodeGraph.init succeeds.
- Already-initialized re-init: write surfaces too, so re-running
`init` is the documented recovery path for a project missing
its rules file.
## Steady-state UX
1. Once, ever: `codegraph install` (writes global agent configs)
2. Per project: `codegraph init -i` (builds the index + auto-wires
project-local agent surfaces — currently Cursor's rules file)
No new tests — wireProjectSurfaces delegates to writeRulesEntry,
which is already covered by the parameterized contract tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(installer): agent-agnostic instructions template
The old template was inherited from the Claude-only era and
prescribed "ALWAYS spawn an Explore agent" — a Claude Code-specific
concept (subagents via the Task tool). When Cursor's agent read
this it had no Explore agent to spawn, got confused, and fell back
to native grep/read even for structural queries the codegraph MCP
tools answer in one call.
This rewrite:
- Frames each tool by the question it answers (search vs callers
vs impact vs context vs explore vs node vs files vs status).
- Tells the agent explicitly to TRUST codegraph results and not
re-verify them with grep — the over-grep-after-codegraph
behavior was the main symptom we saw on Cursor.
- Reframes "spawn Explore agent" as an OPTIONAL pattern for
harnesses that support parallel subagents — Claude Code still
gets the hint, Cursor / Codex / opencode just skip it.
- Trims the "if not initialized" section to one prescriptive line.
Same marker delimiters (`<!-- CODEGRAPH_START/END -->`) so existing
installs upgrade in place via the marker-based section swap. No
test changes needed — the parameterized contract tests check
marker placement + sibling preservation, not the literal body.
Effective surfaces: ~/.claude/CLAUDE.md (Claude), .cursor/rules/
codegraph.mdc (Cursor, project-local), ~/.codex/AGENTS.md (Codex).
Users get the new copy by re-running `codegraph install` for
global writes, or `codegraph init` for Cursor's project rules.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(readme): reflect multi-agent support at the top + accurate flow
- Tagline now reads "Supercharge Claude Code, Cursor & Codex" instead
of Claude-only — multi-agent support is what the PR is about, the
README should say so above the fold.
- New badge row (Claude Code / Cursor / Codex CLI / opencode) in the
same shields.io style as the OS row.
- Install-flow bullets reordered to match the actual prompt order
(agent picker first, then PATH install, then location).
- `codegraph init -i` step now mentions that init wires up
project-local agent surfaces (Cursor rules file etc.) so global
install works in every project without a re-run.
- Agent-agnostic phrasing in the closing line ("your agent" not
"Claude Code").
Headline-level brand decision left intentionally in this PR — the
existing Claude-only positioning predates multi-agent support.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: andreinknv <andrei.nknv@outlook.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes crystal ball emoji and bullet formatting inconsistencies from README headers. Eliminates mark-dirty and sync-if-dirty CLI commands and related hook configuration code, simplifying the codebase after transitioning to file watcher-based auto-sync.
Offloads tree-sitter parsing to a dedicated worker thread, keeping the main thread unblocked so shimmer progress animations render smoothly during indexing. Refactors shimmer progress renderer into separate worker for consistent 50ms animation updates. Falls back to in-process parsing when worker compilation unavailable (e.g., tests).
Replaces ASCII art banner and basic readline prompts with @clack/prompts for a modern interactive CLI. Adds animated shimmer progress bars with spinner glyphs during indexing operations. Improves installer UX with structured prompts, better error handling, and cleaner output formatting throughout all CLI commands.
Replaces fixed-width padding with terminal escape sequences for proper progress line clearing across different terminal widths. Adds periodic parser reset every 5000 parses per language to prevent WASM heap fragmentation that causes "memory access out of bounds" crashes in large repositories. Includes filename truncation to fit available terminal width.
Adds expression index on lower(name) for memory-efficient case-insensitive searches, replacing in-memory caches that caused OOM on large codebases. Includes batched reference resolution, enhanced error reporting with detailed breakdown by error type, and improved CLI progress display for scanning phases.
Eliminates anonymous error reporting functionality that was collecting stack traces and error context via Sentry. Removes all telemetry-related code, configuration options, and documentation references.
Sentry error reporting can now be disabled by:
1. Declining during the interactive installer (sets CODEGRAPH_TELEMETRY=off
in the MCP server config env)
2. Setting CODEGRAPH_TELEMETRY=off in your shell environment
README updated with a Telemetry section documenting what is collected
and how to opt out.
Closes#68
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The installer previously ran `npm install -g` silently without user
consent. Now it asks for confirmation first, explains why the global
install is needed (hooks & MCP server), and gracefully skips if declined.
README updated to document this step.
Closes#69
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
command -v codegraph is unreliable inside npx because npx puts a
temporary binary in PATH. The check always passes, so the global
install is always skipped — which is the root cause of #37 and #38.
Fix: remove the check entirely, always run npm install -g.
- Revert configs (MCP, hooks) to use bare `codegraph` command
- Remove all npx references from configs and messaging
- Add preuninstall script that runs on `npm uninstall -g` to clean up
MCP server, permissions, hooks, and CLAUDE.md section
- Show uninstall instructions in post-install next steps
Global install is still attempted for bare `codegraph` convenience,
but now verifies the command is actually in PATH after install. If it
fails, users get clear actionable messages instead of silent swallowing.
Configs (MCP server, hooks) always use npx regardless — those never
break even if global install fails.
Remove the npm install -g attempt from the installer that silently
fails on many systems (permissions, PATH, node version managers).
All configs (MCP server, hooks, next-steps) now always use
npx @colbymchenry/codegraph. Global install offered as an optional tip.
Fixes#37, #38
Replace native tree-sitter with web-tree-sitter + tree-sitter-wasms for
universal cross-platform support. Add node-sqlite3-wasm as a fallback
when better-sqlite3 native bindings aren't available. Move better-sqlite3
and sqlite-vss to optionalDependencies so installs never fail.
Fix installer to use npx fallback when global npm install fails, so MCP
config, hooks, and quick-start instructions all work without the bare
codegraph command in PATH.
Fix tests: update schema version expectation, fix db test paths and
method names, extract MAX_OUTPUT_LENGTH as module constant, normalize
Windows path separators in import resolver.
PostToolUse(Edit|Write) marks the project dirty via .codegraph/.dirty,
and Stop syncs only if dirty — batching all edits into one sync per
Claude response. The installer now writes these hooks to settings.json.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds support for Dart and Liquid languages with tree-sitter parsing.
Improves accuracy of code symbol extraction for existing languages.
Indexes project files to enhance code navigation features.
Migrates build system to facilitate code contributions.
Removes git hook functionality.
Integrates Sentry for error tracking and reporting.
Enhances project initialization and configuration loading.
- Added claude-md-template.ts with the instructions template
- Installer writes to ~/.claude/CLAUDE.md (global) or ./.claude/CLAUDE.md (local)
- Smart detection: updates existing CodeGraph section or appends if not found
- Uses HTML comment markers for reliable section replacement on upgrades
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The installer runs `npm install -g @colbymchenry/codegraph` so users
can simply run `codegraph init -i` instead of the full npx command.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- New `codegraph install` command and auto-run when invoked with no args
- Beautiful ASCII banner using figlet
- Interactive prompts for global (~/.claude) or local (./.claude) installation
- Writes MCP server config to claude.json
- Writes auto-allow permissions to settings.json
- For local installs: auto-initializes project, indexes, and installs git hooks
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>