Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
a877aa3
docs(upstream): bootstrap v1.5 sync provenance
sunerpy Jul 24, 2026
06d315e
test(release): add workspace version gate
sunerpy Jul 24, 2026
745c5e7
docs(release): record workspace version gate evidence
sunerpy Jul 24, 2026
10352ba
fix(release): pin exact cargo metadata argv and harden lock trap
sunerpy Jul 24, 2026
31db6ab
test(index): add Batch M black-box Red for isolated v2 namespace
sunerpy Jul 24, 2026
b5a66f2
feat(core): add IndexPaths v2 namespace path authority
sunerpy Jul 24, 2026
8aeefc4
feat(index): route init to isolated .codegraph-v2 namespace via Index…
sunerpy Jul 25, 2026
f6ff9e2
fix(index): enforce fail-closed IndexPaths in the v2 data plane
sunerpy Jul 25, 2026
7652267
fix(index): close IndexPaths path-authority verification defects
sunerpy Jul 25, 2026
7d95634
fix(index): prove byte nonmutation and surface invalid CODEGRAPH_DIR …
sunerpy Jul 25, 2026
a6eac9e
fix(index): make the byte-nonmutation oracle fail-closed
sunerpy Jul 25, 2026
4d5a39c
feat(index): add read-only state classifier
sunerpy Jul 25, 2026
224e762
fix(index): harden read-only state classification
sunerpy Jul 25, 2026
ba399c4
docs(upstream-sync): format the Batch M ledger and correct its final …
sunerpy Jul 25, 2026
b772e0f
feat(store): add reusable index lease capability
sunerpy Jul 25, 2026
8c19bce
fix(store): harden index lease identity checks
sunerpy Jul 25, 2026
3af74bf
docs(upstream-sync): record the authoritative Batch M lease final gate
sunerpy Jul 25, 2026
8bce3de
fix(store): enforce atomic state publisher protocol
sunerpy Jul 25, 2026
a600c80
feat(store): add state-gated Store opens
sunerpy Jul 25, 2026
f5c57f5
fix(store): harden state-gated artifact checks
sunerpy Jul 25, 2026
6a175a5
feat(store): finalize full rebuild before publication
sunerpy Jul 25, 2026
c666381
feat(sync): migrate outdated indexes during incremental sync
sunerpy Jul 25, 2026
5c801dd
feat(store): make uninit crash recoverable
sunerpy Jul 25, 2026
ead6c26
test(store): cover writer process lifecycle
sunerpy Jul 26, 2026
3863c26
fix(watch): retain watcher trigger paths
sunerpy Jul 26, 2026
3ea02c5
test(store): cover lease owner drop ordering
sunerpy Jul 26, 2026
fdb2df0
test(store): prove read opens never migrate
sunerpy Jul 26, 2026
4aa6c38
fix(watch): resync removed directories
sunerpy Jul 26, 2026
496afa2
feat(core): add project-scoped config loading
sunerpy Jul 26, 2026
a8c0f5c
docs(upstream-sync): record Batch M acceptance evidence
sunerpy Jul 26, 2026
00a755d
fix(mcp): retain reader leases through requests
sunerpy Jul 26, 2026
25b78a8
test(index): add verified v0.40.4 legacy fixture
sunerpy Jul 26, 2026
2442111
test(mcp): prove long-lived server releases handles per request
sunerpy Jul 26, 2026
73833fa
test(mcp): prove a failed engine open is not cached
sunerpy Jul 26, 2026
b71988c
feat(config): scope configuration to the addressed project
sunerpy Jul 26, 2026
9102415
docs(upstream-sync): record project-scoped config evidence
sunerpy Jul 26, 2026
df86a5a
feat(daemon): drain the daemon under uninit through an owner-bound co…
sunerpy Jul 27, 2026
f691415
fix(daemon): remove the rendezvous socket before releasing its owners…
sunerpy Jul 27, 2026
8c66848
revert(store): drop the out-of-scope daemon-startup sidecar relaxation
sunerpy Jul 27, 2026
721709a
fix(store): recover a killed daemon's leftover WAL on startup
sunerpy Jul 27, 2026
288d892
docs(cli): restore the daemon-startup gate doc comment
sunerpy Jul 27, 2026
1839504
fix(cpp): resolve explicit operator calls to the operator method
sunerpy Jul 27, 2026
302aa40
fix(cpp): strip template args from out-of-line method receiver qualif…
sunerpy Jul 27, 2026
bc36c6e
fix(cpp): compose namespace prefix into out-of-line method qualified …
sunerpy Jul 27, 2026
e95072c
fix(c): blank leading attribute macros so functions index under real …
sunerpy Jul 27, 2026
87a46dc
fix(c): blank only provably attribute-like leading macros
sunerpy Jul 27, 2026
2a6af2e
fix(resolution): calls through an imported singleton resolve to the m…
sunerpy Jul 27, 2026
285d591
fix(resolution): literal-receiver builtins and nested locals stop fab…
sunerpy Jul 27, 2026
29f635b
fix(resolution): key resolved-ref cleanup on the row id so sibling ca…
sunerpy Jul 28, 2026
8c80331
fix(retrieval): score non-ASCII query words so their definers outrank…
sunerpy Jul 28, 2026
b20260a
fix(retrieval): seed multi-segment field-name queries with their segm…
sunerpy Jul 28, 2026
efc6fcd
fix(graph): guard find_path with an enqueue-once set and expose its q…
sunerpy Jul 28, 2026
7d0253b
fix(cli): node <symbol> --file pins one overload and returns its sour…
sunerpy Jul 28, 2026
b7ff1f8
fix(resolve): bound the React Route opening-tag scan to the tag itself
sunerpy Jul 28, 2026
1e1d259
fix(extract): close each DFM object at its own matching end line
sunerpy Jul 28, 2026
063604d
fix(extract): recognize both mapper dialects and resolve qualified re…
sunerpy Jul 28, 2026
ecd3641
feat(release): publish SHA256SUMS and verify it in both installers
sunerpy Jul 28, 2026
5c585ec
test(bench): parse KNOWN_DIFFS.md fail-closed and wire it into the go…
sunerpy Jul 28, 2026
fc23a4a
ci(release): gate release asset-name drift across workflow and instal…
sunerpy Jul 28, 2026
f80ee4f
docs(godot): record the gdext rejection and engine-free alternatives
sunerpy Jul 28, 2026
d897fdc
fix(ci): require every gated job to conclude success
sunerpy Jul 28, 2026
33da2f5
fix(store): detect SQLite sidecars losslessly on non-UTF-8 paths
sunerpy Jul 28, 2026
1a8c13d
docs: point the index, config and rendezvous paths at .codegraph-v2
sunerpy Jul 28, 2026
963c12a
fix(resolve): bound the React data-router route-object walk to its ow…
sunerpy Jul 28, 2026
5789dd2
docs(godot): correct the gdext build-time dependency claim
sunerpy Jul 28, 2026
6b684e6
docs: correct the KNOWN_DIFFS path and the retired index root
sunerpy Jul 28, 2026
76535be
docs: record the stale-heal pid-before-socket deletion order as a def…
sunerpy Jul 29, 2026
82029e3
test(cli,watch): serialize env-mutating tests behind one lock per crate
sunerpy Jul 29, 2026
0922230
fix(daemon): claim the rendezvous before healing its stale socket
sunerpy Jul 29, 2026
fa297e2
fix(store): drop needless return in cfg(windows) alias checks
sunerpy Jul 29, 2026
706d36a
fix(cli): gate the lease-lifetime metadata helper off windows
sunerpy Jul 29, 2026
a131aee
fix(daemon): decide a zero drain budget from the pre-signal session c…
sunerpy Jul 29, 2026
eb4b516
test(daemon): scope the rendezvous socket-file assertions to unix
sunerpy Jul 29, 2026
c7800ca
docs: record the three PR #173 CI failures and their root causes
sunerpy Jul 29, 2026
b71a5f1
fix(store): classify windows directory flush denial as unsupported
sunerpy Jul 29, 2026
5845f11
fix(ci): emit the legacy fixture path in the consumer's path domain
sunerpy Jul 29, 2026
c126f36
test(cli): build the nested status project path in the native separat…
sunerpy Jul 29, 2026
955b89b
test(daemon): serialize the idle-window env against the detached spawn
sunerpy Jul 29, 2026
a0315da
docs: record the round-six windows path and daemon env-race diagnoses
sunerpy Jul 29, 2026
47ee705
fix(daemon): bound the proxy teardown by owed replies, not peer close
sunerpy Jul 29, 2026
acfc401
docs: record the round-seven windows proxy teardown diagnosis
sunerpy Jul 29, 2026
9a04581
docs: record the round-seven windows proxy teardown diagnosis
sunerpy Jul 29, 2026
478575d
docs: record the codebuild windows verification of the proxy teardown…
sunerpy Jul 29, 2026
2215b30
test(store): tolerate windows mandatory lock refusal in snapshot oracles
sunerpy Jul 30, 2026
344699a
docs: record the round-eight windows snapshot lock-violation diagnosis
sunerpy Jul 30, 2026
8389c9e
test(store): assert lock length when windows refuses a locked-range read
sunerpy Jul 30, 2026
cad3577
docs: record the codebuild round-eight confirmation and the tenth layer
sunerpy Jul 30, 2026
cb3e168
test(store): derive temp directory names from a monotonic per-process…
sunerpy Jul 30, 2026
752ea01
test(cli): derive installer temp directory names from a monotonic serial
sunerpy Jul 30, 2026
ff9bf9f
docs: record the round-nine windows temp-name collision diagnosis
sunerpy Jul 30, 2026
a23c37e
docs: record the first windows-green codebuild run for rounds eight a…
sunerpy Jul 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
# 1. cargo fmt --all --check (rustfmt)
# 2. cargo clippy ... -D warnings (lint, warnings are errors)
# 3. cargo test --workspace (incl. golden oracle + sync equivalence)
# 4. scripts/guardrail.sh (no AI / vector / LLM crates)
# 4. scripts/guardrail.sh (no AI/vector/LLM crates + no release
# asset-name drift)
#
# Enable once per clone:
# make hooks # == git config core.hooksPath .githooks
Expand Down Expand Up @@ -45,11 +46,12 @@ if ! cargo test --workspace; then
exit 1
fi

