The UserPromptSubmit hook's structural-prompt gate was English-only, so a
structural question written in Chinese — or any non-Latin script — silently
injected nothing: JS `\b` is ASCII-only and never matches between Han
characters, so the keyword regex couldn't fire (and couldn't be extended in
place). To the user the hook looked unwired, with no error to explain why.
Make the gate language-aware, split into tested helpers in directory.ts:
- hasStructuralKeyword: English (\b-guarded) + CJK structural keywords.
- extractCodeTokens: identifier-shaped tokens (camelCase / snake_case /
name() / a.b) in any language — verified against the index via
getNodesByName before firing, so a tech brand like `JavaScript` that looks
like a symbol but isn't one here doesn't inject ~16KB of spurious context.
- isStructuralPrompt: the cheap candidate gate (keyword OR code-token).
Adds 21 unit tests for the gate (previously untested) covering the reporter's
verification table plus the false-positive guards.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The MCP server gated tool availability on whether the server root had a
.codegraph/ index, so in a monorepo where only sub-projects are indexed the
agent saw zero tools — and couldn't reach an indexed sub-project even by
projectPath. A session started before `codegraph init` also never surfaced the
tools afterward. The Claude front-load hook had the mirror gap: it only walked
UP for an index, so it stayed silent at a monorepo root.
MCP server:
- Always expose the tool surface; when the root isn't indexed, send a
per-project instructions variant (pass projectPath) instead of the
"inactive" note. Safety comes from response SHAPE (success-shaped guidance,
never isError), not from hiding tools.
- Reword the no-default-project guidance to be per-project, not per-session,
and sharpen the projectPath schema description.
Front-load hook (UserPromptSubmit):
- Scan DOWN (bounded depth, workspace-root-gated) for indexed sub-projects and
shape the injection by topology: front-load the one the prompt names, nudge
about the rest, or list them when ambiguous.
Verified: full suite (1703 passed); a live two-package monorepo run confirms the
hook front-loads the correct sub-project with no cross-package leakage. The
front-load's net speed effect is the existing multi-file-vs-single-file
tradeoff, unchanged by this work.
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.
Versions <= 0.9.9 wrote an explicit-allowlist .codegraph/.gitignore
(*.db, cache/, .dirty, ...) that never listed daemon.pid or the socket,
so the daemon's runtime pidfile got committed. The wildcard rewrite in
#654/#492/#484 fixed new inits, but the file is only written when
absent, so existing installs kept their stale file forever — the fix
never reached the people hitting it.
Make the gitignore self-heal: ensureGitignore() writes the file if
absent and upgrades a stale CodeGraph-generated default in place,
leaving a user-authored file untouched. A "stale default" is one that
carries our `# CodeGraph data files` header but predates the wildcard
ignore (no bare `*` line) — a header match heals every historical
variant (v0.7.x..0.9.9, all verified to share it) and is idempotent.
validateDirectory() runs on every open()/openSync(), so existing repos
heal on the next codegraph command after upgrading. The duplicated
template (previously inlined in two formats) is consolidated into one
GITIGNORE_CONTENT constant.
Co-authored-by: Claude Opus 4.8 (1M context) <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>
Batch of small, localized fixes from an open-issue triage:
- .codegraph/.gitignore now ignores everything but itself, so the database,
daemon.pid, sockets, and logs stop showing up in git status (#492, #484)
- MCP server answers resources/list and prompts/list with empty lists instead
of -32601, clearing scary log lines in opencode/Codex (#621)
- index SAP HANA .xsjs/.xsjslib as JavaScript (#556) and TS .mts/.cts (#366)
- visit anonymous AMD/CommonJS/IIFE wrapper bodies so their inner functions and
calls are indexed instead of coming up empty (#528)
- batch the changed-file lookup so a huge first sync no longer hits
"too many SQL variables" (#540)
- list files with `git ls-files -z` so non-ASCII/CJK paths survive
core.quotepath and are no longer silently skipped (#541)
- attach Go methods on generic receivers (*T[P]) to their type (#583, RC1)
- impact no longer climbs the structural `contains` edge, so a leaf symbol
stops dragging in its sibling methods (#536)
- README: explicit `codegraph install` step, run in a new shell (#631)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add validateProjectPath() to reject sensitive system directories
- Add isPathWithinRoot/isPathWithinRootReal for symlink-aware path checks
- Replace hand-rolled glob-to-regex with picomatch to prevent ReDoS
- Add isSafeRegex() to reject custom patterns with nested quantifiers
- Replace FileLock with PID-tracking version that detects stale locks
- Add symlink detection in removeDirectory/listDirectoryContents
- Add subdirectory name validation in ensureSubdirectory
- Add atomicWriteFileSync and corrupted file backup in config-writer
- Add MCP input validation (validateString) for all tool handlers
- Fix CLAUDE.md section replacement to handle ### subsections correctly
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.