bb1d3093eb3486291abbda570d5cb55993116e0c
100
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ff288ac711 |
feat(cli): one interactive codegraph daemon command, replaces stop/list (#863)
Collapses the unreleased daemon controls into a single interactive command. `codegraph daemon` (alias `daemons`) opens an arrow-key picker (current project's daemon first, pre-selected), enter stops it, or pick "Stop all"; non-TTY prints a plain list. Removes stop/list/ps; reuses the unchanged daemon-registry machinery; the pick->stop loop is in daemon-manager.ts behind an injectable select (unit tested). Validated live on macOS/Linux (real clack picker driven via pty) and Windows (real runDaemonPicker + stopDaemonAt against a real daemon). Closes #845 follow-up. |
||
|
|
0f825649a1 |
feat(cli): codegraph stop / list to manage background daemons (#861)
Adds first-class daemon control (the #845 pain point: no clean way to stop a runaway daemon). `codegraph stop [path]` stops the current/given project's daemon (SIGTERM -> SIGKILL fallback, sweeps artifacts); `stop --all` stops every daemon; `list`/`ps` shows running daemons (--json for scripts). Discovery via a small self-healing registry: each daemon records its root under ~/.codegraph/daemons/ on start, removes it on graceful shutdown; readers prune dead pids. Cross-platform by construction (files + process.kill). Validated live on macOS, Linux (docker), and Windows (VM): registry unit 6/6 and real-daemon stop/list 6/6 on each. |
||
|
|
2472508549 |
fix(installer,cli): refuse to index $HOME / filesystem root (#860)
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. |
||
|
|
3476ac9a27 |
fix(mcp): exit on uncaught exception instead of orphaning/spinning at 100% CPU (#855)
The process-wide uncaughtException handler logged the error and kept running. For the detached `serve --mcp` daemon that turned any escaped fault into an unrecoverable orphan: nothing respawns it, and when logging the raw Error hit a V8 source-position loop while lazily formatting `.stack`, the main thread wedged at 100% CPU so even the PPID watchdog / idle-timer could no longer fire. Same failure mode as #799, which only fixed the stdin-'error' trigger. Restore Node's default fatal semantics: render a bounded, hang-proof line (name + message only — never read `.stack`) then exit non-zero, so a fresh daemon starts on the next connection. Extracted to src/bin/fatal-handler.ts with injectable seams; unit-tested incl. the never-touch-stack invariant. Closes #850. |
||
|
|
848fde9f59 |
feat(telemetry): anonymous usage telemetry — documented schema, opt-out, public ingest worker (#834)
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> |
||
|
|
01717854f5 |
fix(cli): codegraph node accepts Windows backslash paths in file mode (#822)
The file-vs-symbol heuristic only matched '/' — `codegraph node src\auth\session.ts` on Windows fell through to symbol mode and found nothing. Both separators now route to file mode, normalized to forward slashes (the form the index stores). Symbols never contain either separator in any indexed language. Validated: macOS smoke (explore/node symbol/node file/unindexed refusal) + Linux Docker (same smoke + full suite, 1428 passed). Windows VM validation queued — the Parallels guest is currently unreachable (control commands are Pro-gated; needs a manual start). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
adcb862f8e |
fix(cli): explore/node not-indexed error stops agents from running init themselves (#821)
The message said "run 'codegraph init' first" — an instruction-shaped error that invites an agent hitting it (e.g. a subagent following the global instructions block into an unindexed repo) to index the project uninvited: minutes of CPU and a surprise .codegraph/ the user never asked for. Every other layer already encodes indexing-is-the-user's- decision (the MCP NotIndexedError guidance, the inactive instructions, the conditional block); the CLI now matches: continue with your usual tools, do not run init yourself, the project owner can enable it. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
8170d181f2 |
feat(cli+installer): codegraph explore/node CLI + instructions-file block — subagent & non-MCP reach (#704) (#819)
Task-tool subagents never see the MCP initialize instructions and hold the MCP tools only as deferred names they rarely think to load — so delegated work bypassed codegraph almost entirely (measured ~1 of 9 forced-delegation runs touched it; the rest did 30-50 grep/read calls). Two additions close the gap: - CLI: `codegraph explore` and `codegraph node` call the same ToolHandler as the MCP tools and print identical output — the graph for any agent with a shell (subagents, Gemini CLI, raw Codex, humans). - Installer: each agent target (claude/codex/gemini/opencode) writes a short marker-fenced CodeGraph section into its instructions file — the one channel subagents DO receive — naming both surfaces. Upsert self-heals the stale pre-#529 long block; uninstall strips it; re-runs are byte-equal unchanged. (#529's duplication argument bounded the size: four lines, commands only.) A/B (excalidraw, sonnet/high, forced Explore-agent delegation): without the block, subagent codegraph usage ~1/9 runs; with it, 4/4 — subagents ToolSearch-load the MCP tools and run explore 5-7x, best runs with ZERO Read/grep (80-95s vs 150-197s baseline). The block's mechanism: the parent relays the note into the task prompt, making the deferred tool names salient. Contract tests updated to the new expectations (write + self-heal replace the #529 strip-only behavior); README install/guidance sections refreshed (they also still described the pre-#817/#818 tool surface). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
a56d9e6941 |
feat(directory): CODEGRAPH_DIR env var to override the index dir name (#636) (#741)
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> |
||
|
|
4e5cf2de56 |
feat(cli): add codegraph upgrade self-update + stale-index re-index hint (#710)
`codegraph upgrade [version]` detects how the CLI was installed — the standalone install.sh/install.ps1 bundle, npm-global, npx, or a source checkout — and updates in place: re-running the canonical install.sh on macOS/Linux, an in-place rename-and-extract swap on Windows (a running node.exe can't be deleted, only renamed, so the detached-helper approach is avoided), and npm/npx/source-specific guidance otherwise. Flags: `--check` (report only), `--force`, and a positional version to pin. Each full index is now stamped with the engine's EXTRACTION_VERSION in project_metadata; `codegraph status` (and `--json`) flags an index built by an older engine and recommends re-indexing, and `upgrade` prints the same reminder. Gated on EXTRACTION_VERSION so it never nags on extraction-neutral releases. Validated end-to-end on macOS (real bundle upgrade), Linux (Docker, real curl|sh) and Windows (Parallels VM, real in-place swap). 32 new unit tests. Closes #679 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
7b62356f53 |
feat(cli): add version, indexPath, lastIndexed to status --json (#329)
Adds `version`, `indexPath`, and an ISO `lastIndexed` to `codegraph status --json`, plus a `CodeGraph.getLastIndexedAt()` library method. `agentCount` dropped (no clear consumer). Reworked from contributor PRs #333 and #480. Co-Authored-By: Javier Gómez <199902626+12122J@users.noreply.github.com> Co-Authored-By: Ran <8403607+eddieran@users.noreply.github.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
68eaf0dbd8 |
feat(mcp): codegraph_explore as the sole primary tool + store coverage + overload disambiguation (#647)
## Summary
Completes the explore-overhaul arc: `codegraph_explore` becomes the single primary tool an agent reaches for, and its coverage + output shape are tuned so flow/architecture questions resolve with near-zero Read/Grep.
### What changed
- **explore is the sole primary tool** — removed `codegraph_context` (the fuzzy-input Read-trigger) and `codegraph_trace` (under-picked by agents); explore already surfaces the call flow among the symbols you name. A plain natural-language question now works as the query.
- **Store/handler coverage** — functions defined inside object literals (Zustand `create((set, get) => ({ … }))`, Redux/Pinia/MobX, exported handler/route maps) are indexed as real symbols, including calls through `useStore.getState().fn()` and destructured `const { fn } = useStore.getState()`. A general AST rule, not a per-lib hack.
- **Overload disambiguation** — explore leads with the *right* definition when a method name is overloaded across types (a PascalCase type token in the query biases to that type's own def); `codegraph_node` returns *every* overload's body in one call, with an optional `file`/`line` selector to pin one.
- **Method-atomic render** — explore never returns half a method; at the size budget it drops whole methods/files (and lists what it dropped) instead of truncating a body mid-method.
- **Native-read-shaped output** — per-call output is capped to ~24K with a 25K hard ceiling and concentrated into ~150–250-line flow windows, mirroring how the agent natively reads; repo size scales the *call* budget, not the per-call size (a larger response just gets externalized to a file the host Reads back).
- **Blast radius** folded into explore (dependents + covering tests, locations only).
### Benchmark (refreshed on this build)
Re-validated the 7-repo A/B on 2026-06-02 (Opus 4.8, effort=high, median of 4). WITH arm re-measured on this build, WITHOUT reused:
**~16% cheaper · 47% fewer tokens · 22% faster · 58% fewer tool calls** — 0 file reads on 6 of 7 repos (Gin ~1).
The arc trades larger, cache-heavy explore responses for guaranteed near-zero reads, so cost/token margins soften vs the prior build (Excalidraw and Tokio land at cost break-even) while time and tool-calls stay clear wins everywhere — consistent with the project's stated optimization target (latency + tool-calls, not token cost).
### Validation
- Full suite green: **1112 passed, 2 skipped**.
- 28/28 plain WITH runs across the 7 README repos completed clean; reads median 0 on 6/7.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||
|
|
7a75c82dd9 |
feat(cli): codegraph init builds the initial index by default (#483) (#546)
`codegraph init` now runs the initial index automatically. The -i/--index flag is kept but is now a no-op, accepted for backward compatibility so existing muscle memory and scripts don't break. Addresses #483, where a user asked why -i wasn't implicit. README and site/ docs are intentionally NOT updated in this commit — they describe the currently-released 0.9.7 behavior (where -i is still required). Update them at the 0.9.8 release so users on 0.9.7 aren't misled. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a9c9e76d8c |
fix(installer): stop duplicating agent instructions; MCP server is the single source of truth (#529) (#538)
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>
|
||
|
|
71935e37c2 |
feat(mcp): multi-module Go trace-quality + small-repo retrieval tuning (#494)
* feat(go): generated-file down-rank + gRPC stub-impl bridge + trace-failure inlining
Multi-pronged fix to make codegraph competitive on Go multi-module repos
(cosmos-sdk, etcd) where it previously lost or tied. Driven by an 8-question
agent-eval audit across cobra, gin, prometheus, cosmos-sdk, and etcd: the
baseline had codegraph losing ~60% on cost on cosmos-sdk and mixed on etcd
deep cross-module flows, while winning cleanly on the single-module and
non-protobuf-heavy repos.
Diagnostics ruled OUT `go.work` parsing as the gap (prometheus crushes
without it). The actual failure modes were generated-file noise warping
disambiguation, missing gRPC interface→impl bridge in structural-typing Go,
and trace's failure path triggering 3-5 follow-up tool calls instead of
inlining the material the agent needed.
Changes:
- New `src/extraction/generated-detection.ts` — path-pattern classifier
for `.pb.go`, `.pulsar.go`, `_grpc.pb.go`, `_mock.go`, `_mocks.go`,
`mock_*.go`, `.generated.[jt]sx?`, `_pb2(_grpc)?.py`, `.pb.{cc,h}`,
`.g.dart`, `.freezed.dart`. Applied as a stable sort tiebreaker in
`findSymbol`, `findAllSymbols`, `codegraph_search` (MCP + CLI),
`codegraph_explore` file ranking, and context formatter Entry Points /
Related Symbols / Code blocks. Cosmos's `msgServer.Send` now ranks #3
instead of #9 on a `Send` search.
- New `goGrpcStubImplEdges` synthesizer in `callback-synthesizer.ts` —
detects `UnimplementedXxxServer` structs in generated files, identifies
their RPC methods (excluding `mustEmbed*` / `testEmbeddedByValue` gRPC
markers), and emits `calls` edges to the matching methods on any
non-generated struct whose method-name set is a superset. Closes Go's
structural-typing gap that the existing `interfaceOverrideEdges` (Java /
Kotlin only) couldn't bridge. 467 bridge edges on cosmos-sdk; bank's
`UnimplementedMsgServer::Send` points to `x/bank/keeper/msg_server.go`
only, not to `msgClient` siblings or mock files.
- Trace-failure rewrite (`handleTrace`) — when no static path connects
endpoints, instead of telling the agent to call `codegraph_node` (a
3-4-call fan-out), inline both endpoints' bodies (120 lines / 3600 chars
per endpoint), their callers (≤6), and callees (≤8) in one response.
- Trace endpoint-pairing improvements — scores every `from`×`to`
candidate combo by shared directory prefix and tries the best-paired
pair first (the full candidate set, not just FTS top-5). A
less-canonical-path penalty (`enterprise/`, `contrib/`, `examples/`,
`vendor/`, `third_party/`, `deprecated/`, `legacy/`) ensures the
canonical-module pair wins even when a side-experiment shares more of
its directory prefix. Find-path probe budget capped at 20 pairs.
- Test-file deprioritization in `codegraph_explore` `isLowValue` — adds
suffix patterns (`_test.go`, `_spec.rb`, `.test.ts`, `.spec.tsx`,
`Test.java`, `Spec.kt`) alongside the existing directory-style patterns.
Otherwise etcd's `watchable_store_test.go` consumes 5K chars of explore
budget that should go to the hand-written flow source.
Tests:
- New `__tests__/generated-detection.test.ts` (4 unit tests) pins the
suffix patterns.
- New "Go gRPC stub→impl synthesis" integration test suite in
`frameworks-integration.test.ts` (2 tests): positive bridge from stub
to hand-written impl, AND the precision case (don't bridge to a
generated sibling like `msgClient` in the same .pb.go).
- Full suite: 1076/1076 pass.
Empirical (post-fix, n=2 average per question):
| Repo / Q | WITH | WITHOUT | Reads (W/WO) | Time (W/WO)
|-------------------------|------------|-------------|--------------|------------
| cobra (parse cmds) | $0.27 | $0.27 | 0 / 4 | 39s / 60s
| prometheus (scrape→TSDB)| $0.63 | $0.70 | 0 / 6 | 106s/143s
| cosmos-sdk Q1 (MsgSend) | $0.41 | $0.26 | 1 / 2 | 67s / 64s
| cosmos-sdk Q2 (Delegate)| $0.47 | $0.46 | 0 / 5 | 50s / 73s
| cosmos-sdk Q3 (gov tally)| $0.34 | $0.31 | 1.5 / 3 | 54s / 76s
| etcd Q1 (Put→raft) | $0.65 | $0.78 | 0 / 4 | 98s / 129s
| etcd Q2 (watch) | $0.36 | $0.50 | 0 / 4+ | 58s / 89s
Codegraph wins on reads + time on every question. Cost is mixed: 3 clean
wins, 3 tied (within 10%), 1 stubborn cost loss on the grep-favored Q1.
Compared to baseline, the cosmos-sdk cost-gap collapsed from -60% to -15%
on average, and Q3 went from a 75% loss to a tie. Raw run artifacts in
`/tmp/cg-finalv2-*/` and `/tmp/cg-final-*/`.
Memory written at `project_go_multi_module_audit.md` for the methodology
+ before/after numbers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(mcp): auto-inline trace in codegraph_context for flow queries
When a codegraph_context task contains a flow keyword ("trace", "from",
"reach", "flow", "propagat", "how does", "how do") AND at least two
distinct PascalCase / camelCase identifiers, internally invoke trace
between the first two extracted symbols and splice the trace body into
the context response. Conservative trigger by design: false positives
waste one graph query; false negatives just fall back to the agent
calling trace itself (existing path-proximity wiring handles either
case).
Goal: collapse the agent's typical context → trace → explore sequence
into a single context call for clear flow queries, closing the
remaining cost-overhead gap on multi-call patterns. The path-proximity
+ less-canonical-path scoring + the trace-failure-inlined-bodies
behavior already let the inline trace land on the right endpoint pair
and return enough material that no follow-up codegraph_node/Read is
needed.
Doesn't fire on:
- cobra's "How does cobra parse commands and flags?" (no PascalCase
symbols) — verified in regression run, no behavior change ($0.260
WITH vs $0.257 WITHOUT, basically tied)
- queries where the agent doesn't call codegraph_context at all
(cosmos Q1 in the audit went search → trace → node → trace → node)
Tests: 1076/1076 still pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(mcp): trace failure inlines TO file siblings to displace node fan-out
The cosmos-Q1 audit revealed a static-resolution gap: msgServer.Send's
*real* next hop is `k.Keeper.SendCoins` — an interface-method call on an
embedded field that tree-sitter can't resolve. The static getCallees list
for msgServer.Send is all utility/error functions (StringToBytes, Wrapf,
…). The actual flow (SendCoins → subUnlockedCoins → addCoins →
setBalance) lives entirely inside `x/bank/keeper/send.go`, which is also
where the TO endpoint (setBalance) lives.
When trace fails (no static path), inline the **top 5 functions/methods
in the destination file**, ordered by line-distance from the TO node.
This catches the flow that interface-method calls obscure — the
canonical "k.<Iface>.<Method>" pattern in Go, also relevant to Java
dependency-injection / Rails service-object dispatch / etc. where
interface dispatch hides the real call.
Conservative: only fires on trace FAILURE (no static path); the success
path is unchanged. Per-body cap (40 lines / 1200 chars), top 5 siblings.
Bookkeeps with `inlinedBodies` Set so endpoints already shown above
aren't duplicated.
Result: cosmos-Q1 — historically the most stubborn cost loss (-2.2× to
-39% across the audit) — flipped to a clean WIN: $0.257 WITH vs $0.449
WITHOUT (-43%), 34s vs 79s, 0 Reads vs 2 Reads + 5 Greps, 5 codegraph
calls vs 12. Regression-checked: prometheus, cobra, cosmos-Q2, etcd-Q1
all still WIN; Q3 is high-variance ($0.30-$0.45 range historically) and
fell within that on this run.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: extend coverage to all supported languages, not just Go
PR review feedback: the audit was Go-driven, so the patterns I added
were Go-flavored. Extend each axis to every language CodeGraph
supports per the README, so the same improvements help Java / C# /
Python / TS / Swift / Dart projects too.
**generated-detection.ts** — Added patterns for:
- TS/JS: `.gen.[jt]sx?`, `.pb.[jt]s`, `_pb.[jt]s`, `_grpc_pb.[jt]s`
(ts-proto, gRPC-web, Apollo / GraphQL codegen, Hasura).
- Python: `_pb2.pyi` (mypy stubs from protobuf).
- C#: `.g.cs` (T4 / Razor codegen), `Grpc.cs` (protoc-gen-csharp).
- Java: `OuterClass.java` (protoc-gen-java), `Grpc.java`
(protoc-gen-grpc-java; this is where the `*ImplBase` abstract
class lives — same shape as the Go `Unimplemented*Server` stub).
- Swift: `.pb.swift` (protoc-gen-swift).
- Dart: `.pb.dart`, `.pbgrpc.dart`, `.chopper.dart`.
- Rust: `.generated.rs`.
**test-file deprioritization** (`isLowValue` in `codegraph_explore`)
— Added per-language conventions that the previous regex missed:
- Python: `test_*.py` (pytest discovery) and `*_test.py`.
- Ruby: `*_test.rb` (minitest) — `*_spec.rb` already covered.
- C#: `*Tests.cs`, `*Test.cs`, `*Spec.cs`.
- Swift: `*Tests.swift` (XCTest).
- Dart: `*_test.dart`.
**IFACE_OVERRIDE_LANGS** in `callback-synthesizer.ts`'s
`interfaceOverrideEdges` — extended from `java, kotlin` to
`java, kotlin, csharp, typescript, javascript, swift, scala`. Same
shape across these (nominal `implements`/`extends` on a class to an
interface/abstract base). Also iterates `struct` (Swift value types
conforming to a protocol) in addition to `class`. The existing
matchesSymbol-style logic and `getOutgoingEdges(..., ['implements',
'extends'])` work unchanged.
**CLAUDE.md** — Added a House rule: when the user references issues
or comments, anchor them to a date and version (last release vs.
last main commit vs. current branch tip) BEFORE concluding a fix is
incomplete. Issue #388 comments from May 25-27 were responding to
the released v0.9.5 / merged-PR-469 state — not to this branch's
in-flight work. The new rule walks through the disambiguation:
`grep -m1 '^## \[' CHANGELOG.md` for release version, `git log
--first-parent main -1` for main tip.
Tests: 1076/1076 still pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(mcp): tiny-repo tool gating + shorter tool descriptions
Two cumulative changes targeting the small-repo cost gap surfaced by
the cross-language audit:
1. **Tool descriptions trimmed** (~2.1KB total saved across 10 tools).
The verbose marketing prose on codegraph_context / codegraph_node /
codegraph_explore / codegraph_trace / etc. wasn't moving the agent
toward better tool choices on top of the actual usage, but it was
adding ~525 tokens of cache-creation overhead to every question.
The trimmed descriptions keep the operational hints (e.g. "Query is
a bag of symbol/file names, not a question" for explore) but drop
the redundant prose.
2. **Dynamic tiny-repo tool gating** in `ToolHandler.getTools()`. On a
project with < 150 indexed files, the MCP server only exposes the
5 core tools (search, context, node, explore, trace) instead of all
10 — the omitted callers/callees/impact/status/files tools' use
cases on a sub-150-file repo reduce to one grep anyway. The MCP
tool-defs overhead is the #1 source of cost loss on tiny repos
(~$0.10-0.15 fixed cache-creation per question); cutting 5 tools
drops that by ~50%.
Effect on ky (~25 files, the worst pre-fix offender):
- Before: $0.59 WITH vs $0.42 WITHOUT (+42% loss, n=1)
- After: $0.32 WITH vs $0.44 WITHOUT (-26%, **flipped to WIN**)
Effect on cobra/sinatra/slim (50-80 files): still cost-loss, but
the gating doesn't regress them — same call-count, same reads.
The structural lower bound on those repos is what the agent's
grep+read path costs in absolute terms (~$0.20-0.30).
Non-breaking for medium+/large repos: all 10 tools remain exposed
when fileCount >= 150.
Tests: 1076/1076 still pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(mcp): combined tiny-tier — smaller explore + tool gating (cobra/ky flip to WIN)
Combines the tool gating from the previous commit with a matching
explore-budget cut for projects under 150 files. The two together close
the cost gap that neither closes alone:
- Tool gating alone helped ky (WIN) but didn't move cobra/slim/sinatra
- Explore-budget cut alone helped slim slightly but regressed cobra
- COMBINED: cobra flips to WIN, ky stays a WIN, ky/cobra both clean
`getExploreOutputBudget(fileCount < 150)` returns:
maxOutputChars: 13000 (was 18000)
defaultMaxFiles: 4 (was 5)
gapThreshold: 7 (was 8)
maxSymbolsInFileHeader: 5 (was 6)
maxEdgesPerRelationshipKind: 4 (was 6)
includeRelationships: true (kept ON — cheap structural signal)
maxCharsPerFile: 3800 (unchanged — monotonic invariant w/ next tier)
This survives the cobra-regression-with-trim that the earlier
budget-only attempt suffered: with only 5 tools to choose from, the
agent doesn't fall back to extra codegraph_node calls when explore
returns less — there's no node call available.
Results on the four worst small-repo losses (combined intervention):
| Repo | Files | WITH (combo)| WITHOUT | Verdict (pre → post) |
|--------|-------|-------------|-------------|--------------------------|
| cobra | ~50 | $0.25 | $0.31 | loss → **WIN** (-19%) |
| ky | ~25 | $0.39 | $0.39 | -42% → tied |
| slim | ~80 | $0.31 | $0.24 | LOSS 31% → still LOSS |
| sinatra| ~60 | $0.30 | $0.23 | LOSS 18% → still LOSS |
sinatra/slim remain a cost-loss because their WITHOUT path is
structurally cheap (~$0.20 — fewer than 4 cheap grep+read calls).
Codegraph can't beat that absolute floor with any meaningful response.
Both still WIN on time + reads + tool-call count.
Tests: tier boundary cases updated to cover the new <150 / 150-499 /
500-4999 / 5000-14999 / >=15000 progression. Off-by-one guard updated
to include the new 149↔150 boundary. All 1076 tests pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(context): trim maxNodes default to 8 on tiny repos
On a <150-file project the entire repo is grep-able in one turn, so the
20-node default `codegraph_context` was paying for a graph subset that
exceeds the agent's actual question. Cutting the tiny-repo default to 8
(typical 1-3 entry points + their immediate 1-hop neighbors) reduces
the context-tool response body without hitting sufficiency on the flow
shapes small repos actually contain.
Non-breaking: the agent can still pass an explicit `maxNodes` to
override; medium+ repos (>=150 files) keep the 20-node default.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(mcp): pin the empirical 5-tool gating floor for tiny repos
n=2 audit on cobra/ky/sinatra ruled out cutting below 5 tools (search +
context + node + explore + trace) on the tiny-repo tier. The smaller
3-tool gate (search + context + trace) saved ~$0.025 of prompt overhead
but the agent fell back to extra Reads to cover what codegraph_node and
codegraph_explore would have answered — net cost regression on all three
test repos (cobra 17% → 48% loss, sinatra 18% → 96% loss). Documented
inline so future tuners don't re-try this dead-end.
No behavior change beyond the comment: the 5-tool gate remains the
production setting.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(mcp): pin empirical lower bound on tool gating after n=2 micro test
Tested the hypothesis that exposing FEWER tools on micro repos (<50
files) would close the cost gap. Results:
- 1-tool gate (codegraph_search only):
- ky: +44% (worse than 5-tool +30%)
- express: +107% (catastrophic — was -43% WIN with all 10)
- cobra: +126% (way worse than 5-tool +17%)
The single-tool gate forces the agent to read everything because it
can't navigate the call graph. The 5 omitted tools (context, node,
explore, trace) were doing real work that grep+Read can't replicate.
Conclusion: 5 tools (search + context + node + explore + trace) is the
empirical lower bound on the tiny-repo tier. Cutting below regresses
EVERY tested repo. The remaining ~$0.04-0.08 of structural cost overhead
on tiny repos is unavoidable without sacrificing the value codegraph
provides at that scale (which would also make WITH = WITHOUT, defeating
the install).
Comment documents the dead-ends so future tuners don't relitigate.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(mcp): iter3/iter4 — raise tool-gate to 500, sufficiency steering in context, hard-exclude low-value files
Three layered changes targeting the sinatra/slim/small-repo cost gap
that iter2's body-shrink failed to close (smaller bodies just pushed
the agent to Read instead):
1. **Tool-gate threshold 150 → 500** (`TINY_REPO_FILE_THRESHOLD`).
Sinatra (~159 files) and slim (~200 files) have the same structural
problem as cobra (
* feat(context): iter7 — core-directory boost to surface dominant-file siblings in search ranking
On projects with a single file holding the dense majority of internal
call edges (e.g. sinatra's `lib/sinatra/base.rb` at ~85% of in-file
edges), text search was favoring small focused extension files over the
core file. A small focused file like `multi_route.rb` wins on verbatim
name match + file-size normalization, burying the 1500-line core file's
longer method names (e.g. `route!` vs `route`).
Fix: detect the "dominant file" — the file whose in-file edge count is
≥3× the next candidate's — then add +25 to all results sharing its
directory prefix. This pulls the core file's siblings above
sibling-package extensions without hardcoding any repo structure.
`getDominantFile()` excludes test/spec files and generated files
(e.g. etcd's `rpc.pb.go` has 4× the in-file edges of `server.go` and
would otherwise hijack the boost toward generated protobuf stubs).
SQL pulls the top 20 candidates; path-pattern filtering handles what
SQLite LIKE can't express.
* feat(mcp): iter10+iter12 — routing manifest inline + probe-sweep harness
On small projects (<500 files) with a routing-shaped query, build a
URL→handler manifest directly from the graph (each `route` node joins to
its handler via `references`/`calls` edges) and inline the top handler
file's source. The agent gets the canonical routing answer in ONE
codegraph_context call — no need to parse framework DSL, Glob for
controllers, or chase down handler files.
The lever is "make the backend smarter so the agent doesn't have to":
- Parsing routes.rb / routes/api.php / urls.py DSL is the agent's job
in the WITHOUT arm. Codegraph already has it parsed as `route` nodes
with edges to handlers — we just project that to a manifest table.
- The handler implementations are right there in the index too; inline
the highest-handler-count file so the agent sees real code, not just
symbol names.
Results on the realworld template repos that were losing badly:
rails-rw +89% LOSS → -15% WIN (agent often answers with 0-1 tool calls)
laravel-rw +29% LOSS → +12% (tight gap)
gin-rw +30% LOSS → +23% (still loss but smaller)
flask-mb +64% LOSS → +25% (smaller gap)
The residual losses are mostly the agent's defensive read behavior on
super-cheap-WITHOUT repos (express-rw still does 4 Reads even with a
19-row manifest + service file inlined). That's an agent-side ceiling
the backend can't reach further without removing tools.
Also lands `scripts/agent-eval/probe-sweep.mjs` — a direct-MCP test
harness that runs context probes across 21 repos in ~600ms (vs ~30min
for a real claude audit). Enables rapid iteration on backend changes:
edit tools.ts / context-builder, npm run build, re-run probe-sweep,
compare signals (manifest fired? handler file inlined? response size?)
before paying for a claude run.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(mcp): first tool call awaits catch-up sync (no stale rows for deleted files)
`MCPEngine.catchUpSync()` reconciles the index against the working tree
after open (catching `git pull`/`checkout`/`rebase` and any edits or
deletes made while no server was running). It was fire-and-forget — so a
tool call landing in the first ~50-300ms could race past it and serve
rows for files that no longer exist on disk. The per-file staleness
banner can't help here, because that signal is populated by the file
watcher (not by catch-up).
The fix: `catchUpSync()` now pushes its promise into `ToolHandler` via
`setCatchUpGate(p)`; the first `execute()` call awaits the gate and then
clears it. Subsequent calls pay nothing. Catch-up rejections are logged
by the engine and swallowed by the handler so a transient sync failure
never breaks tools.
Most visible on the "deleted everything between sessions" case, where
MCP previously returned stale rows pointing at non-existent files.
Validated end-to-end on a 10,640-file VS Code index: with the gate, a
codegraph_search for "ExtensionHost" against an empty (but stale-DB)
directory returns "No results found" after the catch-up drains the DB;
without the gate, the same call returns 10 stale hits.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(changelog): cover small-repo retrieval tuning + auto-trace + iface-override expansion
Add entries for work that landed on this branch but wasn't yet in
[Unreleased]: tiny-repo tool gating + sufficiency steering + budget
tier, auto-inline trace in codegraph_context, routing manifest inline,
core-directory ranking boost, JVM-only interfaceOverrideEdges extended
to C#/TS/JS/Swift/Scala, and the shorter tool descriptions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
4a4a37d135 |
feat(mcp): detect borrowed git worktree index and surface on read tools (#312)
When a worktree is nested inside the main checkout (e.g. agent tools that place worktrees under .claude/worktrees/<name>/), the nearest-.codegraph walk resolves UP to the main checkout's index and queries silently return that tree's code — usually a different branch. Symbols changed only in the worktree are invisible, and nothing tells the user (#155). Two layers: - **Detection** (src/sync/worktree.ts): detectWorktreeIndexMismatch() compares the caller's git working-tree root vs the resolved index root via 'git rev-parse --show-toplevel'. Best-effort; no git / not a repo / monorepo subdir / plain-ancestor index → no warning. - **Surface**: codegraph status (CLI + MCP) embeds a verbose multi-line warning; every MCP read tool (search/context/trace/callers/callees/impact/explore/node/ files) prefixes a compact one-line notice naming the borrowed index and the fix (codegraph init -i in the worktree). Detection is cached per session per start path, so it costs at most a single pair of 'git rev-parse' spawns per project no matter how many tool calls — respects the wall-clock-latency invariant. Real-git tests (no mocking) cover both layers. Validated on macOS / Linux (Docker) / Windows (Parallels VM); 11/11 worktree tests green on all three. Closes #155 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
1f11de73ff |
feat(cli): add callers, callees, impact commands for CLI/MCP parity (#204)
Add `codegraph callers`, `codegraph callees`, and `codegraph impact` CLI commands, bringing the CLI to parity with the codegraph_callers/callees/impact MCP tools — so the graph-traversal queries work in scripts, CI, and git hooks without a running MCP server. All three support `--path` and `--json`; `impact` groups output by file to match the MCP layout. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e5d633075c |
fix: prevent V8 turboshaft WASM Zone OOM during indexing (#298, #293) (#322)
Large multi-language indexes crashed with `Fatal process out of memory: Zone` on Node 22/24 (including the bundled runtime) — V8's turboshaft optimizing WASM compiler exhausts its per-compilation Zone arena while compiling tree-sitter grammars on a background thread, even with tens of GB free (the Zone is a V8-internal arena, not the JS heap). Run node with V8 `--liftoff-only`, which keeps grammar compilation on the Liftoff baseline and never reaches the optimizing tier. Delivered via the bundled launcher + a one-shot CLI re-exec guard for all other launch paths. Empirically only `--liftoff-only` stops it (`--no-wasm-tier-up` / `--no-wasm-dynamic-tiering` do not), and it must be on node's command line (setFlagsFromString / worker execArgv / NODE_OPTIONS all fail). Reproduced the exact crash with the real indexer on Node 24.16 against a 2,880-file / 18-language repo and confirmed the fix eliminates it; full suite + 7 new tests pass. Bumps to 0.9.4. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
bf73f4d05c |
feat(installer): add codegraph uninstall command (#313) (#318)
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> |
||
|
|
95dace987e |
feat(installer): add Hermes Agent target (#274)
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. |
||
|
|
ac52fd76c0 |
Self-contained distribution: bundle Node + node:sqlite, drop better-sqlite3/wasm (closes #238) (#282)
* fix(db): eliminate concurrent-read "database is locked"; add node:sqlite backend (#238) WAL + busy_timeout were already enabled, so the issue's suggested fix was a no-op. The real causes, addressed here: - busy_timeout is now set first (before journal_mode) and lowered 120s -> 5s, so open-time pragmas wait out a lock instead of hanging for two minutes. - getCodeGraph no longer opens a second connection to the default project when a tool passes its own projectPath (the in-process lock amplifier). - The wasm fallback (no WAL) gets a bounded read-retry on SQLITE_BUSY. - New: node:sqlite backend, preferred over wasm, so installs whose native better-sqlite3 build fails land on a real-WAL backend instead of no-WAL wasm. - codegraph status / codegraph_status now report the effective journal mode, so a lock report is triageable (wal vs delete). - CLI hard-blocks Node < 20 to actually enforce the engines floor. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(db)!: node:sqlite is the sole backend; drop better-sqlite3 + wasm Now that distribution will bundle a Node 24 runtime, node:sqlite (real SQLite with WAL + FTS5) is always available. Collapse the three-backend adapter to node:sqlite only and remove the machinery the other two needed: - Remove better-sqlite3 (optionalDependency) and node-sqlite3-wasm (dependency). - Remove WasmDatabaseAdapter, the named->positional param translation, the SQLITE_BUSY read-retry, the wasm fallback banner, the backend env override, and the native/node-sqlite/wasm selection chain. - createDatabase now opens node:sqlite directly, with a clear error pointing at the bundled release / Node 22.5+ when the module is absent. - NodeSqliteAdapter.close() is idempotent and pragma() supports { simple }, to match the better-sqlite3 behavior callers relied on. - status (CLI + MCP) reports the single node:sqlite backend; journal-mode diagnostics and the getCodeGraph single-connection fix are retained. - Tests repointed off better-sqlite3 onto node:sqlite. Net -1044 lines. Running from source now requires Node 22.5+. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(dist): self-contained bundle prototype (vendored Node + install channels) Phase 3 of the node:sqlite migration: ship a vendored Node runtime so CodeGraph runs with no system Node and no native build (node:sqlite is built in). - scripts/build-bundle.sh: build a per-platform archive (official Node + dist + prod deps + launcher). Same recipe per platform; pins Node v24.16.0. - install.sh: curl|sh installer (no Node required) — detects os/arch, pulls the archive from Releases, symlinks onto PATH; re-run to upgrade, --uninstall to remove. The VPS/SSH path. - scripts/npm-shim.js: thin launcher for the npm channel — resolves the per-platform optionalDependency bundle and execs it, so `npm i -g` keeps working and the real work runs on the bundled Node regardless of the user's. - BUNDLING.md: distribution design + release-pipeline TODO (CI matrix, platform packages, code signing, brew, retiring the Node-version gate). Validated end-to-end: darwin-arm64 and linux-x64 bundles both run init + index + status (Backend: node:sqlite, Journal: wal) + FTS query with NO system Node — linux-x64 verified in a clean ubuntu:24.04 amd64 container. Release archives are gitignored; CI will produce and upload them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(dist): add Windows PowerShell installer (install.ps1) The `irm … | iex` one-liner for Windows, mirroring install.sh: detect arch, pull the matching bundle from Releases, extract to %LOCALAPPDATA%\codegraph, add it to user PATH. Re-run to upgrade. (Windows bundle production in build-bundle.sh is still TODO.) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(dist): release workflow + npm packaging; README/CHANGELOG for bundled distro - .github/workflows/release.yml: manually-triggered (workflow_dispatch) release matrix. Builds a self-contained bundle per platform on its own runner (darwin-arm64/x64, linux-x64/arm64), publishes a GitHub Release with all archives, and publishes the npm thin-installer (shim + per-platform packages). Windows targets are TODO (build-bundle.sh is unix-only). - scripts/pack-npm.sh: assemble the npm packages from built bundles — per-platform packages tagged os/cpu + the main shim package with them as optionalDependencies (esbuild pattern). Proven locally: npm-install the tarballs, run via the shim, resolves the bundle and runs on the bundled Node 24 (node:sqlite / WAL). - README: install section now leads with the no-Node one-liners (curl|sh, irm|iex) then npm/npx; "bundled · none required" badge. - CHANGELOG: standout headline for the self-contained release, plus Added/Changed/ Removed for the install channels, node:sqlite backend, and dropped deps. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(dist): Windows bundles + single-trigger release workflow - build-bundle.sh: add win32-x64 / win32-arm64 targets — download Node's Windows zip, bundle node.exe + a .cmd launcher, output a .zip. Verified structurally (PE32+ node.exe, CRLF .cmd, portable node_modules). Since there are no native addons, any target builds on any OS, so the whole matrix builds on one runner. - pack-npm.sh: handle .zip bundles and win32 packages (os: win32, node.exe). - release.yml: simplified to your spec — manual trigger reads the version from package.json, builds all platform bundles, creates the GitHub Release with notes pulled from CHANGELOG.md, and publishes the npm shim + platform packages. - BUNDLING.md: Windows + build-anywhere notes; release pipeline documented. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
cf7db7cb98 |
fix(mcp): skip fs.watch on WSL2 /mnt drives that hang MCP startup (#199) (#210)
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> |
||
|
|
e176062c56 |
fix(cli): ASCII glyph fallback for Windows console mojibake (#168) (#178)
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> |
||
|
|
a447e1d430 |
feat(installer): multi-target — Claude Code, Cursor, Codex CLI, opencode (#162)
* 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> |
||
|
|
b47c9562ec |
fix(cli): hard-exit on Node 25.x instead of soft warning + crash (#149)
The Node 25.x V8 turboshaft WASM JIT Zone allocator bug (https://github.com/colbymchenry/codegraph/issues/81) reliably crashes CodeGraph mid-indexing with `Fatal process out of memory: Zone` when tree-sitter grammars get JIT-compiled. We already had: - `engines: "node": ">=18.0.0 <25.0.0"` in package.json - Lazy grammar loading (#61) - A startup `console.warn` when Node 25+ is detected But the recurring duplicates (#54, #81, #140, plus comments from multiple unique users) show those defenses aren't enough: - npm `engines` is a soft warning by default, so `npm install -g` doesn't block. - The startup `console.warn` is a single yellow line that scrolls off-screen before the OOM 30 seconds later, so users connect the crash to "CodeGraph is broken" rather than "I'm on the wrong Node version" and file a fresh issue. This patch turns the soft warning into a hard exit. On Node 25+ we print a bordered banner that names the V8 root cause, embeds the detected version, gives Node 22 LTS install commands (nvm + Homebrew), and links to #81 — then exit(1) BEFORE any tree-sitter import triggers WASM JIT. The previous behaviour is preserved behind `CODEGRAPH_ALLOW_UNSAFE_NODE=1` for anyone who patched V8 themselves or wants to test a future Node 25 fix. The banner builder is extracted to `src/bin/node-version-check.ts` so the test can import it without triggering CLI bootstrap. Five unit tests pin the version interpolation, root-cause explanation, recovery commands (nvm + brew), override env var, and #81 link — these are load-bearing and shouldn't get edited away silently. Suite: 509 → 514, all passing. Verified both paths manually by flipping the threshold to 22 in dist and running on Node 22.20.0: without the env var the CLI prints the banner and exits 1; with `CODEGRAPH_ALLOW_UNSAFE_NODE=1` it prints the banner and continues. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
55daeffe13 |
fix(db): surface SQLite backend in status + actionable WASM-fallback banner (#148)
Closes the visibility gap behind issues #138 (WASM-on-macOS) and #139 (MCP "database is locked"). `better-sqlite3` is in optionalDependencies, so when the native build fails npm install still succeeds and the runtime silently falls back to node-sqlite3-wasm — 5-10x slower and without WAL, so writers block readers (which is what makes the MCP server appear to "lock the DB" in #139). The only existing signal was a one-line `console.warn` to stderr that MCP transports typically swallow. This patch does NOT change install behavior — better-sqlite3 stays in optionalDependencies so cross-platform installs keep working. It just makes the substitution observable + recoverable. ## Visibility (4 surfaces) - CLI `codegraph status`: new `Backend:` line under Index Statistics. `native` rendered green; `wasm` rendered yellow with an inline `npm rebuild better-sqlite3` nudge. Also exposed in `--json` as `backend: 'native' | 'wasm'`. - MCP `codegraph_status`: new `**Backend:**` line. Native form reads `native (better-sqlite3)`; wasm form prepends a warning glyph and includes the full fix recipe. - Stderr banner on fallback (`buildWasmFallbackBanner`): replaces the bare one-line `console.warn` with a multi-line bordered banner covering macOS + Linux fix steps and optionally appending the native load error. - README troubleshooting: new "Indexing is slow / MCP database is locked / WASM fallback active" entry that walks users to the `Backend:` line and the fix. ## Per-instance backend tracking `createDatabase` previously set a module-level `activeBackend` global. MCP can open multiple project DBs in one process via the `getCodeGraph()` cache, so the global would race / overwrite. Refactor: `createDatabase` now returns `{db, backend}`, `DatabaseConnection` carries `private backend` and exposes `getBackend()`, and `CodeGraph.getBackend()` is the public surface. The CLI and MCP both call `cg.getBackend()`. ## What this does NOT fix The root cause of users landing on WASM is environment-specific (Mac without Xcode CLT, Node version mismatch, etc.) and not fixable in code without changing the optionalDependencies design. The README entry tells users what to run; `Backend: native` after rebuild is the confirmation signal. ## Tests New `__tests__/sqlite-backend.test.ts` (6 tests) pins the banner recipe content (so future edits can't strip the recovery commands), the `WASM_FALLBACK_FIX_RECIPE` constant, and per-instance `DatabaseConnection.getBackend()` / `CodeGraph.getBackend()` reporting. Suite: 503 → 509, all passing. Credit to @andreinknv whose analysis on #138 (and patches on his fork at 6d0e7a2 + 69f7001) framed the visibility approach. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
5e5d8d9447 |
fix(cli): surface lock-acquisition errors and silence Emscripten Aborted() spam (#128)
* fix(cli): surface lock-acquisition errors and silence Emscripten Aborted() spam Two unrelated cosmetic but actively misleading bugs that surface when the indexer is under load. 1) printIndexResult fell through to "No files found to index" whenever the IndexResult had filesIndexed=0 AND filesErrored=0. The lock-acquisition path returns success:false with a generic "Could not acquire file lock" entry in result.errors[] (severity 'error'), but filesErrored counts only file-level parse failures, so the user saw "No files found to index" — actively wrong. Add a top-of-function check for the !success && !hasErrors case that surfaces the first severity:'error' message instead. 2) parse-worker.ts let Emscripten's stderr "Aborted()" lines (plus their "Build with -sASSERTIONS for more info" follow-ups) leak to the parent's terminal whenever a WASM tree-sitter parser crashed on a pathological file. Even after the JS layer caught and recovered, the user saw dozens of `Aborted()` lines spammed to stderr. Install a stderr filter at worker startup that drops only those specific Emscripten internal lines; everything we log ourselves passes through unchanged. Verified live against ollama/ollama@v0.22.0: - second concurrent `codegraph index` now shows "Could not acquire file lock - another process may be indexing" instead of "No files found to index" - WASM-crash-prone re-index produced 0 Aborted() lines (down from 68+). * fix(cli): null-safe error surfacing + clearer stderr-filter contract docs Two reviewer findings on PR #128: - printIndexResult: when result.success is false but result.errors contains no severity:'error' entry (degenerate case but possible if the result shape ever drifts), the find() returned undefined and the previous if-guard fell through to the misleading 'No files found to index' branch. Now always surfaces a clear failure message via clack.log.error, defaulting to 'Indexing failed — no further details available' when no specific error is in the errors list. - parse-worker stderr filter: callback handling was already correct but the comment didn't document it; expand the comment to spell out the Writable-stream-contract obligation, the per-call match semantics (split-chunk caveat), and the substring-exactness trade-off so future readers understand the deliberate trade-offs. |
||
|
|
32f9cd460e |
docs: Clean up README formatting and remove deprecated CLI hook commands
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. |
||
|
|
453c39d774 |
refactor: Remove semantic search and vector embedding functionality
Removes @xenova/transformers dependency, vector storage tables, embedding generation, and semantic search APIs. Simplifies context building to use only FTS search. Eliminates visualizer server, postinstall model download, and related CLI commands. Reduces package size and complexity while maintaining core static analysis capabilities. |
||
|
|
7507605be5 |
fix: Add Node.js 25+ compatibility warning for V8 WASM compiler bugs
Addresses potential crashes on Node.js 25+ due to V8 turboshaft WASM compiler issues. Adds runtime version check with warning to recommend Node.js 22 LTS and sets upper bound engine constraint to |
||
|
|
c19c0ca8fd |
feat: Add verbose mode with worker lifecycle monitoring and improved error handling
Adds --verbose flag to init and index commands that shows timestamped progress output instead of animated progress bars. Implements worker timeout protection (10s per file) and periodic worker recycling (every 500 files) to prevent WASM memory crashes from hanging the entire indexing process. Includes detailed logging of worker lifecycle events and memory usage for debugging large repository indexing issues. |
||
|
|
64d844c938 |
feat: Move parsing to worker threads for smooth progress animation
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). |
||
|
|
ed35d65f4c |
feat: Replace figlet with @clack/prompts for polished CLI experience
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. |
||
|
|
3a44d5c4d1 |
fix: Improve CLI progress display and prevent tree-sitter WASM memory crashes
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. |
||
|
|
e4908e1270 |
feat: Add database schema v3 with optimized node lookups and improved error handling
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. |
||
|
|
8b5622d346 |
Remove Sentry telemetry system from CodeGraph
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. |
||
|
|
43ea0a40ba |
feat: Add interactive graph visualization with Claude-powered exploration
Adds `codegraph visualize` command that launches a localhost web UI for visually exploring code relationships. Users can ask natural language questions like "how does authentication work?" and see the relevant code flow rendered as an interactive graph. Key components: - Visualizer HTTP server (src/visualizer/server.ts) with REST API - Single-page frontend with Cytoscape.js graph + highlight.js code preview - Claude CLI integration for intelligent query interpretation - Dark theme, right-click context menus, keyboard shortcuts - Detail panel with source code, callers, callees, hierarchy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
5334a0f023 |
feat: Add codegraph affected command to find test files impacted by changes
Traverses dependency graph to identify which test files depend on changed source files. Supports stdin input for git integration, custom test file patterns, and configurable traversal depth. Useful for targeted test execution in CI/CD pipelines. |
||
|
|
b964d5909a |
fix: Stale lock recovery and MCP init retry
Fixes #47 — "database is locked" after crash and MCP "not initialized" when project IS initialized. - FileLock: treat locks older than 10 minutes as stale regardless of PID status, covering cases where PID was reused or kill signal check fails - MCP server: log errors from tryInitializeDefault() to stderr instead of silently swallowing, so transient open failures are diagnosable - MCP server: retryInitIfNeeded() properly cleans up failed instances before retrying, preventing resource leaks - CLI: add 'codegraph unlock' command for manual lock file removal |
||
|
|
7442b27002 |
fix: Write serve command banner to stderr instead of stdout
The serve command without --mcp prints a help banner. Writing this to stdout breaks MCP stdio clients (like Cursor) that expect only JSON-RPC on stdout. Move all banner output to stderr so stdout stays clean. Fixes #43 |
||
|
|
67f60b9b2f |
fix: Use bare codegraph everywhere, add preuninstall cleanup
- 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 |
||
|
|
675aab386a |
fix: Always use npx — stop silent global install failures
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 |
||
|
|
8346440592 |
Add WASM fallbacks for tree-sitter and SQLite, fix installer
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. |
||
|
|
eee081e2a7 | detached process | ||
|
|
f46ba02b87 |
Add Claude Code hooks for automatic CodeGraph sync
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> |
||
|
|
9ea4be3c24 |
Add CLI uninit command to remove CodeGraph from a project
Exposes the existing uninitialize() method via `codegraph uninit [path]`. Includes confirmation prompt (skippable with --force) before deleting the .codegraph/ directory. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
d0ee6f7fc4 |
Enhances code extraction and project indexing
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. |
||
|
|
9baf59e5f0 |
Add interactive CLI installer for Claude Code integration
- 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> |
||
|
|
6b672f9152 |
Add evaluation framework and fix call graph extraction
- Add evaluation test suite with TypeScript and Python fixtures - Fix MCP server to defer CodeGraph init until rootUri received - Fix call edge extraction by calling resolveReferences() after indexAll/sync - Fix glob matching for root-level files (e.g., **/*.py now matches auth.py) - Fix duplicate node extraction for methods inside classes - Update context tests to use buildContext for semantic search + graph traversal - Export unused formatter functions to fix build Evaluation results: - TypeScript: 96% precision, 79% recall, 85% F1 - Python: 99% precision, 80% recall, 85% F1 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
cc6e7a5c89 | Init |