echo "==> [4/4] scripts/guardrail.sh (no AI/vector/LLM crates)"
echo "==> [4/4] scripts/guardrail.sh (no AI/vector/LLM crates + asset-name drift)"
if ! bash scripts/guardrail.sh; then
echo "" >&2
echo "❌ Scope guardrail failed: a forbidden AI/vector/LLM crate was detected." >&2
echo " This project is deterministic and ML-free by design. Push aborted." >&2
echo "❌ Scope guardrail failed: a forbidden AI/vector/LLM crate was detected," >&2
echo " or the release workflow and the installers disagree on asset names." >&2
echo " Read the diagnostics above; push aborted." >&2
exit 1
fi

Expand Down
123 changes: 118 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,40 @@ jobs:
- name: Clippy lint
run: cargo clippy --workspace --all-targets -- -D warnings

# Materializes the frozen v0.40.4 legacy CLI for the Batch M legacy
# compatibility tests, using THIS host's NATIVE asset (linux x86_64). The
# script verifies the archive digest, the extracted executable digest, and
# the real `--version` before exporting the path. A network or digest
# failure fails the job here — legacy tests are never skipped.
- name: Prepare legacy v0.40.4 fixture (native linux asset)
run: echo "CODEGRAPH_LEGACY_BIN=$(bash scripts/setup-legacy-fixture.sh)" >> "$GITHUB_ENV"

