Add landing page + Starlight docs site (#375)
* udpated matrix * feat(site): add landing page + Starlight docs site Astro + Starlight site in site/ — a flat/paper editorial landing page plus 18 docs pages seeded from the README. Monochrome theme, hairline rules, square corners, live GitHub star count, light default + dark toggle. Deploys to GitHub Pages via .github/workflows/deploy-site.yml. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
1f3625a3e9
commit
4509b45dd5
@@ -0,0 +1,43 @@
|
|||||||
|
name: Deploy site to GitHub Pages
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- 'site/**'
|
||||||
|
- '.github/workflows/deploy-site.yml'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# Allow GITHUB_TOKEN to deploy to Pages and verify the deployment origin.
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
# One deploy at a time; let an in-progress run finish.
|
||||||
|
concurrency:
|
||||||
|
group: pages
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Build with Astro
|
||||||
|
uses: withastro/action@v3
|
||||||
|
with:
|
||||||
|
path: site
|
||||||
|
node-version: 22
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
steps:
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
@@ -1,23 +1,31 @@
|
|||||||
# CodeGraph A/B benchmark — with vs without, every language × S/M/L
|
# CodeGraph A/B benchmark — with vs without, every language × S/M/L
|
||||||
|
|
||||||
**Date:** 2026-05-23 · **Branch:** `architectural-improvements`
|
**Date:** 2026-05-24 · **Branch:** `main` · **codegraph 0.9.4**
|
||||||
|
|
||||||
A headless agent (Claude Opus, `--permission-mode bypassPermissions`) answers one
|
A headless agent (Claude Opus, `--permission-mode bypassPermissions`) answers one
|
||||||
**canonical flow question** per repo — twice: **with** the codegraph MCP server, and
|
**canonical flow question** per repo — twice: **with** the codegraph MCP server, and
|
||||||
**without** any MCP (built-in Read/Grep/Glob/Bash only). Same model, same prompt; codegraph
|
**without** any MCP (built-in Read/Grep/Glob/Bash only). Same model, same prompt; codegraph
|
||||||
is the only variable. Each cell was **re-indexed fresh** first, so the "with" arm reflects the
|
is the only variable. Each cell was **re-indexed fresh** first (against a `dist/` build of the
|
||||||
current resolvers.
|
current `main` HEAD), so the "with" arm reflects the shipped 0.9.4 resolvers.
|
||||||
|
|
||||||
## Headline
|
## Headline
|
||||||
|
|
||||||
**Across 37 cells, codegraph cut total file reads from 158 → 40 — 75% fewer.** It never
|
**Across 37 cells, codegraph cut total file reads from 159 → 38 — 76% fewer.** It never
|
||||||
*increased* reads in any cell. The mechanism: a few sub-millisecond codegraph calls replace a
|
*increased* reads in any cell (0 regressions). The mechanism: a few sub-millisecond codegraph
|
||||||
read-and-grep exploration. Token cost stays roughly flat (codegraph calls trade for reads) —
|
calls replace a read-and-grep exploration.
|
||||||
the win is **fewer tool calls + lower wall-clock**, which is the design target.
|
|
||||||
|
**Cost stays roughly flat — marginally higher on the with-arm here** (summed across the 37
|
||||||
|
cells: with `$15.4` vs without `$13.8`). On these short single-flow questions the without-arm
|
||||||
|
resolves in <10 calls and never balloons, so it doesn't reach the regime where codegraph's cost
|
||||||
|
savings compound, while the with-arm pays fixed MCP overhead (tool definitions in context +
|
||||||
|
tool-loading) that short tasks don't amortize. The win is **fewer tool calls (189 vs 321, −41%)
|
||||||
|
+ lower wall-clock** (mean **38s vs 48s**), which is the design target. On harder multi-turn
|
||||||
|
investigations cost flips to a net saving as the without-arm's accumulated context balloons —
|
||||||
|
see `docs/benchmarks/call-sequence-analysis.md`.
|
||||||
|
|
||||||
The gap widens with repo size and flow complexity: on medium/large repos the without-codegraph
|
The gap widens with repo size and flow complexity: on medium/large repos the without-codegraph
|
||||||
arm often **thrashes** — many greps/globs, shell `find`/`grep` (Bash), and occasionally spawning
|
arm often **thrashes** — many greps/globs, shell `find`/`grep` (Bash), and occasionally spawning
|
||||||
a **sub-agent** — while the with-codegraph arm answers in 2–6 calls. On tiny repos (a handful of
|
a **sub-agent** — while the with-codegraph arm answers in 2–8 calls. On tiny repos (a handful of
|
||||||
files) the two arms tie or codegraph is marginally slower (MCP/index overhead doesn't pay off
|
files) the two arms tie or codegraph is marginally slower (MCP/index overhead doesn't pay off
|
||||||
when the whole flow fits in one or two files) — but reads still drop.
|
when the whole flow fits in one or two files) — but reads still drop.
|
||||||
|
|
||||||
@@ -35,66 +43,70 @@ when the whole flow fits in one or two files) — but reads still drop.
|
|||||||
|
|
||||||
| Language | Size | Repo | files | **with** R/G | cg-calls | dur | **without** R/G | dur | reads saved |
|
| Language | Size | Repo | files | **with** R/G | cg-calls | dur | **without** R/G | dur | reads saved |
|
||||||
|---|---|---|--:|---|--:|--:|---|--:|--:|
|
|---|---|---|--:|---|--:|--:|---|--:|--:|
|
||||||
| C | L | `c-redis` | 884 | 0R / 4G | 4 | 48s | 4R / 9G / 1Gl | 50s | 4 |
|
| C | L | `c-redis` | 884 | 0R / 2G | 4 | 42s | 5R / 6G | 51s | 5 |
|
||||||
| C# | S | `aspnet-realworld` | 78 | 0R / 0G | 2 | 40s | 2R / 1G / 2Gl | 31s | 2 |
|
| C# | S | `aspnet-realworld` | 78 | 0R / 0G | 2 | 27s | 5R / 3G / 2Gl | 54s | 5 |
|
||||||
| C# | M | `aspnet-eshop` | 262 | 0R / 0G | 5 | 39s | 6R / 2G / 3Gl / 1B | 61s | 6 |
|
| C# | M | `aspnet-eshop` | 262 | 0R / 1G | 5 | 39s | 9R / 2G / 5Gl | 58s | 9 |
|
||||||
| C# | L | `aspnet-jellyfin` | 2081 | 4R / 0G | 2 | 61s | 13R / 0G / 4Gl / 21B / 1Ag | 132s | 9 |
|
| C# | L | `aspnet-jellyfin` | 2081 | 3R / 0G | 4 | 51s | 17R / 1G / 2Gl / 17B / 1Ag | 212s | 14 |
|
||||||
| C++ | M | `cpp-leveldb` | 134 | 0R / 0G | 3 | 40s | 2R / 3G | 52s | 2 |
|
| C++ | M | `cpp-leveldb` | 134 | 0R / 0G | 3 | 26s | 4R / 2G | 37s | 4 |
|
||||||
| Dart | S | `flutter_module_books` | 6 | 1R / 0G | 2 | 37s | 1R / 0G / 1Gl | 20s | 0 |
|
| Dart | S | `flutter_module_books` | 6 | 1R / 0G | 2 | 24s | 2R / 0G / 1Gl | 29s | 1 |
|
||||||
| Dart | M | `compass_app` | 212 | 2R / 0G | 2 | 31s | 3R / 1G / 3Gl | 47s | 1 |
|
| Dart | M | `compass_app` | 212 | 2R / 0G / 1Gl | 2 | 42s | 3R / 0G / 2Gl | 30s | 1 |
|
||||||
| Go | S | `gin-realworld` | 21 | 2R / 1G | 3 | 31s | 4R / 0G / 1B | 44s | 2 |
|
| Go | S | `gin-realworld` | 21 | 0R / 0G | 5 | 35s | 4R / 3G / 1Gl | 57s | 4 |
|
||||||
| Go | M | `gin-vueadmin` | 625 | 0R / 0G | 2 | 31s | 3R / 3G / 2Gl | 47s | 3 |
|
| Go | M | `gin-vueadmin` | 625 | 1R / 1G | 4 | 47s | 3R / 3G / 1Gl | 44s | 2 |
|
||||||
| Go | L | `gin-gitness` | 4438 | 3R / 3G | 4 | 52s | 7R / 4G / 3Gl | 60s | 4 |
|
| Go | L | `gin-gitness` | 4438 | 4R / 3G | 4 | 64s | 8R / 7G / 2Gl | 57s | 4 |
|
||||||
| Java | S | `spring-realworld` | 117 | 0R / 0G | 4 | 31s | 8R / 1G / 1Gl | 50s | 8 |
|
| Java | S | `spring-realworld` | 117 | 2R / 0G | 3 | 35s | 8R / 1G / 5B | 57s | 6 |
|
||||||
| Java | M | `spring-mall` | 536 | 1R / 0G | 5 | 51s | 5R / 0G / 4Gl | 64s | 4 |
|
| Java | M | `spring-mall` | 536 | 1R / 0G | 5 | 39s | 2R / 4G / 2Gl | 49s | 1 |
|
||||||
| Java | L | `spring-halo` | 2444 | 0R / 1G | 8 | 75s | 9R / 5G / 8B | 148s | 9 |
|
| Java | L | `spring-halo` | 2444 | 1R / 2G | 8 | 60s | 4R / 1G / 6B | 52s | 3 |
|
||||||
| Kotlin | S | `kotlin-petclinic` | 43 | 1R / 0G | 1 | 23s | 3R / 0G / 2Gl | 26s | 2 |
|
| Kotlin | S | `kotlin-petclinic` | 43 | 0R / 0G | 2 | 37s | 3R / 0G / 1Gl | 23s | 3 |
|
||||||
| Kotlin | M | `Jetcaster` | 166 | 1R / 0G | 3 | 36s | 1R / 0G / 2Gl | 34s | 0 |
|
| Kotlin | M | `Jetcaster` | 166 | 1R / 0G | 3 | 36s | 1R / 0G / 2Gl | 46s | 0 |
|
||||||
| Lua | S | `lualine.nvim` | 123 | 1R / 0G | 4 | 48s | 4R / 0G / 1Gl | 45s | 3 |
|
| Lua | S | `lualine.nvim` | 123 | 1R / 1G | 4 | 48s | 4R / 0G / 2Gl | 49s | 3 |
|
||||||
| Lua | M | `telescope.nvim` | 84 | 0R / 0G | 2 | 33s | 2R / 0G / 1Gl | 26s | 2 |
|
| Lua | M | `telescope.nvim` | 84 | 0R / 0G | 1 | 15s | 1R / 0G / 1Gl | 20s | 1 |
|
||||||
| Luau | S | `Knit` | 11 | 0R / 0G | 4 | 36s | 5R / 0G / 2Gl | 57s | 5 |
|
| Luau | S | `Knit` | 11 | 0R / 0G | 2 | 30s | 5R / 0G / 2Gl | 37s | 5 |
|
||||||
| PHP | S | `laravel-realworld` | 114 | 3R / 0G / 1Gl | 2 | 41s | 6R / 2G / 3Gl | 38s | 3 |
|
| PHP | S | `laravel-realworld` | 114 | 1R / 0G | 6 | 40s | 5R / 1G / 3Gl | 39s | 4 |
|
||||||
| PHP | M | `laravel-firefly` | 2047 | 4R / 4G | 5 | 79s | 5R / 3G / 3Gl / 2B | 70s | 1 |
|
| PHP | M | `laravel-firefly` | 2047 | 2R / 1G | 4 | 47s | 4R / 5G / 3Gl | 75s | 2 |
|
||||||
| PHP | L | `laravel-bookstack` | 2160 | 0R / 1G | 5 | 42s | 3R / 2G / 2Gl | 46s | 3 |
|
| PHP | L | `laravel-bookstack` | 2160 | 1R / 2G | 2 | 41s | 2R / 4G / 1Gl | 50s | 1 |
|
||||||
| Python | S | `django-realworld` | 44 | 1R / 1G | 2 | 30s | 8R / 0G / 1Gl | 35s | 7 |
|
| Python | S | `django-realworld` | 44 | 2R / 1G | 2 | 47s | 9R / 0G / 1B | 38s | 7 |
|
||||||
| Python | M | `django-wagtail` | 1672 | 3R / 0G | 5 | 73s | 7R / 5G / 2Gl / 1B | 63s | 4 |
|
| Python | M | `django-wagtail` | 1672 | 2R / 0G | 4 | 45s | 8R / 3G / 3Gl / 1B | 66s | 6 |
|
||||||
| Python | L | `django-saleor` | 4429 | 1R / 2G | 3 | 59s | 6R / 5G / 2Gl / 1B | 72s | 5 |
|
| Python | L | `django-saleor` | 4429 | 2R / 2G | 4 | 52s | 4R / 6G / 1Gl | 64s | 2 |
|
||||||
| Ruby | S | `rails-realworld` | 59 | 0R / 0G | 2 | 34s | 4R / 0G / 3Gl | 40s | 4 |
|
| Ruby | S | `rails-realworld` | 59 | 0R / 0G | 2 | 30s | 3R / 0G / 2B | 33s | 3 |
|
||||||
| Ruby | M | `rails-spree` | 2905 | 1R / 2G | 8 | 60s | 3R / 4G / 3Gl | 56s | 2 |
|
| Ruby | M | `rails-spree` | 2905 | 2R / 3G / 1Gl | 5 | 43s | 3R / 3G / 2Gl / 1B | 55s | 1 |
|
||||||
| Ruby | L | `rails-forem` | 4658 | 3R / 1G | 3 | 54s | 3R / 2G / 1Gl | 49s | 0 |
|
| Ruby | L | `rails-forem` | 4658 | 3R / 1G | 3 | 43s | 4R / 2G / 3Gl | 48s | 1 |
|
||||||
| Rust | S | `rust-axum-realworld` | 13 | 1R / 0G | 4 | 28s | 3R / 1G / 1Gl | 49s | 2 |
|
| Rust | S | `rust-axum-realworld` | 13 | 0R / 0G | 2 | 21s | 3R / 0G / 1Gl | 38s | 3 |
|
||||||
| Rust | M | `rust-actix-examples` | 176 | 1R / 0G | 5 | 42s | 4R / 1G / 2B | 35s | 3 |
|
| Rust | M | `rust-actix-examples` | 176 | 0R / 1G | 3 | 42s | 3R / 0G / 3B | 36s | 3 |
|
||||||
| Rust | L | `rust-cratesio` | 1053 | 0R / 0G | 3 | 20s | 1R / 2G | 15s | 1 |
|
| Rust | L | `rust-cratesio` | 1053 | 1R / 0G | 3 | 22s | 1R / 2G | 18s | 0 |
|
||||||
| Scala | S | `computer-database` | 10 | 1R / 0G | 4 | 47s | 2R / 0G / 1B | 28s | 1 |
|
| Scala | S | `computer-database` | 10 | 1R / 0G | 2 | 27s | 3R / 0G / 1Gl | 25s | 2 |
|
||||||
| Swift | S | `vapor-template` | 14 | 0R / 0G | 1 | 16s | 2R / 0G / 1Gl | 22s | 2 |
|
| Swift | S | `vapor-template` | 14 | 0R / 0G | 2 | 21s | 2R / 0G / 2Gl | 22s | 2 |
|
||||||
| Swift | M | `vapor-steampress` | 100 | 1R / 0G | 8 | 53s | 3R / 3G / 2B | 57s | 2 |
|
| Swift | M | `vapor-steampress` | 100 | 0R / 0G | 5 | 49s | 3R / 1G / 2Gl | 39s | 3 |
|
||||||
| Swift | L | `vapor-spi` | 542 | 2R / 0G | 5 | 49s | 2R / 3G / 2Gl | 36s | 0 |
|
| Swift | L | `vapor-spi` | 542 | 1R / 1G | 4 | 27s | 2R / 5G | 34s | 1 |
|
||||||
| TypeScript/JS | S | `express-realworld` | 39 | 1R / 0G | 1 | 16s | 2R / 1G / 1Gl | 27s | 1 |
|
| TypeScript/JS | S | `express-realworld` | 39 | 1R / 0G | 1 | 25s | 2R / 2G | 19s | 1 |
|
||||||
| TypeScript/JS | M | `excalidraw` | 643 | 0R / 0G | 4 | 53s | 9R / 7G | 98s | 9 |
|
| TypeScript/JS | M | `excalidraw` | 643 | 1R / 0G | 3 | 55s | 7R / 5G / 3Gl / 1B | 87s | 6 |
|
||||||
| TypeScript/JS | L | `nest-immich` | 2759 | 1R / 1G | 6 | 50s | 3R / 1G / 2Gl | 57s | 2 |
|
| TypeScript/JS | L | `nest-immich` | 2759 | 1R / 0G | 7 | 50s | 3R / 0G / 1Gl | 44s | 2 |
|
||||||
|
|
||||||
**Totals (37 cells):** with codegraph **40 reads / 21 greps**, without **158 reads / 71 greps** —
|
**Totals (37 cells):** with codegraph **38 reads / 22 greps**, without **159 reads / 72 greps** —
|
||||||
**75% fewer reads, ~70% fewer greps.** Codegraph never increased reads in any cell, and the
|
**76% fewer reads, ~69% fewer greps.** Codegraph never increased reads in any cell, and the
|
||||||
without-arm additionally ran shell `find`/`grep` (Bash) and a sub-agent that the with-arm never
|
without-arm additionally ran **52 globs + 37 shell `find`/`grep` (Bash) + 1 sub-agent** that the
|
||||||
needed. (74 agent runs, ~$29 total.)
|
with-arm (**0 Bash, 0 sub-agents**) never needed. (74 agent runs, $29.18 total.)
|
||||||
|
|
||||||
## Observations
|
## Observations
|
||||||
|
|
||||||
- **Biggest wins are medium/large backends with a real route→handler→service flow:** excalidraw
|
- **Biggest wins are medium/large backends with a real route→handler→service flow:** aspnet-jellyfin
|
||||||
(0R vs 9R/7G), spring-halo (0R vs 9R + 8 Bash), spring-realworld (0R vs 8R), django-realworld
|
(3R / 51s vs **17R + 17 Bash + a spawned sub-agent / 212s** — the single most dramatic cell),
|
||||||
(1R vs 8R), aspnet-jellyfin (4R vs 13R + 21 Bash + a spawned sub-agent), aspnet-eshop (0R vs 6R).
|
aspnet-eshop (0R vs 9R), django-realworld (2R vs 9R), spring-realworld (2R vs 8R + 5 Bash),
|
||||||
|
django-wagtail (2R vs 8R), excalidraw (1R / 55s vs 7R / 87s), Luau Knit (0R vs 5R), aspnet-realworld
|
||||||
|
(0R vs 5R), c-redis (0R vs 5R).
|
||||||
- **Without codegraph, large repos make the agent thrash:** it falls back to shell `find`/`grep`
|
- **Without codegraph, large repos make the agent thrash:** it falls back to shell `find`/`grep`
|
||||||
(Bash) and on jellyfin even spawned a sub-agent — exactly the behavior codegraph is meant to
|
(37 Bash calls across the matrix) and on jellyfin even spawned a sub-agent — exactly the behavior
|
||||||
prevent. The with-arm answers those in 2–6 codegraph calls.
|
codegraph is meant to prevent. The with-arm answers those in 2–8 codegraph calls and used **0 Bash
|
||||||
- **Tie zone = tiny repos** (Dart books 6 files, Kotlin Jetcaster, Ruby forem, Swift spi): the whole
|
and 0 sub-agents** anywhere.
|
||||||
flow fits in 1–2 files, so reading is already cheap; codegraph ties on reads and is sometimes a
|
- **Tie zone = tiny repos** (Kotlin Jetcaster 1R/1R, Rust cratesio 1R/1R, express 1R/2R, Swift template
|
||||||
few seconds slower (MCP + index overhead). This matches the design note that codegraph's value
|
0R/2R): the whole flow fits in 1–2 files, so reading is already cheap; codegraph ties on reads and is
|
||||||
scales with repo size.
|
sometimes a few seconds slower (MCP + index overhead — Kotlin petclinic 37s vs 23s, cratesio 22s vs
|
||||||
- **Duration tracks reads on the big repos** (jellyfin 61s vs 132s, spring-halo 75s vs 148s,
|
18s). This matches the design note that codegraph's value scales with repo size.
|
||||||
excalidraw 53s vs 98s) and is noise on small ones.
|
- **Duration tracks reads on the big repos** (jellyfin 51s vs 212s, excalidraw 55s vs 87s, aspnet-eshop
|
||||||
- Some "with" cells still read 2–4 files (jellyfin, gitness, laravel-firefly, forem) — the residual
|
39s vs 58s, django-wagtail 45s vs 66s) and is noise on small ones; mean wall-clock is 38s with vs 48s
|
||||||
is the documented frontier (anonymous handlers, deep service chains, dynamic finders); codegraph
|
without.
|
||||||
gets the agent to the right file, then it reads one to confirm a detail.
|
- Some "with" cells still read 2–4 files (jellyfin, gitness, forem, saleor, django) — the residual is
|
||||||
|
the documented frontier (anonymous handlers, deep service chains, dynamic finders); codegraph gets the
|
||||||
|
agent to the right file, then it reads one to confirm a detail.
|
||||||
|
|
||||||
## Coverage note
|
## Coverage note
|
||||||
|
|
||||||
@@ -105,7 +117,9 @@ than faked.
|
|||||||
|
|
||||||
## Reproduce
|
## Reproduce
|
||||||
|
|
||||||
Driver + parser: `/tmp/ab-matrix/run.sh` (matrix of `lang|size|repo|question`) and
|
Canonical harness: `scripts/agent-eval/run-all.sh <repo> "<question>" headless` (with = codegraph-only
|
||||||
`/tmp/ab-matrix/parse-matrix.mjs`. Each cell: `rm -rf .codegraph && codegraph init -i`, then
|
MCP, without = empty MCP), parsed from the stream-json logs. The throwaway matrix driver + parser used
|
||||||
`scripts/agent-eval/run-all.sh <repo> "<question>" headless` (with = codegraph-only MCP, without =
|
for this table live in `/tmp/ab-matrix/`: `run.sh` (the `lang|size|repo|question` matrix — each cell does
|
||||||
empty MCP), parsed from the stream-json logs.
|
`rm -rf .codegraph && codegraph init -i` then both arms), `parse-matrix.mjs` (cells → this table), and
|
||||||
|
`compare.mjs` (old-vs-new diff + aggregates). Build `dist/` from the target commit first so the MCP
|
||||||
|
server loads the code under test (`codegraph` on PATH is `npm link`ed to the dev `dist/`).
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# build output
|
||||||
|
dist/
|
||||||
|
# generated types
|
||||||
|
.astro/
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
|
||||||
|
# environment variables
|
||||||
|
.env
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# macOS-specific files
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Starlight Starter Kit: Basics
|
||||||
|
|
||||||
|
[](https://starlight.astro.build)
|
||||||
|
|
||||||
|
```
|
||||||
|
npm create astro@latest -- --template starlight
|
||||||
|
```
|
||||||
|
|
||||||
|
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||||
|
|
||||||
|
## 🚀 Project Structure
|
||||||
|
|
||||||
|
Inside of your Astro + Starlight project, you'll see the following folders and files:
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── public/
|
||||||
|
├── src/
|
||||||
|
│ ├── assets/
|
||||||
|
│ ├── content/
|
||||||
|
│ │ └── docs/
|
||||||
|
│ └── content.config.ts
|
||||||
|
├── astro.config.mjs
|
||||||
|
├── package.json
|
||||||
|
└── tsconfig.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name.
|
||||||
|
|
||||||
|
Images can be added to `src/assets/` and embedded in Markdown with a relative link.
|
||||||
|
|
||||||
|
Static assets, like favicons, can be placed in the `public/` directory.
|
||||||
|
|
||||||
|
## 🧞 Commands
|
||||||
|
|
||||||
|
All commands are run from the root of the project, from a terminal:
|
||||||
|
|
||||||
|
| Command | Action |
|
||||||
|
| :------------------------ | :----------------------------------------------- |
|
||||||
|
| `npm install` | Installs dependencies |
|
||||||
|
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||||
|
| `npm run build` | Build your production site to `./dist/` |
|
||||||
|
| `npm run preview` | Preview your build locally, before deploying |
|
||||||
|
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||||
|
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||||
|
|
||||||
|
## 👀 Want to learn more?
|
||||||
|
|
||||||
|
Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat).
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
// @ts-check
|
||||||
|
import { defineConfig } from 'astro/config';
|
||||||
|
import starlight from '@astrojs/starlight';
|
||||||
|
|
||||||
|
// Project page on GitHub Pages: https://colbymchenry.github.io/codegraph/
|
||||||
|
// `site` + `base` make every internal link resolve under the /codegraph/ prefix.
|
||||||
|
export default defineConfig({
|
||||||
|
site: 'https://colbymchenry.github.io',
|
||||||
|
base: '/codegraph',
|
||||||
|
integrations: [
|
||||||
|
starlight({
|
||||||
|
title: 'codegraph',
|
||||||
|
description:
|
||||||
|
'A local-first code-intelligence tool that turns any codebase into a queryable knowledge graph for AI coding agents.',
|
||||||
|
favicon: '/favicon.svg',
|
||||||
|
head: [
|
||||||
|
{
|
||||||
|
// Default to the light / paper theme on first visit; the toggle still
|
||||||
|
// lets a visitor switch to (and persist) the dark / ink theme.
|
||||||
|
tag: 'script',
|
||||||
|
content:
|
||||||
|
"if(!localStorage.getItem('starlight-theme')){try{localStorage.setItem('starlight-theme','light')}catch(e){}document.documentElement.dataset.theme='light';document.documentElement.style.colorScheme='light'}",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
social: [
|
||||||
|
{
|
||||||
|
icon: 'github',
|
||||||
|
label: 'GitHub',
|
||||||
|
href: 'https://github.com/colbymchenry/codegraph',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
customCss: [
|
||||||
|
'@fontsource-variable/archivo',
|
||||||
|
'@fontsource/ibm-plex-mono/400.css',
|
||||||
|
'@fontsource/ibm-plex-mono/500.css',
|
||||||
|
'@fontsource/ibm-plex-mono/600.css',
|
||||||
|
'./src/styles/theme.css',
|
||||||
|
],
|
||||||
|
components: {
|
||||||
|
// Wordmark in the docs header.
|
||||||
|
SiteTitle: './src/components/SiteTitle.astro',
|
||||||
|
// Default GitHub icon + a live star-count pill (matches the landing nav).
|
||||||
|
SocialIcons: './src/components/SocialIcons.astro',
|
||||||
|
},
|
||||||
|
expressiveCode: {
|
||||||
|
themes: ['github-light', 'github-dark'],
|
||||||
|
styleOverrides: {
|
||||||
|
borderRadius: '0px',
|
||||||
|
borderColor: '#cdcabf',
|
||||||
|
codeFontFamily: "'IBM Plex Mono', ui-monospace, monospace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sidebar: [
|
||||||
|
{
|
||||||
|
label: 'Getting Started',
|
||||||
|
items: [
|
||||||
|
{ label: 'Introduction', slug: 'getting-started/introduction' },
|
||||||
|
{ label: 'Quickstart', slug: 'getting-started/quickstart' },
|
||||||
|
{ label: 'Installation', slug: 'getting-started/installation' },
|
||||||
|
{ label: 'Configuration', slug: 'getting-started/configuration' },
|
||||||
|
{ label: 'Your First Graph', slug: 'getting-started/your-first-graph' },
|
||||||
|
{ label: 'Next Steps', slug: 'getting-started/next-steps' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Core Concepts',
|
||||||
|
items: [
|
||||||
|
{ label: 'How It Works', slug: 'core-concepts/how-it-works' },
|
||||||
|
{ label: 'The Knowledge Graph', slug: 'core-concepts/knowledge-graph' },
|
||||||
|
{ label: 'Resolution & Frameworks', slug: 'core-concepts/resolution' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Guides',
|
||||||
|
items: [
|
||||||
|
{ label: 'Indexing a Project', slug: 'guides/indexing' },
|
||||||
|
{ label: 'Framework Routes', slug: 'guides/framework-routes' },
|
||||||
|
{ label: 'Affected Tests in CI', slug: 'guides/affected-tests' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Reference',
|
||||||
|
items: [
|
||||||
|
{ label: 'MCP Server', slug: 'reference/mcp-server' },
|
||||||
|
{ label: 'Integrations', slug: 'reference/integrations' },
|
||||||
|
{ label: 'CLI', slug: 'reference/cli' },
|
||||||
|
{ label: 'API', slug: 'reference/api' },
|
||||||
|
{ label: 'Languages', slug: 'reference/languages' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ label: 'Troubleshooting', slug: 'troubleshooting' },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
Generated
+6207
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "site",
|
||||||
|
"type": "module",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "astro dev",
|
||||||
|
"start": "astro dev",
|
||||||
|
"build": "astro build",
|
||||||
|
"preview": "astro preview",
|
||||||
|
"astro": "astro"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@astrojs/starlight": "^0.39.2",
|
||||||
|
"@fontsource-variable/archivo": "^5.2.8",
|
||||||
|
"@fontsource/ibm-plex-mono": "^5.2.7",
|
||||||
|
"astro": "^6.3.1",
|
||||||
|
"sharp": "^0.34.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none" stroke="#16150f" stroke-width="2">
|
||||||
|
<line x1="16" y1="8" x2="8" y2="23" />
|
||||||
|
<line x1="16" y1="8" x2="24" y2="23" />
|
||||||
|
<line x1="8" y1="23" x2="24" y2="23" />
|
||||||
|
<circle cx="16" cy="8" r="3.4" fill="#16150f" />
|
||||||
|
<circle cx="8" cy="23" r="3.4" fill="#f7f6f2" />
|
||||||
|
<circle cx="24" cy="23" r="3.4" fill="#f7f6f2" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 393 B |
@@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
// Flat technical node-link diagram for the hero. Hand-placed so it reads as a
|
||||||
|
// deliberate blueprint, not a physics blob: thin ink lines, hollow nodes, mono
|
||||||
|
// labels. Hovering a node inks it in. No glow, no gradients, no motion.
|
||||||
|
---
|
||||||
|
|
||||||
|
<svg
|
||||||
|
class="cg-graph"
|
||||||
|
viewBox="0 0 780 600"
|
||||||
|
role="img"
|
||||||
|
aria-label="A code knowledge graph: index.ts links to auth.ts, router.ts and api/users.ts, which branch to middleware.ts, types/index.ts, createRouter and listUsers."
|
||||||
|
>
|
||||||
|
<g class="edges">
|
||||||
|
<line x1="430" y1="64" x2="250" y2="210" />
|
||||||
|
<line x1="430" y1="64" x2="450" y2="250" />
|
||||||
|
<line x1="430" y1="64" x2="650" y2="200" />
|
||||||
|
<line x1="250" y1="210" x2="180" y2="380" />
|
||||||
|
<line x1="250" y1="210" x2="340" y2="380" />
|
||||||
|
<line x1="450" y1="250" x2="560" y2="380" />
|
||||||
|
<line x1="560" y1="380" x2="560" y2="500" />
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g class="nodes">
|
||||||
|
<g class="node">
|
||||||
|
<circle cx="430" cy="64" r="9" />
|
||||||
|
<text x="448" y="69" text-anchor="start">index.ts</text>
|
||||||
|
</g>
|
||||||
|
<g class="node">
|
||||||
|
<circle cx="250" cy="210" r="9" />
|
||||||
|
<text x="232" y="215" text-anchor="end">auth.ts</text>
|
||||||
|
</g>
|
||||||
|
<g class="node">
|
||||||
|
<circle cx="450" cy="250" r="9" />
|
||||||
|
<text x="468" y="255" text-anchor="start">router.ts</text>
|
||||||
|
</g>
|
||||||
|
<g class="node">
|
||||||
|
<circle cx="650" cy="200" r="9" />
|
||||||
|
<text x="668" y="205" text-anchor="start">api/users.ts</text>
|
||||||
|
</g>
|
||||||
|
<g class="node">
|
||||||
|
<circle cx="180" cy="380" r="9" />
|
||||||
|
<text x="180" y="410" text-anchor="middle">middleware.ts</text>
|
||||||
|
</g>
|
||||||
|
<g class="node">
|
||||||
|
<circle cx="340" cy="380" r="9" />
|
||||||
|
<text x="340" y="410" text-anchor="middle">types/index.ts</text>
|
||||||
|
</g>
|
||||||
|
<g class="node">
|
||||||
|
<circle cx="560" cy="380" r="9" />
|
||||||
|
<text x="578" y="385" text-anchor="start">createRouter</text>
|
||||||
|
</g>
|
||||||
|
<g class="node">
|
||||||
|
<circle cx="560" cy="500" r="9" />
|
||||||
|
<text x="560" y="530" text-anchor="middle">listUsers</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.cg-graph {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
max-width: 560px;
|
||||||
|
min-width: 0; /* flex item: allow shrinking below intrinsic SVG width */
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.cg-graph .edges line {
|
||||||
|
stroke: var(--cg-ink);
|
||||||
|
stroke-width: 1.25;
|
||||||
|
}
|
||||||
|
.cg-graph .node circle {
|
||||||
|
fill: var(--cg-paper);
|
||||||
|
stroke: var(--cg-ink);
|
||||||
|
stroke-width: 1.5;
|
||||||
|
transition: fill 0.12s ease;
|
||||||
|
}
|
||||||
|
.cg-graph .node text {
|
||||||
|
font-family: var(--sl-font-mono);
|
||||||
|
font-size: 15px;
|
||||||
|
fill: var(--cg-ink);
|
||||||
|
dominant-baseline: middle;
|
||||||
|
}
|
||||||
|
.cg-graph .node:hover circle {
|
||||||
|
fill: var(--cg-ink);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
// Starlight 0.39 exposes route data on Astro.locals.starlightRoute (not props).
|
||||||
|
// Link the wordmark to the landing page at the site root.
|
||||||
|
const { siteTitle } = Astro.locals.starlightRoute;
|
||||||
|
const base = import.meta.env.BASE_URL.replace(/\/$/, '');
|
||||||
|
---
|
||||||
|
|
||||||
|
<a href={`${base}/`} class="cg-site-title" translate="no">{siteTitle}</a>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.cg-site-title {
|
||||||
|
font-family: var(--sl-font);
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--cg-ink);
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.cg-site-title:hover {
|
||||||
|
color: var(--cg-ink);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
// Keep Starlight's default social icons (the GitHub link) and append a live
|
||||||
|
// star-count pill, matching the landing page nav.
|
||||||
|
import Default from '@astrojs/starlight/components/SocialIcons.astro';
|
||||||
|
import { getStarsLabel } from '../lib/github';
|
||||||
|
|
||||||
|
const stars = await getStarsLabel();
|
||||||
|
const repo = 'https://github.com/colbymchenry/codegraph';
|
||||||
|
---
|
||||||
|
|
||||||
|
<Default {...Astro.props} />
|
||||||
|
<a
|
||||||
|
class="cg-star"
|
||||||
|
href={`${repo}/stargazers`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
aria-label={`${stars} GitHub stars`}
|
||||||
|
>
|
||||||
|
<span class="cg-star-glyph" aria-hidden="true">★</span>{stars}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.cg-star {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.35rem;
|
||||||
|
border: 1px solid var(--cg-rule);
|
||||||
|
padding: 0.32rem 0.6rem;
|
||||||
|
font-family: var(--sl-font);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--cg-ink);
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
.cg-star:hover {
|
||||||
|
background: var(--cg-paper-press);
|
||||||
|
color: var(--cg-ink);
|
||||||
|
}
|
||||||
|
.cg-star-glyph {
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
/* Don't crowd the compact mobile header. */
|
||||||
|
@media (max-width: 50rem) {
|
||||||
|
.cg-star {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { defineCollection } from 'astro:content';
|
||||||
|
import { docsLoader } from '@astrojs/starlight/loaders';
|
||||||
|
import { docsSchema } from '@astrojs/starlight/schema';
|
||||||
|
|
||||||
|
export const collections = {
|
||||||
|
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
|
||||||
|
};
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
title: How It Works
|
||||||
|
description: The extraction, storage, resolution, and auto-sync pipeline.
|
||||||
|
---
|
||||||
|
|
||||||
|
CodeGraph turns source code into a queryable graph in four stages.
|
||||||
|
|
||||||
|
```
|
||||||
|
files → Extraction (tree-sitter) → DB (nodes/edges/files)
|
||||||
|
↓
|
||||||
|
Resolution (imports, name-matching, framework patterns)
|
||||||
|
↓
|
||||||
|
Graph queries (callers, callees, impact)
|
||||||
|
↓
|
||||||
|
Context building (markdown / JSON for AI consumption)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1. Extraction
|
||||||
|
|
||||||
|
[tree-sitter](https://tree-sitter.github.io/) parses source into ASTs. Language-specific queries extract **nodes** (functions, classes, methods, types…) and **edges** (calls, imports, extends, implements). Heavy parsing runs off the main thread.
|
||||||
|
|
||||||
|
## 2. Storage
|
||||||
|
|
||||||
|
Everything goes into a local SQLite database (`.codegraph/codegraph.db`) with FTS5 full-text search. CodeGraph uses native `better-sqlite3` when available and transparently falls back to a WASM backend; `codegraph status` shows which is live.
|
||||||
|
|
||||||
|
## 3. Resolution
|
||||||
|
|
||||||
|
After extraction, references are resolved: function calls → definitions, imports → source files, class inheritance, and framework-specific patterns. Some dynamic-dispatch boundaries (callbacks, observers, React re-render, JSX children) are bridged by synthesizers so flows connect end-to-end. See [Resolution & Frameworks](/codegraph/core-concepts/resolution/).
|
||||||
|
|
||||||
|
## 4. Auto-sync
|
||||||
|
|
||||||
|
The MCP server watches your project using native OS file events (FSEvents / inotify / ReadDirectoryChangesW). Changes are debounced, filtered to source files, and incrementally synced — the graph stays fresh as you code, with no configuration.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
title: The Knowledge Graph
|
||||||
|
description: The node and edge kinds the graph is built from.
|
||||||
|
---
|
||||||
|
|
||||||
|
CodeGraph stores three things: **nodes** (symbols and files), **edges** (relationships between them), and **files**. Every node and edge carries an exact `kind`, drawn from a fixed vocabulary so queries are consistent across languages.
|
||||||
|
|
||||||
|
## Node kinds
|
||||||
|
|
||||||
|
`file`, `module`, `class`, `struct`, `interface`, `trait`, `protocol`, `function`, `method`, `property`, `field`, `variable`, `constant`, `enum`, `enum_member`, `type_alias`, `namespace`, `parameter`, `import`, `export`, `route`, `component`.
|
||||||
|
|
||||||
|
## Edge kinds
|
||||||
|
|
||||||
|
`contains`, `calls`, `imports`, `exports`, `extends`, `implements`, `references`, `type_of`, `returns`, `instantiates`, `overrides`, `decorates`.
|
||||||
|
|
||||||
|
## Provenance
|
||||||
|
|
||||||
|
Most edges come straight from the AST. A few — at dynamic-dispatch boundaries that static parsing can't follow — are **synthesized** and marked with `provenance: 'heuristic'` plus the wiring site that created them. These are surfaced inline in `trace`, the `node` trail, and `context` call-paths, so an agent can see exactly where a connection came from.
|
||||||
|
|
||||||
|
## Querying it
|
||||||
|
|
||||||
|
- **Search** symbols by name (FTS5).
|
||||||
|
- **Callers / callees** walk the call graph one hop at a time.
|
||||||
|
- **Impact** computes the transitive radius affected by a change.
|
||||||
|
- **Trace** returns a whole call path between two symbols in one call.
|
||||||
|
|
||||||
|
See the [CLI](/codegraph/reference/cli/) and [MCP Server](/codegraph/reference/mcp-server/) references for how to run these.
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
title: Resolution & Frameworks
|
||||||
|
description: How CodeGraph connects references and links routes to handlers.
|
||||||
|
---
|
||||||
|
|
||||||
|
Extraction produces nodes and raw edges; **resolution** turns names into real connections.
|
||||||
|
|
||||||
|
## Reference resolution
|
||||||
|
|
||||||
|
After parsing, CodeGraph resolves:
|
||||||
|
|
||||||
|
- **Imports** → the source files they point at (including tsconfig path aliases and cargo workspace members).
|
||||||
|
- **Calls** → their definitions, by import resolution and name matching.
|
||||||
|
- **Inheritance** → `extends` / `implements` between types.
|
||||||
|
|
||||||
|
## Framework awareness
|
||||||
|
|
||||||
|
CodeGraph recognizes web-framework routing files and emits `route` nodes linked by `references` edges to their handler classes or functions — so querying the callers of a view or controller surfaces the URL pattern that binds it. See [Framework Routes](/codegraph/guides/framework-routes/) for the full list of recognized frameworks.
|
||||||
|
|
||||||
|
## Dynamic-dispatch coverage
|
||||||
|
|
||||||
|
Static parsing misses computed and indirect calls, so flows can break at dynamic dispatch. CodeGraph bridges several of these boundaries with synthesizers so a flow connects end-to-end:
|
||||||
|
|
||||||
|
- Callback / observer registration
|
||||||
|
- `EventEmitter` channels
|
||||||
|
- React re-render (`setState` → `render`)
|
||||||
|
- JSX child (`render` → child component)
|
||||||
|
- Django ORM descriptors
|
||||||
|
|
||||||
|
Every synthesized edge is marked `provenance: 'heuristic'` with the site that wired it, and is shown inline wherever a path crosses it.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: Configuration
|
||||||
|
description: CodeGraph is zero-config — here's what that means in practice.
|
||||||
|
---
|
||||||
|
|
||||||
|
There isn't any — CodeGraph is **zero-config**. It indexes every file whose extension maps to a [supported language](/codegraph/reference/languages/) and **respects your `.gitignore`**: in git repos via git itself, and in non-git projects by reading `.gitignore` files directly (root and nested, the same way git would).
|
||||||
|
|
||||||
|
## What that means in practice
|
||||||
|
|
||||||
|
- Anything git ignores — `node_modules`, build output, secrets in `.env` — is never indexed. **To keep something out of the graph, add it to `.gitignore`.**
|
||||||
|
- There's no config file to write or keep in sync, and nothing to wire up per language: support is automatic from the file extension.
|
||||||
|
- Files larger than 1 MB are skipped (generated bundles, minified JS, vendored blobs) — they cost parse budget for no useful symbols.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Committed files that aren't gitignored *are* indexed, even under `vendor/` or a committed `dist/`. If you commit a dependency or build directory you don't want in the graph, add it to `.gitignore`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Where data lives
|
||||||
|
|
||||||
|
Per-project data lives in a `.codegraph/` directory at your project root, containing the SQLite database (`codegraph.db`). Nothing leaves your machine.
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
title: Installation
|
||||||
|
description: Install CodeGraph and configure your AI coding agents.
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Run the installer
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx @colbymchenry/codegraph
|
||||||
|
```
|
||||||
|
|
||||||
|
The installer will:
|
||||||
|
|
||||||
|
- Ask which agent(s) to configure — auto-detecting installed ones from **Claude Code**, **Cursor**, **Codex CLI**, **opencode**, and **Hermes Agent**.
|
||||||
|
- Prompt to install `codegraph` on your `PATH` (so agents can launch the MCP server).
|
||||||
|
- Ask whether configs apply to all your projects or just this one.
|
||||||
|
- Write each chosen agent's MCP server config plus an instructions file (e.g. `CLAUDE.md`, `.cursor/rules/codegraph.mdc`, `~/.codex/AGENTS.md`).
|
||||||
|
- Set up auto-allow permissions when Claude Code is one of the targets.
|
||||||
|
- Initialize your current project (local installs only).
|
||||||
|
|
||||||
|
## Non-interactive (scripting / CI)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph install --yes # auto-detect agents, install global
|
||||||
|
codegraph install --target=cursor,claude --yes # explicit target list
|
||||||
|
codegraph install --target=auto --location=local # detected agents, project-local
|
||||||
|
codegraph install --print-config codex # print snippet, no file writes
|
||||||
|
```
|
||||||
|
|
||||||
|
| Flag | Values | Default |
|
||||||
|
|---|---|---|
|
||||||
|
| `--target` | `auto`, `all`, `none`, or csv (`claude,cursor,…`) | prompt |
|
||||||
|
| `--location` | `global`, `local` | prompt |
|
||||||
|
| `--yes` | (boolean) | prompt every step |
|
||||||
|
| `--no-permissions` | (boolean) skip Claude auto-allow list | permissions on |
|
||||||
|
| `--print-config <id>` | dump snippet for one agent and exit | — |
|
||||||
|
|
||||||
|
## 2. Restart your agent
|
||||||
|
|
||||||
|
Restart your agent (Claude Code / Cursor / Codex CLI / opencode / Hermes Agent) for the MCP server to load.
|
||||||
|
|
||||||
|
## 3. Initialize projects
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd your-project
|
||||||
|
codegraph init -i
|
||||||
|
```
|
||||||
|
|
||||||
|
This builds the per-project knowledge graph index and wires up any project-local agent surfaces, so a single global `codegraph install` works in every project you open.
|
||||||
|
|
||||||
|
## Supported platforms
|
||||||
|
|
||||||
|
Every release ships a self-contained build (bundled Node runtime — nothing to compile) for all three desktop OSes, on both x64 and arm64:
|
||||||
|
|
||||||
|
| Platform | Architectures | Install |
|
||||||
|
|---|---|---|
|
||||||
|
| Windows | x64, arm64 | PowerShell installer or npm |
|
||||||
|
| macOS | x64, arm64 | shell installer or npm |
|
||||||
|
| Linux | x64, arm64 | shell installer or npm |
|
||||||
|
|
||||||
|
## Uninstall
|
||||||
|
|
||||||
|
Changed your mind? One command removes CodeGraph from every agent it configured:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph uninstall
|
||||||
|
```
|
||||||
|
|
||||||
|
This reverses the installer — stripping CodeGraph's MCP server config, instructions, and permissions from each configured agent. Your project indexes (`.codegraph/`) are left untouched; remove those per-project with `codegraph uninit`. Use `--target` to remove from specific agents, or `--yes` to run non-interactively.
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
title: Introduction
|
||||||
|
description: What CodeGraph is, and why it makes AI coding agents faster and cheaper.
|
||||||
|
---
|
||||||
|
|
||||||
|
CodeGraph is a **local-first code-intelligence tool**. It parses your codebase with [tree-sitter](https://tree-sitter.github.io/), stores every symbol, edge, and file in a local SQLite database, and exposes the result as a queryable **knowledge graph** — over the [Model Context Protocol (MCP)](/codegraph/reference/mcp-server/), a CLI, and a TypeScript library.
|
||||||
|
|
||||||
|
It exists to make AI coding agents — Claude Code, Cursor, Codex CLI, opencode, and Hermes Agent — **answer structural questions without scanning files**. Instead of fanning out across `grep`, `glob`, and `Read` to reconstruct how code fits together, an agent queries a pre-built index and gets the answer in a handful of calls.
|
||||||
|
|
||||||
|
## Why it matters
|
||||||
|
|
||||||
|
When an agent explores a codebase, it spends most of its budget on *discovery* — finding the right files before it can read them. CodeGraph removes that step: symbol relationships, call graphs, and structure are already indexed.
|
||||||
|
|
||||||
|
Tested across 7 real-world open-source codebases (median of 4 runs per arm), giving an agent CodeGraph was on average:
|
||||||
|
|
||||||
|
- **35% cheaper**
|
||||||
|
- **57% fewer tokens**
|
||||||
|
- **46% faster**
|
||||||
|
- **71% fewer tool calls**
|
||||||
|
|
||||||
|
The gains scale with codebase size — on large repos the agent answers from the index with **zero file reads**.
|
||||||
|
|
||||||
|
## What's in the graph
|
||||||
|
|
||||||
|
- **Symbols** — functions, classes, methods, types, routes, components, and more.
|
||||||
|
- **Edges** — calls, imports, inheritance, references, and framework-specific relationships.
|
||||||
|
- **Files** — structure plus full-text search (FTS5).
|
||||||
|
|
||||||
|
Extraction is **deterministic** — derived from the AST, never LLM-summarized.
|
||||||
|
|
||||||
|
## 100% local
|
||||||
|
|
||||||
|
No data leaves your machine. No API keys, no external services — just a SQLite database in `.codegraph/`.
|
||||||
|
|
||||||
|
Ready to try it? Head to the [Quickstart](/codegraph/getting-started/quickstart/).
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
title: Next Steps
|
||||||
|
description: Where to go once CodeGraph is installed and indexing.
|
||||||
|
---
|
||||||
|
|
||||||
|
You've got CodeGraph installed and a graph built. Here's where to go next.
|
||||||
|
|
||||||
|
## Understand the model
|
||||||
|
|
||||||
|
- [How It Works](/codegraph/core-concepts/how-it-works/) — the extraction → storage → resolution → sync pipeline.
|
||||||
|
- [The Knowledge Graph](/codegraph/core-concepts/knowledge-graph/) — the node and edge kinds the graph is built from.
|
||||||
|
- [Resolution & Frameworks](/codegraph/core-concepts/resolution/) — how references and framework routes get connected.
|
||||||
|
|
||||||
|
## Put it to work
|
||||||
|
|
||||||
|
- [Indexing a Project](/codegraph/guides/indexing/) — full index, incremental sync, and the file watcher.
|
||||||
|
- [Framework Routes](/codegraph/guides/framework-routes/) — link URL patterns to their handlers.
|
||||||
|
- [Affected Tests in CI](/codegraph/guides/affected-tests/) — run only the tests a change touches.
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [MCP Server](/codegraph/reference/mcp-server/) — the tools agents call.
|
||||||
|
- [CLI](/codegraph/reference/cli/) — every command and flag.
|
||||||
|
- [API](/codegraph/reference/api/) — use CodeGraph as a TypeScript library.
|
||||||
|
- [Integrations](/codegraph/reference/integrations/) — supported agents and manual setup.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
title: Get Started
|
||||||
|
description: Get up and running with CodeGraph in seconds.
|
||||||
|
---
|
||||||
|
|
||||||
|
Get up and running with CodeGraph in seconds.
|
||||||
|
|
||||||
|
## No Node.js required — one command grabs the right build for your OS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# macOS / Linux
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh
|
||||||
|
|
||||||
|
# Windows (PowerShell)
|
||||||
|
irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 | iex
|
||||||
|
```
|
||||||
|
|
||||||
|
## Already have Node? Use npm instead (works on any version)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx @colbymchenry/codegraph # zero-install, or:
|
||||||
|
npm i -g @colbymchenry/codegraph
|
||||||
|
```
|
||||||
|
|
||||||
|
CodeGraph bundles its own runtime — nothing to compile, no native build, works the same everywhere. The interactive installer auto-configures your agent(s) — Claude Code, Cursor, Codex CLI, opencode, Hermes Agent.
|
||||||
|
|
||||||
|
## Initialize Projects
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd your-project
|
||||||
|
codegraph init -i
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it — your agent will use CodeGraph tools automatically when a `.codegraph/` directory exists.
|
||||||
|
|
||||||
|
Next: build [Your First Graph](/codegraph/getting-started/your-first-graph/), or see the full [Installation](/codegraph/getting-started/installation/) options.
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
title: Your First Graph
|
||||||
|
description: Build an index and run your first queries against it.
|
||||||
|
---
|
||||||
|
|
||||||
|
Once CodeGraph is installed, building and exploring a graph takes three commands.
|
||||||
|
|
||||||
|
## Index a project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd your-project
|
||||||
|
codegraph init -i # initialize + index in one step
|
||||||
|
```
|
||||||
|
|
||||||
|
`init` creates the `.codegraph/` directory; `-i` (or `--index`) immediately builds the full index. For an existing project you can re-index any time:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph index # full index
|
||||||
|
codegraph sync # incremental update of changed files
|
||||||
|
```
|
||||||
|
|
||||||
|
## Check it worked
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph status
|
||||||
|
```
|
||||||
|
|
||||||
|
This reports the node/edge/file counts, the active SQLite backend, and the journal mode — a quick health check that the index is ready.
|
||||||
|
|
||||||
|
## Run a query
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph query UserService # find symbols by name
|
||||||
|
codegraph callers handleRequest # what calls a function
|
||||||
|
codegraph callees handleRequest # what a function calls
|
||||||
|
codegraph impact AuthMiddleware # what a change would affect
|
||||||
|
codegraph context "fix the login flow" # build task-focused context
|
||||||
|
```
|
||||||
|
|
||||||
|
Each accepts `--json` for machine-readable output. See the full [CLI reference](/codegraph/reference/cli/).
|
||||||
|
|
||||||
|
## Hand it to your agent
|
||||||
|
|
||||||
|
With a `.codegraph/` directory present and an agent configured (see [Installation](/codegraph/getting-started/installation/)), your agent uses the [MCP tools](/codegraph/reference/mcp-server/) automatically — no extra step.
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
title: Affected Tests in CI
|
||||||
|
description: Run only the tests a change actually touches.
|
||||||
|
---
|
||||||
|
|
||||||
|
`codegraph affected` traces import dependencies transitively to find which test files are affected by a set of changed source files — so CI can run only the relevant tests.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph affected src/utils.ts src/api.ts # pass files as arguments
|
||||||
|
git diff --name-only | codegraph affected --stdin # pipe from git diff
|
||||||
|
codegraph affected src/auth.ts --filter "e2e/*" # custom test-file pattern
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description | Default |
|
||||||
|
|---|---|---|
|
||||||
|
| `--stdin` | Read the file list from stdin | `false` |
|
||||||
|
| `-d, --depth <n>` | Max dependency traversal depth | `5` |
|
||||||
|
| `-f, --filter <glob>` | Custom glob to identify test files | auto-detect |
|
||||||
|
| `-j, --json` | Output as JSON | `false` |
|
||||||
|
| `-q, --quiet` | Output file paths only | `false` |
|
||||||
|
|
||||||
|
## CI / hook example
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
AFFECTED=$(git diff --name-only HEAD | codegraph affected --stdin --quiet)
|
||||||
|
if [ -n "$AFFECTED" ]; then
|
||||||
|
npx vitest run $AFFECTED
|
||||||
|
fi
|
||||||
|
```
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
title: Framework Routes
|
||||||
|
description: CodeGraph links URL patterns to the handlers that serve them.
|
||||||
|
---
|
||||||
|
|
||||||
|
CodeGraph detects web-framework routing files and emits `route` nodes linked by `references` edges to their handler classes or functions. Querying the callers of a view or controller then surfaces the URL pattern that binds it.
|
||||||
|
|
||||||
|
| Framework | Shapes recognized |
|
||||||
|
|---|---|
|
||||||
|
| **Django** | `path()`, `re_path()`, `url()`, `include()` in `urls.py` (CBV `.as_view()`, dotted paths) |
|
||||||
|
| **Flask** | `@app.route('/path', methods=[…])`, blueprint routes |
|
||||||
|
| **FastAPI** | `@app.get(…)`, `@router.post(…)`, all standard methods |
|
||||||
|
| **Express** | `app.get(…)`, `router.post(…)` with middleware chains |
|
||||||
|
| **NestJS** | `@Controller` + `@Get/@Post/…`, GraphQL resolvers, message/event patterns, WebSocket subscriptions |
|
||||||
|
| **Laravel** | `Route::get()`, `Route::resource()`, `Controller@action`, tuple syntax |
|
||||||
|
| **Drupal** | `*.routing.yml` routes; `hook_*` implementations in `.module`/`.theme`/`.install`/`.inc` |
|
||||||
|
| **Rails** | `get '/x', to: 'users#index'`, hash-rocket syntax |
|
||||||
|
| **Spring** | `@GetMapping`, `@PostMapping`, `@RequestMapping` on methods |
|
||||||
|
| **Gin / chi / gorilla / mux** | `r.GET(…)`, `router.HandleFunc(…)` |
|
||||||
|
| **Axum / actix / Rocket** | `.route("/x", get(handler))` |
|
||||||
|
| **ASP.NET** | `[HttpGet("/x")]` attributes on action methods |
|
||||||
|
| **Vapor** | `app.get("x", use: handler)` |
|
||||||
|
| **React Router** / **SvelteKit** | Route component nodes |
|
||||||
|
|
||||||
|
Route resolution is automatic — there's nothing to configure. If a framework file is recognized, its routes appear in the graph after the next index or sync.
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
title: Indexing a Project
|
||||||
|
description: Full index, incremental sync, and the file watcher.
|
||||||
|
---
|
||||||
|
|
||||||
|
## Initialize and index
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd your-project
|
||||||
|
codegraph init -i # initialize + full index
|
||||||
|
```
|
||||||
|
|
||||||
|
`init` creates `.codegraph/`; `-i`/`--index` builds the index immediately. To initialize without indexing, drop the flag and run `codegraph index` later.
|
||||||
|
|
||||||
|
## Full vs. incremental
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph index # full index of the whole project
|
||||||
|
codegraph index --force # re-index from scratch
|
||||||
|
codegraph sync # incremental — only changed files
|
||||||
|
```
|
||||||
|
|
||||||
|
`sync` is fast because it only reparses what changed. Use it after a branch switch or a batch of edits.
|
||||||
|
|
||||||
|
## Stay fresh automatically
|
||||||
|
|
||||||
|
When the MCP server is running, CodeGraph watches your project with native OS file events and syncs in the background — debounced, and filtered to source files only. You don't need to run `sync` by hand during an agent session.
|
||||||
|
|
||||||
|
## Check status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph status
|
||||||
|
```
|
||||||
|
|
||||||
|
Reports node/edge/file counts, the active SQLite backend, and the journal mode.
|
||||||
|
|
||||||
|
## What gets indexed
|
||||||
|
|
||||||
|
Every file whose extension maps to a [supported language](/codegraph/reference/languages/), minus anything your `.gitignore` excludes and files over 1 MB. See [Configuration](/codegraph/getting-started/configuration/).
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
title: API
|
||||||
|
description: Use CodeGraph as a TypeScript library.
|
||||||
|
---
|
||||||
|
|
||||||
|
CodeGraph ships a TypeScript API. The public surface is the `CodeGraph` class.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import CodeGraph from '@colbymchenry/codegraph';
|
||||||
|
|
||||||
|
const cg = await CodeGraph.init('/path/to/project');
|
||||||
|
// Or open an existing index:
|
||||||
|
// const cg = await CodeGraph.open('/path/to/project');
|
||||||
|
|
||||||
|
await cg.indexAll({
|
||||||
|
onProgress: (p) => console.log(`${p.phase}: ${p.current}/${p.total}`),
|
||||||
|
});
|
||||||
|
|
||||||
|
const results = cg.searchNodes('UserService');
|
||||||
|
const callers = cg.getCallers(results[0].node.id);
|
||||||
|
const context = await cg.buildContext('fix login bug', {
|
||||||
|
maxNodes: 20,
|
||||||
|
includeCode: true,
|
||||||
|
format: 'markdown',
|
||||||
|
});
|
||||||
|
const impact = cg.getImpactRadius(results[0].node.id, 2);
|
||||||
|
|
||||||
|
cg.watch(); // auto-sync on file changes
|
||||||
|
cg.unwatch(); // stop watching
|
||||||
|
cg.close();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key methods
|
||||||
|
|
||||||
|
| Method | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `CodeGraph.init(path)` / `CodeGraph.open(path)` | Create or open a project index |
|
||||||
|
| `indexAll(opts)` | Full index, with progress callback |
|
||||||
|
| `sync()` | Incremental update |
|
||||||
|
| `searchNodes(query)` | Full-text symbol search |
|
||||||
|
| `getCallers(id)` / `getCallees(id)` | Walk the call graph |
|
||||||
|
| `getImpactRadius(id, depth)` | Transitive impact of a change |
|
||||||
|
| `buildContext(task, opts)` | Markdown / JSON context for AI |
|
||||||
|
| `watch()` / `unwatch()` | Start / stop the file watcher |
|
||||||
|
| `close()` | Close the database connection |
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
title: CLI
|
||||||
|
description: Every CodeGraph command and the flags it accepts.
|
||||||
|
---
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph # Run interactive installer
|
||||||
|
codegraph install # Run installer (explicit)
|
||||||
|
codegraph uninstall # Remove CodeGraph from your agents (inverse of install)
|
||||||
|
codegraph init [path] # Initialize in a project (--index to also index)
|
||||||
|
codegraph uninit [path] # Remove CodeGraph from a project (--force to skip prompt)
|
||||||
|
codegraph index [path] # Full index (--force to re-index, --quiet for less output)
|
||||||
|
codegraph sync [path] # Incremental update
|
||||||
|
codegraph status [path] # Show statistics
|
||||||
|
codegraph query <search> # Search symbols (--kind, --limit, --json)
|
||||||
|
codegraph files [path] # Show file structure (--format, --filter, --max-depth, --json)
|
||||||
|
codegraph context <task> # Build context for AI (--format, --max-nodes)
|
||||||
|
codegraph callers <symbol> # Find what calls a function/method (--limit, --json)
|
||||||
|
codegraph callees <symbol> # Find what a function/method calls (--limit, --json)
|
||||||
|
codegraph impact <symbol> # Analyze what code is affected by changing a symbol (--depth, --json)
|
||||||
|
codegraph affected [files...] # Find test files affected by changes
|
||||||
|
codegraph serve --mcp # Start MCP server
|
||||||
|
```
|
||||||
|
|
||||||
|
## Query commands
|
||||||
|
|
||||||
|
`query`, `callers`, `callees`, and `impact` all accept `--json` for machine-readable output.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph query UserService --kind class --limit 10
|
||||||
|
codegraph callers handleRequest --json
|
||||||
|
codegraph impact AuthMiddleware --depth 3
|
||||||
|
```
|
||||||
|
|
||||||
|
## affected
|
||||||
|
|
||||||
|
Traces import dependencies transitively to find which test files are affected by changed source files. See [Affected Tests in CI](/codegraph/guides/affected-tests/) for options and a CI example.
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
---
|
||||||
|
title: Integrations
|
||||||
|
description: Supported agents, and manual MCP setup.
|
||||||
|
---
|
||||||
|
|
||||||
|
The interactive installer auto-detects and configures each supported agent — wiring up the MCP server and writing its instructions file.
|
||||||
|
|
||||||
|
## Supported agents
|
||||||
|
|
||||||
|
- **Claude Code**
|
||||||
|
- **Cursor**
|
||||||
|
- **Codex CLI**
|
||||||
|
- **opencode**
|
||||||
|
- **Hermes Agent**
|
||||||
|
|
||||||
|
Run `npx @colbymchenry/codegraph` and pick your agent(s); see [Installation](/codegraph/getting-started/installation/) for the non-interactive flags.
|
||||||
|
|
||||||
|
## Manual setup
|
||||||
|
|
||||||
|
If you'd rather wire it up yourself, install globally:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -g @colbymchenry/codegraph
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the MCP server to `~/.claude.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"codegraph": {
|
||||||
|
"type": "stdio",
|
||||||
|
"command": "codegraph",
|
||||||
|
"args": ["serve", "--mcp"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Optionally auto-allow the read-only tools in `~/.claude/settings.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"mcp__codegraph__codegraph_search",
|
||||||
|
"mcp__codegraph__codegraph_context",
|
||||||
|
"mcp__codegraph__codegraph_callers",
|
||||||
|
"mcp__codegraph__codegraph_callees",
|
||||||
|
"mcp__codegraph__codegraph_impact",
|
||||||
|
"mcp__codegraph__codegraph_node",
|
||||||
|
"mcp__codegraph__codegraph_status",
|
||||||
|
"mcp__codegraph__codegraph_files"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Cursor launches MCP subprocesses with the wrong working directory. The installer handles this for you by injecting a `--path` argument; if you wire Cursor up by hand, pass the project path explicitly.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
title: Languages
|
||||||
|
description: Every language CodeGraph parses, and the extensions it recognizes.
|
||||||
|
---
|
||||||
|
|
||||||
|
Language support is automatic from the file extension — there's nothing to configure.
|
||||||
|
|
||||||
|
| Language | Extensions | Status |
|
||||||
|
|---|---|---|
|
||||||
|
| TypeScript | `.ts`, `.tsx` | Full support |
|
||||||
|
| JavaScript | `.js`, `.jsx`, `.mjs` | Full support |
|
||||||
|
| Python | `.py` | Full support |
|
||||||
|
| Go | `.go` | Full support |
|
||||||
|
| Rust | `.rs` | Full support |
|
||||||
|
| Java | `.java` | Full support |
|
||||||
|
| C# | `.cs` | Full support |
|
||||||
|
| PHP | `.php` | Full support |
|
||||||
|
| Ruby | `.rb` | Full support |
|
||||||
|
| C | `.c`, `.h` | Full support |
|
||||||
|
| C++ | `.cpp`, `.hpp`, `.cc` | Full support |
|
||||||
|
| Swift | `.swift` | Full support |
|
||||||
|
| Kotlin | `.kt`, `.kts` | Full support |
|
||||||
|
| Scala | `.scala`, `.sc` | Full support (classes, traits, methods, type aliases, Scala 3 enums) |
|
||||||
|
| Dart | `.dart` | Full support |
|
||||||
|
| Svelte | `.svelte` | Full support (script extraction, Svelte 5 runes, SvelteKit routes) |
|
||||||
|
| Vue | `.vue` | Full support (script + script-setup, Nuxt page/API/middleware routes) |
|
||||||
|
| Liquid | `.liquid` | Full support |
|
||||||
|
| Pascal / Delphi | `.pas`, `.dpr`, `.dpk`, `.lpr` | Full support (classes, records, interfaces, enums, DFM/FMX forms) |
|
||||||
|
| Lua | `.lua` | Full support (functions, methods, locals, `require` imports, call edges) |
|
||||||
|
| Luau | `.luau` | Full support (Lua, plus typed signatures, `type` aliases, Roblox `require`) |
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
title: MCP Server
|
||||||
|
description: The tools CodeGraph exposes to AI agents over MCP.
|
||||||
|
---
|
||||||
|
|
||||||
|
CodeGraph runs as a [Model Context Protocol](https://modelcontextprotocol.io/) server. Start it with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
codegraph serve --mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
Agents configured by the installer launch this automatically. When a `.codegraph/` index exists, the agent uses the tools below.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
| Tool | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `codegraph_search` | Find symbols by name across the codebase |
|
||||||
|
| `codegraph_context` | Build relevant code context for a task — composes search + node + callers + callees in one call |
|
||||||
|
| `codegraph_trace` | Trace the call path between two symbols ("how does X reach Y") in one call — each hop with its body inline, following dynamic-dispatch hops (callbacks, React re-render, interface→impl) that grep can't |
|
||||||
|
| `codegraph_callers` | Find what calls a function |
|
||||||
|
| `codegraph_callees` | Find what a function calls |
|
||||||
|
| `codegraph_impact` | Analyze what code is affected by changing a symbol |
|
||||||
|
| `codegraph_node` | Get details about a specific symbol (optionally with source code) |
|
||||||
|
| `codegraph_explore` | Return source for several related symbols grouped by file, plus a relationship map, in one call |
|
||||||
|
| `codegraph_files` | Get the indexed file structure (faster than filesystem scanning) |
|
||||||
|
| `codegraph_status` | Check index health and statistics |
|
||||||
|
|
||||||
|
## How agents should use it
|
||||||
|
|
||||||
|
CodeGraph *is* the pre-built search index. For "how does X work?", architecture, trace, or where-is-X questions, an agent should answer in a handful of CodeGraph calls and stop — typically with **zero file reads** — rather than re-deriving the answer with `grep` + `Read`. A direct CodeGraph answer is a handful of calls; a grep/read exploration is dozens.
|
||||||
|
|
||||||
|
The installer writes this guidance into each agent's instructions file automatically.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
title: Troubleshooting
|
||||||
|
description: Fixes for the most common CodeGraph issues.
|
||||||
|
---
|
||||||
|
|
||||||
|
## "CodeGraph not initialized"
|
||||||
|
|
||||||
|
Run `codegraph init` in your project directory first.
|
||||||
|
|
||||||
|
## Indexing is slow
|
||||||
|
|
||||||
|
Check that `node_modules` and other large directories are excluded (they are, if gitignored). Use `--quiet` to reduce output overhead.
|
||||||
|
|
||||||
|
## MCP hits `database is locked`
|
||||||
|
|
||||||
|
Current builds shouldn't: CodeGraph bundles its own Node runtime and uses Node's built-in `node:sqlite` in WAL mode, where concurrent reads never block on a writer. If you still see it:
|
||||||
|
|
||||||
|
- **You're on an old (pre-0.9) install.** Reinstall to get the bundled runtime — `curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh` (macOS/Linux), `irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 | iex` (Windows), or `npm i -g @colbymchenry/codegraph@latest`.
|
||||||
|
- **`codegraph status` shows `Journal:` other than `wal`** — WAL couldn't be enabled on this filesystem (common on network shares and WSL2 `/mnt`), so reads can block on writes. Move the project (with its `.codegraph/` folder) onto a local disk.
|
||||||
|
|
||||||
|
## MCP server not connecting
|
||||||
|
|
||||||
|
Ensure the project is initialized/indexed, verify the path in your MCP config, and check that `codegraph serve --mcp` works from the command line.
|
||||||
|
|
||||||
|
## Missing symbols
|
||||||
|
|
||||||
|
The MCP server auto-syncs on save (wait a couple of seconds). Run `codegraph sync` manually if needed. Check that the file's language is [supported](/codegraph/reference/languages/) and isn't excluded by `.gitignore`.
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Build-time GitHub star count. Fetched once when the site is built (the GitHub
|
||||||
|
* Actions runner has network); falls back to a constant locally / offline so a
|
||||||
|
* build never hangs or fails on the network. The result is memoized for the
|
||||||
|
* lifetime of the build process, so rendering it on every page is a single API
|
||||||
|
* call, not one per page.
|
||||||
|
*/
|
||||||
|
function format(n: number): string {
|
||||||
|
if (n >= 1000) {
|
||||||
|
const k = n / 1000;
|
||||||
|
const rounded = k >= 10 ? Math.round(k) : Math.round(k * 10) / 10;
|
||||||
|
return `${String(rounded).replace(/\.0$/, '')}k`;
|
||||||
|
}
|
||||||
|
return String(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchStars(fallback: string): Promise<string> {
|
||||||
|
try {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeout = setTimeout(() => controller.abort(), 3000);
|
||||||
|
const res = await fetch('https://api.github.com/repos/colbymchenry/codegraph', {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/vnd.github+json',
|
||||||
|
'User-Agent': 'codegraph-site',
|
||||||
|
},
|
||||||
|
signal: controller.signal,
|
||||||
|
});
|
||||||
|
clearTimeout(timeout);
|
||||||
|
if (!res.ok) return fallback;
|
||||||
|
const data = (await res.json()) as { stargazers_count?: number };
|
||||||
|
return typeof data.stargazers_count === 'number' ? format(data.stargazers_count) : fallback;
|
||||||
|
} catch {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let cached: Promise<string> | null = null;
|
||||||
|
|
||||||
|
export function getStarsLabel(fallback = '22k'): Promise<string> {
|
||||||
|
cached ??= fetchStars(fallback);
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
@@ -0,0 +1,430 @@
|
|||||||
|
---
|
||||||
|
import '@fontsource-variable/archivo';
|
||||||
|
import '@fontsource/ibm-plex-mono/400.css';
|
||||||
|
import '@fontsource/ibm-plex-mono/500.css';
|
||||||
|
import '@fontsource/ibm-plex-mono/600.css';
|
||||||
|
import '../styles/theme.css';
|
||||||
|
import GraphDiagram from '../components/GraphDiagram.astro';
|
||||||
|
import { getStarsLabel } from '../lib/github';
|
||||||
|
|
||||||
|
const base = import.meta.env.BASE_URL.replace(/\/$/, '');
|
||||||
|
const repo = 'https://github.com/colbymchenry/codegraph';
|
||||||
|
const npm = 'https://www.npmjs.com/package/@colbymchenry/codegraph';
|
||||||
|
const stars = await getStarsLabel();
|
||||||
|
const install = 'npx @colbymchenry/codegraph';
|
||||||
|
---
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="icon" href={`${base}/favicon.svg`} type="image/svg+xml" />
|
||||||
|
<title>codegraph — Understand any codebase as a graph</title>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="A local-first code-intelligence tool that turns any codebase into a queryable knowledge graph for AI coding agents."
|
||||||
|
/>
|
||||||
|
<meta property="og:title" content="codegraph" />
|
||||||
|
<meta property="og:description" content="Understand any codebase as a graph." />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta name="theme-color" content="#f7f6f2" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="frame">
|
||||||
|
<header class="nav">
|
||||||
|
<a class="wordmark" href={`${base}/`}>codegraph</a>
|
||||||
|
<nav class="nav-links">
|
||||||
|
<a href={`${base}/getting-started/introduction`}>Docs</a>
|
||||||
|
<a class="opt" href={`${base}/reference/languages`}>Languages</a>
|
||||||
|
<a href={repo}>GitHub</a>
|
||||||
|
<a class="star" href={`${repo}/stargazers`}>
|
||||||
|
<span class="star-glyph" aria-hidden="true">★</span>{stars}
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-left">
|
||||||
|
<h1>Understand any codebase as a graph</h1>
|
||||||
|
<p class="lede">
|
||||||
|
A local-first code-intelligence tool that turns any codebase into a
|
||||||
|
queryable knowledge graph for AI coding agents.
|
||||||
|
</p>
|
||||||
|
<div class="cta">
|
||||||
|
<a class="btn btn-primary" href={`${base}/getting-started/quickstart`}>Get started</a>
|
||||||
|
<a class="btn btn-ghost" href={`${base}/getting-started/introduction`}>View documentation</a>
|
||||||
|
</div>
|
||||||
|
<div class="install" data-install={install}>
|
||||||
|
<code>{install}</code>
|
||||||
|
<button class="copy" type="button" aria-label="Copy install command">
|
||||||
|
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6">
|
||||||
|
<rect x="9" y="9" width="11" height="11" />
|
||||||
|
<path d="M5 15V5a1 1 0 0 1 1-1h9" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hero-right">
|
||||||
|
<GraphDiagram />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="features">
|
||||||
|
<article class="feature">
|
||||||
|
<svg class="ficon" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||||
|
<rect x="19" y="4" width="10" height="10" />
|
||||||
|
<rect x="4" y="34" width="10" height="10" />
|
||||||
|
<rect x="19" y="34" width="10" height="10" />
|
||||||
|
<rect x="34" y="34" width="10" height="10" />
|
||||||
|
<path d="M24 14v10M9 34v-10h30v10M24 24v10" />
|
||||||
|
</svg>
|
||||||
|
<h2>Tree-sitter parsing</h2>
|
||||||
|
<p>
|
||||||
|
Fast, incremental parsing across 20+ languages — accurate symbols and
|
||||||
|
edges drawn from real ASTs, not guesses.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
<article class="feature">
|
||||||
|
<svg class="ficon" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||||
|
<rect x="5" y="10" width="38" height="28" />
|
||||||
|
<path d="M13 20l6 4-6 4M26 28h9" />
|
||||||
|
</svg>
|
||||||
|
<h2>MCP server</h2>
|
||||||
|
<p>
|
||||||
|
Expose the graph to Claude Code, Cursor, Codex, opencode, and Hermes
|
||||||
|
over MCP — agents answer in a handful of calls.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
<article class="feature">
|
||||||
|
<svg class="ficon" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||||
|
<circle cx="16" cy="24" r="10" />
|
||||||
|
<circle cx="16" cy="24" r="3.5" fill="currentColor" stroke="none" />
|
||||||
|
<path d="M16 8v6M16 34v6M2 24h4M26 24h6M32 24l8-6M32 24l8 6" />
|
||||||
|
<circle cx="41" cy="17" r="2.5" />
|
||||||
|
<circle cx="41" cy="31" r="2.5" />
|
||||||
|
</svg>
|
||||||
|
<h2>Impact analysis</h2>
|
||||||
|
<p>
|
||||||
|
Trace callers, callees, and the full impact radius of any symbol
|
||||||
|
before you change a line.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="foot">
|
||||||
|
<span class="foot-mark">codegraph</span>
|
||||||
|
<nav class="foot-links">
|
||||||
|
<a href={`${base}/getting-started/introduction`}>Docs</a>
|
||||||
|
<a href={repo}>GitHub</a>
|
||||||
|
<a href={npm}>npm</a>
|
||||||
|
<a href={`${repo}/blob/main/LICENSE`}>MIT</a>
|
||||||
|
</nav>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const wrap = document.querySelector('.install');
|
||||||
|
const btn = wrap?.querySelector('.copy');
|
||||||
|
if (wrap && btn) {
|
||||||
|
const original = btn.innerHTML;
|
||||||
|
btn.addEventListener('click', async () => {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(wrap.getAttribute('data-install') || '');
|
||||||
|
btn.innerHTML = '<span class="copied">Copied</span>';
|
||||||
|
setTimeout(() => (btn.innerHTML = original), 1400);
|
||||||
|
} catch {
|
||||||
|
/* clipboard blocked — no-op */
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:global(html) {
|
||||||
|
background: var(--cg-paper);
|
||||||
|
}
|
||||||
|
:global(body) {
|
||||||
|
margin: 0;
|
||||||
|
font-family: var(--sl-font);
|
||||||
|
color: var(--cg-ink);
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frame {
|
||||||
|
max-width: 1440px;
|
||||||
|
margin: 0 auto;
|
||||||
|
border: 1px solid var(--cg-rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- nav ---- */
|
||||||
|
.nav {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 1.1rem 2rem;
|
||||||
|
border-bottom: 1px solid var(--cg-rule);
|
||||||
|
}
|
||||||
|
.wordmark {
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
letter-spacing: -0.035em;
|
||||||
|
color: var(--cg-ink);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.nav-links {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
.nav-links a {
|
||||||
|
color: var(--cg-ink);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.98rem;
|
||||||
|
}
|
||||||
|
.nav-links a:not(.star):hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
text-underline-offset: 4px;
|
||||||
|
}
|
||||||
|
.star {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
border: 1px solid var(--cg-rule);
|
||||||
|
padding: 0.4rem 0.85rem;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
.star:hover {
|
||||||
|
background: var(--cg-paper-press);
|
||||||
|
}
|
||||||
|
.star-glyph {
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- hero ---- */
|
||||||
|
.hero {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.05fr 0.95fr;
|
||||||
|
border-bottom: 1px solid var(--cg-rule);
|
||||||
|
}
|
||||||
|
.hero-left {
|
||||||
|
padding: 4.5rem 3rem 4rem;
|
||||||
|
min-width: 0; /* allow the grid cell to shrink below content width */
|
||||||
|
}
|
||||||
|
.hero-right {
|
||||||
|
border-inline-start: 1px solid var(--cg-rule);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 2.5rem;
|
||||||
|
min-width: 0; /* let the SVG scale down instead of widening the page */
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: clamp(2.4rem, 6vw, 4.6rem);
|
||||||
|
line-height: 0.98;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: -0.04em;
|
||||||
|
margin: 0 0 1.6rem;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
.lede {
|
||||||
|
font-size: 1.18rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--cg-ink-2);
|
||||||
|
max-width: 34ch;
|
||||||
|
margin: 0 0 2.2rem;
|
||||||
|
}
|
||||||
|
.cta {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.9rem;
|
||||||
|
margin-bottom: 1.6rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.8rem 1.5rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
border: 1px solid var(--cg-rule);
|
||||||
|
transition:
|
||||||
|
background 0.12s ease,
|
||||||
|
color 0.12s ease;
|
||||||
|
}
|
||||||
|
.btn-primary {
|
||||||
|
background: var(--cg-ink);
|
||||||
|
color: var(--cg-paper);
|
||||||
|
}
|
||||||
|
.btn-primary:hover {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--cg-ink);
|
||||||
|
}
|
||||||
|
.btn-ghost {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--cg-ink);
|
||||||
|
}
|
||||||
|
.btn-ghost:hover {
|
||||||
|
background: var(--cg-paper-press);
|
||||||
|
}
|
||||||
|
.install {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
border: 1px solid var(--cg-rule);
|
||||||
|
padding: 0.5rem 0.55rem 0.5rem 0.9rem;
|
||||||
|
font-family: var(--sl-font-mono);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
.install code {
|
||||||
|
font-family: inherit;
|
||||||
|
background: none;
|
||||||
|
color: var(--cg-ink);
|
||||||
|
}
|
||||||
|
.copy {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0.3rem;
|
||||||
|
color: var(--cg-ink-2);
|
||||||
|
}
|
||||||
|
.copy:hover {
|
||||||
|
color: var(--cg-ink);
|
||||||
|
}
|
||||||
|
.copy :global(.copied) {
|
||||||
|
font-family: var(--sl-font);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- features ---- */
|
||||||
|
.features {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
.feature {
|
||||||
|
padding: 2.4rem 2rem 2.8rem;
|
||||||
|
}
|
||||||
|
.feature + .feature {
|
||||||
|
border-inline-start: 1px solid var(--cg-rule);
|
||||||
|
}
|
||||||
|
.ficon {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
margin-bottom: 1.2rem;
|
||||||
|
color: var(--cg-ink);
|
||||||
|
}
|
||||||
|
.feature h2 {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0 0 0.6rem;
|
||||||
|
}
|
||||||
|
.feature p {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.55;
|
||||||
|
color: var(--cg-ink-2);
|
||||||
|
margin: 0;
|
||||||
|
max-width: 34ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- footer ---- */
|
||||||
|
.foot {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 1.4rem 2rem;
|
||||||
|
border-top: 1px solid var(--cg-rule);
|
||||||
|
}
|
||||||
|
.foot-mark {
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
}
|
||||||
|
.foot-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 1.6rem;
|
||||||
|
}
|
||||||
|
.foot-links a {
|
||||||
|
color: var(--cg-ink-2);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.92rem;
|
||||||
|
}
|
||||||
|
.foot-links a:hover {
|
||||||
|
color: var(--cg-ink);
|
||||||
|
text-decoration: underline;
|
||||||
|
text-underline-offset: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- restrained entrance ---- */
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.hero-left > * {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(8px);
|
||||||
|
animation: cg-in 0.5s ease forwards;
|
||||||
|
}
|
||||||
|
.hero-left > *:nth-child(1) {
|
||||||
|
animation-delay: 0.04s;
|
||||||
|
}
|
||||||
|
.hero-left > *:nth-child(2) {
|
||||||
|
animation-delay: 0.1s;
|
||||||
|
}
|
||||||
|
.hero-left > *:nth-child(3) {
|
||||||
|
animation-delay: 0.16s;
|
||||||
|
}
|
||||||
|
.hero-left > *:nth-child(4) {
|
||||||
|
animation-delay: 0.22s;
|
||||||
|
}
|
||||||
|
@keyframes cg-in {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- responsive ---- */
|
||||||
|
@media (max-width: 860px) {
|
||||||
|
.hero {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
.hero-right {
|
||||||
|
border-inline-start: none;
|
||||||
|
border-top: 1px solid var(--cg-rule);
|
||||||
|
}
|
||||||
|
.features {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
.feature + .feature {
|
||||||
|
border-inline-start: none;
|
||||||
|
border-top: 1px solid var(--cg-rule);
|
||||||
|
}
|
||||||
|
.nav {
|
||||||
|
padding: 1rem 1.25rem;
|
||||||
|
}
|
||||||
|
.nav-links {
|
||||||
|
gap: 0.85rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
.nav-links .opt {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.star {
|
||||||
|
display: none; /* count still lives on the GitHub page */
|
||||||
|
}
|
||||||
|
.hero-left {
|
||||||
|
padding: 2.75rem 1.25rem 2.5rem;
|
||||||
|
}
|
||||||
|
.foot {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
/* =====================================================================
|
||||||
|
codegraph — flat / paper editorial theme
|
||||||
|
Monochrome ink-on-paper, hairline rules, square corners. Shared by the
|
||||||
|
custom landing page (src/pages/index.astro) and the Starlight docs.
|
||||||
|
===================================================================== */
|
||||||
|
|
||||||
|
/* ---- Fonts ---- */
|
||||||
|
:root {
|
||||||
|
--sl-font: 'Archivo Variable', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
--sl-font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Starlight colour mapping: light / paper (default) ---- */
|
||||||
|
:root,
|
||||||
|
:root[data-theme='light'] {
|
||||||
|
--sl-color-accent-low: #e2dfd5;
|
||||||
|
--sl-color-accent: #16150f;
|
||||||
|
--sl-color-accent-high: #16150f;
|
||||||
|
--sl-color-white: #16150f;
|
||||||
|
--sl-color-gray-1: #2a281f;
|
||||||
|
--sl-color-gray-2: #56544a;
|
||||||
|
--sl-color-gray-3: #6f6c61;
|
||||||
|
--sl-color-gray-4: #87847a;
|
||||||
|
--sl-color-gray-5: #b4b1a5;
|
||||||
|
--sl-color-gray-6: #d6d3c8;
|
||||||
|
--sl-color-gray-7: #e8e6dd;
|
||||||
|
--sl-color-black: #f7f6f2;
|
||||||
|
|
||||||
|
--sl-color-bg: #f7f6f2;
|
||||||
|
--sl-color-bg-nav: #f7f6f2;
|
||||||
|
--sl-color-bg-sidebar: #f7f6f2;
|
||||||
|
--sl-color-bg-inline-code: #e8e6dd;
|
||||||
|
--sl-color-bg-accent: #16150f;
|
||||||
|
|
||||||
|
--sl-color-text: #16150f;
|
||||||
|
--sl-color-text-accent: #16150f;
|
||||||
|
--sl-color-text-invert: #f7f6f2;
|
||||||
|
|
||||||
|
--sl-color-hairline: #16150f;
|
||||||
|
--sl-color-hairline-light: #d6d3c8;
|
||||||
|
--sl-color-hairline-shade: #d6d3c8;
|
||||||
|
|
||||||
|
/* shared tokens */
|
||||||
|
--cg-paper: #f7f6f2;
|
||||||
|
--cg-paper-2: #f1efe8;
|
||||||
|
--cg-paper-press: #e8e6dd;
|
||||||
|
--cg-ink: #16150f;
|
||||||
|
--cg-ink-2: #56544a;
|
||||||
|
--cg-ink-3: #87847a;
|
||||||
|
--cg-rule: #16150f;
|
||||||
|
--cg-rule-soft: #d6d3c8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Starlight colour mapping: dark / ink ---- */
|
||||||
|
:root[data-theme='dark'] {
|
||||||
|
--sl-color-accent-low: #34322a;
|
||||||
|
--sl-color-accent: #f3f1ea;
|
||||||
|
--sl-color-accent-high: #f3f1ea;
|
||||||
|
--sl-color-white: #f3f1ea;
|
||||||
|
--sl-color-gray-1: #e7e5dc;
|
||||||
|
--sl-color-gray-2: #c9c6ba;
|
||||||
|
--sl-color-gray-3: #a7a499;
|
||||||
|
--sl-color-gray-4: #7c7a70;
|
||||||
|
--sl-color-gray-5: #57554c;
|
||||||
|
--sl-color-gray-6: #2c2a23;
|
||||||
|
--sl-color-gray-7: #1e1c16;
|
||||||
|
--sl-color-black: #16150f;
|
||||||
|
|
||||||
|
--sl-color-bg: #16150f;
|
||||||
|
--sl-color-bg-nav: #16150f;
|
||||||
|
--sl-color-bg-sidebar: #16150f;
|
||||||
|
--sl-color-bg-inline-code: #23211a;
|
||||||
|
--sl-color-bg-accent: #f3f1ea;
|
||||||
|
|
||||||
|
--sl-color-text: #f3f1ea;
|
||||||
|
--sl-color-text-accent: #f3f1ea;
|
||||||
|
--sl-color-text-invert: #16150f;
|
||||||
|
|
||||||
|
--sl-color-hairline: #f3f1ea;
|
||||||
|
--sl-color-hairline-light: #34322a;
|
||||||
|
--sl-color-hairline-shade: #34322a;
|
||||||
|
|
||||||
|
--cg-paper: #16150f;
|
||||||
|
--cg-paper-2: #1e1c16;
|
||||||
|
--cg-paper-press: #23211a;
|
||||||
|
--cg-ink: #f3f1ea;
|
||||||
|
--cg-ink-2: #b8b5a8;
|
||||||
|
--cg-ink-3: #87847a;
|
||||||
|
--cg-rule: #f3f1ea;
|
||||||
|
--cg-rule-soft: #34322a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Global flat resets ---- */
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
border-radius: 0 !important; /* this design has no rounded corners, anywhere */
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--sl-shadow-sm: none;
|
||||||
|
--sl-shadow-md: none;
|
||||||
|
--sl-shadow-lg: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: var(--cg-paper);
|
||||||
|
color: var(--cg-ink);
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
:where(h1, h2, h3, h4, h5) {
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Docs chrome ---- */
|
||||||
|
|
||||||
|
/* Header: one crisp bottom rule. Starlight nests <div class="header"> inside
|
||||||
|
<header class="header">, so a bare `.header { border-bottom }` draws two
|
||||||
|
lines — put the rule on the outer <header> only and clear the inner div. */
|
||||||
|
.header {
|
||||||
|
background: var(--cg-paper);
|
||||||
|
-webkit-backdrop-filter: none;
|
||||||
|
backdrop-filter: none;
|
||||||
|
}
|
||||||
|
header.header {
|
||||||
|
border-bottom: 1px solid var(--cg-rule);
|
||||||
|
}
|
||||||
|
.header .header {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sidebar: crisp right rule */
|
||||||
|
#starlight__sidebar,
|
||||||
|
.sidebar-pane {
|
||||||
|
border-inline-end: 1px solid var(--cg-rule);
|
||||||
|
background: var(--cg-paper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sidebar group labels — small caps, committed editorial direction */
|
||||||
|
.sidebar-content details > summary,
|
||||||
|
.sidebar-content > ul > li > span,
|
||||||
|
.sidebar-content .large {
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.07em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
color: var(--cg-ink-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sidebar links */
|
||||||
|
.sidebar-content a {
|
||||||
|
color: var(--cg-ink-2);
|
||||||
|
}
|
||||||
|
.sidebar-content a:hover {
|
||||||
|
background: var(--cg-paper-press);
|
||||||
|
color: var(--cg-ink);
|
||||||
|
}
|
||||||
|
.sidebar-content a[aria-current='page'],
|
||||||
|
.sidebar-content a[aria-current='page']:hover {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--cg-ink);
|
||||||
|
font-weight: 700;
|
||||||
|
border-inline-start: 2px solid var(--cg-ink);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Right "On this page" rail */
|
||||||
|
starlight-toc a {
|
||||||
|
color: var(--cg-ink-3);
|
||||||
|
}
|
||||||
|
starlight-toc a[aria-current='true'] {
|
||||||
|
color: var(--cg-ink);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prev / next pagination: flat bordered boxes */
|
||||||
|
.pagination-links a {
|
||||||
|
border: 1px solid var(--cg-rule);
|
||||||
|
box-shadow: none;
|
||||||
|
background: var(--cg-paper);
|
||||||
|
}
|
||||||
|
.pagination-links a:hover {
|
||||||
|
background: var(--cg-paper-press);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
.sl-markdown-content :not(pre) > code {
|
||||||
|
border: 1px solid var(--cg-rule-soft);
|
||||||
|
background: var(--cg-paper-2);
|
||||||
|
font-size: 0.875em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cards / asides: square, hairline */
|
||||||
|
.card,
|
||||||
|
.starlight-aside {
|
||||||
|
border: 1px solid var(--cg-rule);
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search trigger */
|
||||||
|
button[data-open-modal] {
|
||||||
|
border: 1px solid var(--cg-rule);
|
||||||
|
background: var(--cg-paper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content horizontal rules */
|
||||||
|
.sl-markdown-content hr {
|
||||||
|
border: 0;
|
||||||
|
border-top: 1px solid var(--cg-rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links in prose */
|
||||||
|
.sl-markdown-content a {
|
||||||
|
color: var(--cg-ink);
|
||||||
|
text-underline-offset: 3px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "astro/tsconfigs/strict",
|
||||||
|
"include": [".astro/types.d.ts", "**/*"],
|
||||||
|
"exclude": ["dist"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user