- name: Run tests (incl. golden oracle + sync equivalence)
run: cargo test --workspace

# Windows cross-check is intentionally omitted on Ubuntu: target C deps
# (tree-sitter/libsqlite3-sys/ring) require MSVC tooling. Runtime
# correctness is gated by the native windows-latest job below.

- name: Scope guardrail (no AI / vector / LLM crates)
# The guardrail's asset-name drift gate parses release-please.yml with
# yaml.safe_load, so PyYAML must be importable. Idempotent: installs only
# when the runner image does not already ship it. A missing PyYAML must
# never degrade the gate into a silent skip — the gate itself exits nonzero
# in that case, and this step fails loudly first.
- name: Ensure PyYAML (asset-name drift gate)
run: |
python3 -c 'import yaml' \
|| python3 -m pip install --break-system-packages PyYAML \
|| python3 -m pip install PyYAML

# The CI-gate integrity block of the guardrail runs the shipped `ci-success`
# step body over a synthetic needs context, which needs jq. Present on
# ubuntu-latest; asserted here so a missing jq fails loudly rather than
# letting the gate degrade.
- name: Ensure jq (CI gate-integrity check)
run: jq --version

- name: Scope guardrail (no AI/vector/LLM crates + release asset-name drift + CI gate integrity)
run: bash scripts/guardrail.sh

windows:
Expand All @@ -69,9 +95,27 @@ jobs:
# codegraph-bench is a Unix-only dev harness (publish=false); excluded from the Windows job.
run: cargo clippy --workspace --exclude codegraph-bench --all-targets -- -D warnings

# Same fixture step, but the script selects THIS host's NATIVE asset
# (windows x86_64 .zip). There is no cross-execution and no emulation:
# the Windows legacy proof runs only here, on a real Windows runner.
- name: Prepare legacy v0.40.4 fixture (native windows asset)
shell: bash
run: echo "CODEGRAPH_LEGACY_BIN=$(bash scripts/setup-legacy-fixture.sh)" >> "$GITHUB_ENV"

- name: Run tests
run: cargo test --workspace --exclude codegraph-bench

# Batch M item 16 acceptance: ONE long-lived shipped `serve --mcp` process
# releases every SQLite handle when a request completes, so the v2 main
# database can be REPLACED (MoveFileEx + REPLACE_EXISTING) without the
# compatibility close seam, and the next request serves only the
# replacement graph. The replacement rename is the Windows-specific handle
# proof (a retained handle makes it fail with a sharing violation), so this
# target is selected EXPLICITLY here — never compile-only, never skipped —
# even though the workspace run above already covers it.
- name: Run Batch M item 16 native Windows replacement acceptance
run: cargo test -p codegraph-rs --test batch_m_long_lived_mcp

audit:
name: Security Audit
runs-on: ubuntu-latest
Expand Down Expand Up @@ -133,18 +177,87 @@ jobs:
# to repo Secrets to use it; harmless/ignored if unset on a public repo.
token: ${{ secrets.CODECOV_TOKEN }}

# ci-success is the SINGLE required status check for branch protection AND the
# job the release workflow's `verify-ci` waits on before a release may leave
# draft. It must therefore be a STRICT gate: it passes only when every required
# job's result is exactly `success`.
#
# WHY strict (the bug this shape fixes): `needs.<job>.result` can be `success`,
# `failure`, `cancelled`, or `skipped`. The previous check rejected only
# `failure`, so `cancelled` and `skipped` both PASSED. Combined with
# `cancel-in-progress: true` above, a run cancelled by a newer push could still
# conclude `CI Success` — and release-please.yml's `verify-ci` gates the release
# on exactly that job. A release could then be cut on a run whose tests never
# finished. Anything other than `success` now fails, including any result value
# GitHub may add in the future (unknown values are not silently tolerated).
#
# WHY the results are read from `toJSON(needs)` rather than named one by one:
# the step body hardcodes no job name, so adding a job to `needs:` below
# automatically makes it required with no change to the script. GitHub Actions
# cannot make this fully automatic — the `needs` context contains ONLY the jobs
# listed in `needs:`, so a new job that is never added there is invisible to
# this gate no matter how the expression is written. That gap is closed OUTSIDE
# the workflow, loudly: `scripts/check-ci-gate.sh` (run by scripts/guardrail.sh
# in `make ci`, the pre-push hook, and the CI `test` job) asserts that
# `ci-success.needs` equals every job in this file minus an explicit
# informational allow-list, so forgetting to list a new job turns CI red
# instead of silently narrowing the gate.
ci-success:
name: CI Success
runs-on: ubuntu-latest
if: always()
# NOTE: `coverage` is intentionally NOT listed here — coverage is
# informational and must never gate a merge.
# informational (codecov.yml sets `informational: true`, baseline ~72% vs an
# aspirational 95% target) and must never gate a merge or a release. It is
# the ONLY allowed exclusion; scripts/check-ci-gate.sh enforces that, and
# also enforces that codecov.yml still marks coverage informational, so the
# exclusion can never outlive its justification.
needs: [test, audit, windows]
steps:
- name: Check job status
env:
# The whole needs context as JSON: {"test":{"result":"success",...},...}
NEEDS_JSON: ${{ toJSON(needs) }}
run: |
if [[ "${{ needs.test.result }}" == "failure" || "${{ needs.audit.result }}" == "failure" || "${{ needs.windows.result }}" == "failure" ]]; then
echo "❌ CI failed"
set -euo pipefail

if [ -z "${NEEDS_JSON:-}" ]; then
echo "::error title=CI gate::the needs context was empty; cannot prove any required job succeeded — failing closed."
exit 1
fi
if ! printf '%s' "$NEEDS_JSON" | jq -e 'type == "object" and length > 0' > /dev/null 2>&1; then
echo "::error title=CI gate::the needs context did not parse as a non-empty JSON object — failing closed."
printf 'needs context was: %s\n' "$NEEDS_JSON"
exit 1
fi

# One row per required job: "<job>\t<result>". A job whose `result` key
# is absent renders as <missing> and fails, never passes.
mapfile -t rows < <(
printf '%s' "$NEEDS_JSON" \
| jq -r 'to_entries | sort_by(.key)[] | "\(.key)\t\(.value.result // "<missing>")"'
)
if [ "${#rows[@]}" -eq 0 ]; then
echo "::error title=CI gate::no required jobs were found in the needs context — failing closed."
exit 1
fi

echo "Required job results (only 'success' passes):"
offenders=0
for row in "${rows[@]}"; do
job="${row%%$'\t'*}"
result="${row#*$'\t'}"
if [ "$result" = "success" ]; then
printf ' ✅ %-12s %s\n' "$job" "$result"
else
printf ' ❌ %-12s %s\n' "$job" "$result"
echo "::error title=CI gate::required job '${job}' concluded '${result}', not 'success'."
offenders=$((offenders + 1))
fi
done

if [ "$offenders" -ne 0 ]; then
echo "❌ CI failed: ${offenders} of ${#rows[@]} required job(s) did not conclude 'success' (see the ❌ rows above)."
exit 1
fi
echo "✅ CI passed"
echo "✅ CI passed: all ${#rows[@]} required job(s) concluded 'success'."
25 changes: 25 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,30 @@ jobs:
path: dist
merge-multiple: true

# Checksums are computed HERE, from the very same merged `dist/` that the
# attach step below uploads, so the sums provably describe the uploaded
# bytes. Determinism: `LC_ALL=C sort` on basenames gives a byte-order,
# locale-independent ordering; sha256sum is run with cwd=dist so each line
# carries the bare asset name (no `dist/` prefix); output is LF-only.
- name: Generate SHA256SUMS
shell: bash
working-directory: dist
run: |
set -euo pipefail
shopt -s nullglob
archives=(*.tar.gz *.zip)
if [ "${#archives[@]}" -eq 0 ]; then
echo "::error::no release archives found in dist/" >&2
exit 1
fi
mapfile -t sorted < <(printf '%s\n' "${archives[@]}" | LC_ALL=C sort)
: > SHA256SUMS
for archive in "${sorted[@]}"; do
sha256sum "$archive" >> SHA256SUMS
done
echo "--- SHA256SUMS ---"
cat SHA256SUMS

- name: Generate release notes
uses: orhun/git-cliff-action@v4
with:
Expand All @@ -321,6 +345,7 @@ jobs:
files: |
dist/*.tar.gz
dist/*.zip
dist/SHA256SUMS
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand Down
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ target/llvm-cov/

# Per-project index DB written by `codegraph init` / `index`.
.codegraph/

# Local upstream-sync ledger (colby-upstream-sync skill); not part of the repo.
docs/upstream-sync/
.codegraph-v2/

# AWS CodeBuild local config (sensitive — never commit)
.aws/codebuild.env
Expand Down
5 changes: 5 additions & 0 deletions .oxfmtignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ changelog/
.release-please-manifest.json
release-please-config.json

# Frozen/hash-addressed upstream-sync provenance. These bytes are reviewed and
# verified by SHA rather than rewritten by the general Markdown formatter.
docs/upstream-sync/UPSTREAM.md
docs/upstream-sync/V1_5_COMMIT_MANIFEST.md

# Golden artifacts are byte-compared by the equivalence/golden oracle tests
# (include_str! / fs::read). Reformatting them breaks the test suite.
reference/
Expand Down
12 changes: 7 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ Full Godot static-analysis scope, static-vs-runtime boundary, and honesty signal

## HTTP MCP server: background mode + addr-keyed registry

`serve --mcp` (stdio) uses the PER-PROJECT daemon (`.codegraph/daemon.pid` + socket). `serve --http`
`serve --mcp` (stdio) uses the PER-PROJECT daemon (`.codegraph-v2/daemon.pid` + socket; the whole
rendezvous is derived from `IndexPaths::current_root`). `serve --http`
(streamable-HTTP) is different: HTTP servers are keyed by BIND ADDR — a global server (no `--path`)
spans many projects — so they use a GLOBAL, addr-keyed registry, NOT `.codegraph/`. The registry
spans many projects — so they use a GLOBAL, addr-keyed registry, NOT the per-project root. The registry
lives in `codegraph-daemon/src/http_registry.rs`: one `<addr-sanitized>.json` file per running server
(`HttpServerInfo { pid, addr, mode, project, started_at, version, log_file }`) under
`$XDG_STATE_HOME/codegraph/http` (else `~/.local/state/codegraph/http`; `%LOCALAPPDATA%\codegraph\http`
Expand Down Expand Up @@ -158,9 +159,10 @@ make coverage # workspace coverage summary (informational; `make coverage-htm
`Security Audit` (cargo-audit) + `CI Success` gate, on push/PR to `main`.
- **Release** (`.github/workflows/release-please.yml`): release-please opens a
release PR; merging it cuts a `v<version>` tag and triggers the pipeline —
4-platform binaries (linux musl x86_64/aarch64 via cargo-zigbuild, macOS
x86_64/aarch64), git-cliff release notes, and a GitHub Release with the
binaries attached. The project is distributed via GitHub Releases +
6-platform binaries (linux musl x86_64/aarch64 via cargo-zigbuild, macOS
x86_64/aarch64, and Windows MSVC `x86_64-pc-windows-msvc` on `windows-latest`
plus `aarch64-pc-windows-msvc` on `windows-11-arm`), git-cliff release notes,
and a GitHub Release with the binaries attached. The project is distributed via GitHub Releases +
`cargo install --git`; it is NOT published to crates.io. Version bumps are
owned by release-please via `.release-please-manifest.json` — never bump by
hand.
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ test:
@echo "🧪 Running tests..."
$(CARGO) test --workspace

# Scope guardrail: no AI / vector / LLM crates allowed in the workspace
# Scope guardrail: no AI / vector / LLM crates in the workspace, and no drift
# between the release workflow's asset names and what the installers download.
guardrail:
@echo "🛡️ Running scope guardrail..."
bash scripts/guardrail.sh
Expand Down
42 changes: 35 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ No AI/LLM anywhere inside the binary — output is byte-stable and deterministic
## Table of Contents

- [Quickstart](#quickstart)
- [Upgrading from v0.40.4](#upgrading-from-v0404)
- [Installation](#installation)
- [One-liner install (scripts)](#one-liner-install-scripts)
- [Prebuilt binaries](#prebuilt-binaries)
Expand Down Expand Up @@ -56,13 +57,37 @@ irm https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/instal
**Index a project and query it:**

```bash
codegraph init /path/to/project # create .codegraph/ and run the first index
codegraph init /path/to/project # create .codegraph-v2/ and run the first index
codegraph query "<symbol>" -p /path/to/project # full-text search
codegraph serve --mcp --path /path/to/project # MCP server (--path optional, defaults to cwd)
```

---

## Upgrading from v0.40.4

The per-project index moved out of `<project>/.codegraph/` into an isolated
`<project>/.codegraph-v2/`. A `v0.40.4` index is **not migrated and not read** —
this binary never opens, migrates, or writes the old root, so an existing
`.codegraph/` is simply ignored. Two consequences:

- **Run `codegraph init` again in each project.** Until you do, the project counts
as not indexed: `serve --mcp` falls back to direct mode with nothing to serve,
and the query commands report `CodeGraph not initialized`.
- **Old configuration does not carry over.** `.codegraph/config.toml` and
`.codegraph/codegraph.json` are ignored. Copy them to
`.codegraph-v2/config.toml` and `.codegraph-v2/codegraph.json` if you still
want them.

The daemon rendezvous (`daemon.pid`, `daemon.sock`, `daemon.log`) moved with the
index, so it now also lives under `.codegraph-v2/`.

`codegraph status` reports both roots: `indexPath` is the current one, and
`legacyIndexPaths` lists any old root still on disk. The old directory is left
untouched — delete it by hand once you no longer want it.

---

## Installation

The CLI package is **`codegraph-rs`** — a single binary named `codegraph`. SQLite
Expand Down Expand Up @@ -91,7 +116,7 @@ irm https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/instal
# Fallback — build from source (only if you have a Rust toolchain)
cargo install --git https://github.com/sunerpy/codegraph-rust codegraph-rs # binary: `codegraph`

codegraph init /path/to/project # create the index DB (.codegraph/)
codegraph init /path/to/project # create the index DB (.codegraph-v2/)
codegraph index /path/to/project # parse + build the graph
```

Expand Down Expand Up @@ -218,7 +243,7 @@ Beyond wiring the MCP server, CodeGraph can install a `SKILL.md` directly into
each agent's skill directory. The skill teaches your agent to use CodeGraph for
code research and project onboarding — reach for `codegraph_explore` before
grep/read, use `codegraph_node` instead of a plain file read on indexed source,
and run `codegraph init` when no `.codegraph/` index is present yet.
and run `codegraph init` when no `.codegraph-v2/` index is present yet.

```bash
codegraph skill install --yes # install into all detected agents (global)
Expand Down Expand Up @@ -384,8 +409,8 @@ LLM library _inside_ the codegraph binary itself.

CodeGraph spawns a shared background daemon for each indexed project when you run
`codegraph serve --mcp`. Multiple MCP clients (terminal tabs, agents) share that
one daemon via a Unix socket (`.codegraph/daemon.sock`). It exits once all clients
disconnect and the idle timeout elapses.
one daemon via a Unix socket (`.codegraph-v2/daemon.sock`). It exits once all
clients disconnect and the idle timeout elapses.

Key operations:

Expand All @@ -398,8 +423,8 @@ codegraph http stop <addr> # terminate one HTTP server by address

Set `CODEGRAPH_NO_DAEMON=1` to force foreground mode (useful in CI). The daemon
watches files with a 2 s debounce; pass `--no-watch` or set `CODEGRAPH_NO_WATCH=1`
to disable. Custom extension mapping goes in `.codegraph/codegraph.json`; exclude
patterns in `.codegraph/config.toml` under `[indexing] exclude`.
to disable. Custom extension mapping goes in `.codegraph-v2/codegraph.json`;
exclude patterns in `.codegraph-v2/config.toml` under `[indexing] exclude`.

Full env-var table, HTTP server details, filesystem fallback behavior, and the
Claude prompt-hook: [`docs/mcp.md`](docs/mcp.md) and
Expand Down Expand Up @@ -476,6 +501,9 @@ Full list with extensions and per-language notes: [`docs/languages.md`](docs/lan
- [`docs/godot.md`](docs/godot.md) — Godot static analysis: what CodeGraph
extracts from `.tscn`/`.tres`/`project.godot`/`.gd`, the static-vs-runtime
boundary, and honesty signals for dynamic reachability.
- [`docs/godot-gdext-decision.md`](docs/godot-gdext-decision.md) — why `gdext`
(godot-rust GDExtension bindings) is rejected for Godot analysis, and the
engine-free alternatives.
- [`docs/grammar-manifest.md`](docs/grammar-manifest.md) /
[`docs/embedded-extraction.md`](docs/embedded-extraction.md) — language support
and extraction tiers (engineering ABI detail).
Expand Down
Loading
Loading