chore: import upstream snapshot with attribution
This commit is contained in:
@@ -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,70 @@
|
||||
---
|
||||
// Docs-header right cluster: Docs + Languages text links, Starlight's default
|
||||
// social icons (the GitHub link), and a live star-count pill — same order as
|
||||
// the landing nav (Docs · Languages · GitHub · Star). Done here, in the slot we
|
||||
// already own, to avoid a full header rebuild that could break search/mobile.
|
||||
import Default from '@astrojs/starlight/components/SocialIcons.astro';
|
||||
import { getStarsLabel } from '../lib/github';
|
||||
|
||||
const stars = await getStarsLabel();
|
||||
const base = import.meta.env.BASE_URL.replace(/\/$/, '');
|
||||
const repo = 'https://github.com/colbymchenry/codegraph';
|
||||
---
|
||||
|
||||
<a class="cg-navlink" href={`${base}/getting-started/introduction/`}>Docs</a>
|
||||
<a class="cg-navlink" href={`${base}/reference/languages/`}>Languages</a>
|
||||
<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-navlink {
|
||||
font-family: var(--sl-font);
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: var(--cg-ink);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.cg-navlink:hover {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 4px;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
/* Keep the compact mobile header clean — the sidebar covers navigation there. */
|
||||
@media (max-width: 50rem) {
|
||||
.cg-navlink,
|
||||
.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, using Node's built-in `node:sqlite` in WAL mode from the bundled runtime.
|
||||
|
||||
## 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 `explore` and the `node` trail, 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.
|
||||
- **Explore** returns source for several related symbols grouped by file, plus the call path among them, 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)
|
||||
- Interface → implementation dispatch
|
||||
|
||||
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,97 @@
|
||||
---
|
||||
title: Configuration
|
||||
description: CodeGraph is zero-config by default, with one optional codegraph.json for custom extensions, excluding tracked directories, indexing gitignored source, and indexing nested git repositories.
|
||||
---
|
||||
|
||||
Next to none — CodeGraph is **zero-config by default**, with nothing to write or keep in sync to get started. Language support is automatic from the file extension; there's nothing to wire up per language. The one optional file, `codegraph.json`, covers [custom file extensions](#custom-file-extensions), [excluding tracked directories](#excluding-a-tracked-directory), [indexing gitignored source](#indexing-gitignored-source-a-second-vcs), and [indexing nested git repositories](#indexing-nested-git-repositories).
|
||||
|
||||
## What it skips out of the box
|
||||
|
||||
- **Dependency, build, and cache directories** — `node_modules`, `vendor`, `dist`, `build`, `target`, `.venv`, `Pods`, `.next`, and the like across every [supported stack](/codegraph/reference/languages/) — so the graph is your code, not third-party noise. This holds even with no `.gitignore`.
|
||||
- **Anything in your `.gitignore`** — honored in git repos via git, and in non-git projects by reading `.gitignore` directly (root and nested).
|
||||
- **Files larger than 1 MB** — generated bundles, minified JS, vendored blobs.
|
||||
|
||||
## Excluding or including more
|
||||
|
||||
To keep something else out, add it to `.gitignore`. To pull a default-excluded directory back **in** (e.g. you really want a vendored dependency indexed), add a negation — `!vendor/`.
|
||||
|
||||
The defaults apply uniformly, so committing a dependency or build directory doesn't force it into the graph — the `.gitignore` negation is the explicit opt-in.
|
||||
|
||||
## Excluding a tracked directory
|
||||
|
||||
`.gitignore` only affects files git **doesn't already track** — it can't drop a directory you've committed. So a vendored theme, SDK, or asset bundle that's checked into the repo (say a Metronic admin theme under `static/`, with hundreds of `.js` files) can't be excluded that way. For those, list them under `exclude` in `codegraph.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"exclude": ["static/", "**/vendor/**"]
|
||||
}
|
||||
```
|
||||
|
||||
Each entry is a gitignore-style pattern, matched against project-root-relative paths, and honored everywhere CodeGraph looks at files — the full index, incremental `sync`, and file-watching. It applies even to tracked files (that's the whole point) and takes precedence over everything else, so it's the right tool for a large committed dependency that bloats the graph but isn't really your code. (This is the opposite of [`includeIgnored`](#indexing-nested-git-repositories), which pulls gitignored directories back *in*.)
|
||||
|
||||
Re-index (`codegraph index`) after adding or changing `exclude`.
|
||||
|
||||
## Indexing gitignored source (a second VCS)
|
||||
|
||||
`.gitignore` keeps files out of the index — which is usually what you want, but not when the gitignored files are real first-party source. The case this exists for: a project tracked by **SVN, Perforce, or another VCS alongside Git**, where some source is committed to that VCS and deliberately listed in `.gitignore` so it never lands in Git. That source is still yours and you want it in the graph, but git never lists it, so CodeGraph never sees it. (`includeIgnored` doesn't help — it only revives *embedded git repositories* inside a gitignored directory, not plain source.)
|
||||
|
||||
List those paths under `include` in `codegraph.json` to force them in:
|
||||
|
||||
```json
|
||||
{
|
||||
"include": ["Tools/", "Local/typescript/"]
|
||||
}
|
||||
```
|
||||
|
||||
Each entry is a gitignore-style pattern, matched against project-root-relative paths (a directory like `"Tools/"`, a recursive `"Tools/**"` glob, or a single file all work). CodeGraph discovers the matching files directly off disk — overriding `.gitignore` — and indexes them everywhere it looks at files: the full index, incremental `sync`, and file-watching.
|
||||
|
||||
A few things to know:
|
||||
|
||||
- An explicit [`exclude`](#excluding-a-tracked-directory) still wins — listing the same path in both keeps it out.
|
||||
- Built-in skips like `node_modules`, `dist`, and `.git` are never re-included, even when an `include` pattern would match inside them.
|
||||
- This is the opposite of `exclude` (which keeps tracked files *out*); it's for source git itself never tracks.
|
||||
|
||||
Re-index (`codegraph index`) after adding or changing `include`.
|
||||
|
||||
## Custom file extensions
|
||||
|
||||
If your project uses a non-standard extension for a [supported language](/codegraph/reference/languages/) — say `.dota_lua` for Lua, or `.tpl` for PHP — those files are skipped by default, because the extension isn't one CodeGraph recognizes. Map them with an optional `codegraph.json` at your project root:
|
||||
|
||||
```json
|
||||
{
|
||||
"extensions": {
|
||||
".dota_lua": "lua",
|
||||
".tpl": "php"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each value is a supported language id. The mappings merge on top of the built-in defaults and win on conflict, so you can also re-point a built-in (e.g. `".h": "cpp"`). Commit the file to share the mapping with your team.
|
||||
|
||||
A typo'd language or a malformed file is warned about and skipped — it never breaks indexing — and a project with no `codegraph.json` behaves exactly as before. Re-index (`codegraph index`) after adding or changing mappings.
|
||||
|
||||
## Indexing nested git repositories
|
||||
|
||||
CodeGraph respects your `.gitignore`, so a directory you've gitignored stays out of the graph — **including any git repositories nested inside it.** If you keep cloned reference projects, vendored copies, or a folder of unrelated repos in a gitignored directory (a `resource/`, `.repos/`, or `examples/` dir), CodeGraph leaves it untouched: it won't walk in, discover the embedded repos, or index them.
|
||||
|
||||
If instead you run a **"super-repo" of independent clones** — a workspace whose own `.gitignore` lists its child repos to keep `git status` quiet, where you genuinely want every child indexed into one graph — opt those directories back in with `includeIgnored`:
|
||||
|
||||
```json
|
||||
{
|
||||
"includeIgnored": ["packages/", "services/"]
|
||||
}
|
||||
```
|
||||
|
||||
Each entry is a gitignore-style pattern naming a gitignored directory whose nested git repositories should be indexed anyway. CodeGraph descends into the directories you list and indexes each embedded repo by its own `git ls-files`, so every child repo's own `.gitignore` is still honored. Directories you don't list stay excluded.
|
||||
|
||||
A few things to know:
|
||||
|
||||
- **Untracked** nested repositories (ones you haven't gitignored) are indexed automatically — `includeIgnored` is only for the ones your `.gitignore` excludes.
|
||||
- Built-in skips like `node_modules` are never re-included, even inside an opted-in directory.
|
||||
- A project without this layout needs no `codegraph.json` at all.
|
||||
|
||||
Re-index (`codegraph index`) after adding or changing `includeIgnored`.
|
||||
|
||||
## 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,70 @@
|
||||
---
|
||||
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**, **Hermes Agent**, **Gemini CLI**, **Antigravity IDE**, and **Kiro**.
|
||||
- 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 a small marker-fenced CodeGraph section in the agent's instructions file (`CLAUDE.md` / `AGENTS.md` / `GEMINI.md`). Cursor and Kiro get the MCP config only. Removed cleanly by `codegraph uninstall`.
|
||||
- Set up auto-allow permissions when Claude Code is one of the targets.
|
||||
|
||||
The installer **wires up your agents only — it does not index your code.** After it finishes, build each project's graph yourself with `codegraph init` (step 3 below).
|
||||
|
||||
## 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 / Gemini CLI / Antigravity IDE / Kiro) for the MCP server to load.
|
||||
|
||||
## 3. Initialize projects
|
||||
|
||||
```bash
|
||||
cd your-project
|
||||
codegraph init
|
||||
```
|
||||
|
||||
`codegraph init` creates the local `.codegraph/` directory and builds the full graph in the same step — one command. A single global `codegraph install` covers every project; you run `codegraph init` once per project.
|
||||
|
||||
## 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,34 @@
|
||||
---
|
||||
title: Introduction
|
||||
description: What CodeGraph is, and why it makes AI coding agents faster and more precise.
|
||||
---
|
||||
|
||||
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, Hermes Agent, Gemini CLI, Antigravity IDE, and Kiro — **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: it hands the agent the exact code it needs in one call, so symbol relationships, call graphs, and structure don't have to be rebuilt file by file.
|
||||
|
||||
The universal win is **surgical context and speed** — fewer tool calls, faster answers, on every codebase. Tested across 7 real-world open-source codebases (median of 4 runs per arm), giving an agent CodeGraph meant, regardless of repo size:
|
||||
|
||||
- **58% fewer tool calls**
|
||||
- **22% faster**
|
||||
- **file reads cut to ~zero**
|
||||
|
||||
Token and dollar savings are real too, but they're the **scale-dependent bonus** that shows up on large, tangled codebases run at volume — small and noisy on a modest repo, material only once the codebase (and the team) gets big.
|
||||
|
||||
## 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,39 @@
|
||||
---
|
||||
title: Get Started
|
||||
description: Get up and running with CodeGraph in seconds.
|
||||
---
|
||||
|
||||
Get up and running with CodeGraph in seconds.
|
||||
|
||||
## 1. Install the CLI
|
||||
|
||||
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? `npm i -g @colbymchenry/codegraph` works on any version. CodeGraph bundles its own runtime — nothing to compile, no native build, works the same everywhere. The installer puts `codegraph` on your `PATH` but doesn't change your current shell — open a new terminal before the next step.
|
||||
|
||||
## 2. Wire up your agent(s)
|
||||
|
||||
```bash
|
||||
codegraph install
|
||||
```
|
||||
|
||||
Auto-detects and configures Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Gemini CLI, Antigravity IDE, and Kiro — wiring the CodeGraph MCP server into each. This step connects your agents only; it does **not** index any code. (Shortcut: `npx @colbymchenry/codegraph` downloads and runs the installer in one go.)
|
||||
|
||||
## 3. Initialize each project
|
||||
|
||||
```bash
|
||||
cd your-project
|
||||
codegraph init
|
||||
```
|
||||
|
||||
`codegraph init` creates the local `.codegraph/` directory and builds the full graph in the same step — one command, done. 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,51 @@
|
||||
---
|
||||
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 a few commands.
|
||||
|
||||
## Index a project
|
||||
|
||||
```bash
|
||||
cd your-project
|
||||
codegraph init
|
||||
```
|
||||
|
||||
`codegraph init` creates the `.codegraph/` directory and builds the full graph in the same step — one command, done. From there a native file watcher keeps the index in sync on every change, so you rarely need to rebuild by hand. When you do want to:
|
||||
|
||||
```bash
|
||||
codegraph index # full re-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
|
||||
|
||||
Reach for `codegraph explore` first — a natural-language question or a bag of symbol names returns the relevant source plus the call paths between those symbols in a single shot (the same output the `codegraph_explore` tool gives your agent):
|
||||
|
||||
```bash
|
||||
codegraph explore "how does login work"
|
||||
```
|
||||
|
||||
For narrower, scriptable lookups there are focused commands:
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
These four each accept `--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,28 @@
|
||||
---
|
||||
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 `@Resolver` + `@Query/@Mutation`, `@MessagePattern`/`@EventPattern`, `@SubscribeMessage` |
|
||||
| **Laravel** | `Route::get()`, `Route::resource()`, `Controller@action`, tuple syntax |
|
||||
| **Drupal** | `*.routing.yml` routes (`_controller`, `_form`, entity handlers); `hook_*` implementations in `.module`/`.theme`/`.install`/`.inc` |
|
||||
| **Rails** | `get '/x', to: 'users#index'`, hash-rocket `=>` syntax |
|
||||
| **Spring** | `@GetMapping`, `@PostMapping`, `@RequestMapping` on methods |
|
||||
| **Play** | `GET`/`POST`/… verb routes in `conf/routes` → `Controller.method` actions (Scala + Java) |
|
||||
| **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 |
|
||||
| **Vue Router** / **Nuxt** | `pages/` file-based routes, `server/api/` endpoints, route middleware |
|
||||
| **Astro** | `src/pages/` file-based routes (`.astro` pages + `.ts` endpoints, `[param]`/`[...rest]` syntax) |
|
||||
|
||||
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,101 @@
|
||||
---
|
||||
title: Indexing a Project
|
||||
description: Full index, incremental sync, and the file watcher.
|
||||
---
|
||||
|
||||
## Initialize and index
|
||||
|
||||
```bash
|
||||
cd your-project
|
||||
codegraph init # creates .codegraph/ and builds the full graph — one step
|
||||
```
|
||||
|
||||
`codegraph init` creates the local `.codegraph/` directory and builds the full graph in the same step — one command, done. There's no separate index step to run afterward, and from here the graph [stays fresh automatically](#stay-fresh-automatically).
|
||||
|
||||
## 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 — it's what the file watcher runs for you on every edit (see [Stay fresh automatically](#stay-fresh-automatically)). You rarely need to run it by hand.
|
||||
|
||||
## Stay fresh automatically
|
||||
|
||||
**You don't need to run `codegraph sync` by hand during an agent session.** When your agent (Claude Code, Cursor, Codex, opencode, Hermes, Gemini, Antigravity, Kiro) launches `codegraph serve --mcp`, three layers cooperate to keep the index in step with your code — and to never give the agent a quiet wrong answer in the small window between an edit and the next sync.
|
||||
|
||||
### 1. File watcher with debounced auto-sync (always on)
|
||||
|
||||
`serve --mcp` spins up a native file watcher (FSEvents on macOS, inotify on Linux, ReadDirectoryChangesW on Windows) over the project root. Every source-file create / modify / delete is captured. A debounce timer collapses bursts of edits into a single sync.
|
||||
|
||||
```
|
||||
agent writes src/Widget.ts
|
||||
→ watcher fires (event delivery: typically <100ms)
|
||||
→ 2000ms debounce
|
||||
→ sync runs; Widget.ts's nodes + edges are in the index
|
||||
→ next agent query sees it
|
||||
```
|
||||
|
||||
**Tunable**: `CODEGRAPH_WATCH_DEBOUNCE_MS` overrides the default 2000ms, clamped to `[100ms, 60s]`. Useful when a build step or formatter writes many files in a tight burst — bump it to `5000` or `10000` so the watcher coalesces them into one sync.
|
||||
|
||||
### 2. Per-file staleness banner — covers the debounce window
|
||||
|
||||
The watcher debounce introduces a small window (typically 2s) where a freshly-edited file is on disk but not yet in the index. CodeGraph closes that window with a per-file staleness banner: if any MCP tool response would reference a file that's currently pending re-index, the response prepends a `⚠️` banner naming the stale file:
|
||||
|
||||
```
|
||||
⚠️ Some files referenced below were edited since the last index sync —
|
||||
their codegraph entries may be stale:
|
||||
- src/Widget.ts (edited 800ms ago, pending sync)
|
||||
For accurate content of those specific files, Read them directly.
|
||||
The rest of this response is fresh.
|
||||
|
||||
## Code Context
|
||||
…
|
||||
```
|
||||
|
||||
Agents read this and follow up with a direct `Read` on the named file — validated end-to-end with Claude Code, where the agent literally says "Reading the file directly for the live content" before opening it. So even during the 2-second debounce window, the agent never gets a silent wrong answer.
|
||||
|
||||
Pending files **not** referenced by the response surface as a small footer instead (`(Note: N file(s) elsewhere in this project are pending index sync but were not referenced above: …)`). Either way, the signal is explicit.
|
||||
|
||||
### 3. Connect-time catch-up — covers gaps when the MCP server wasn't running
|
||||
|
||||
When your editor / agent (re)connects to the MCP server, codegraph runs a fast filesystem-based reconciliation (a `(size, mtime)` stat pre-filter, then a content hash on the rest) before answering the first query. So files changed while no MCP server was running — a `git pull` from the terminal, an edit from another editor, an agent that finished and exited — are caught up automatically on the next session's first tool call.
|
||||
|
||||
### Verify what the watcher sees
|
||||
|
||||
`codegraph_status` exposes the pending set first-class — useful for an agent asking "is the index caught up?" in one call:
|
||||
|
||||
```
|
||||
codegraph_status →
|
||||
## CodeGraph Status
|
||||
…
|
||||
### Pending sync:
|
||||
- src/Widget.ts (edited 1200ms ago)
|
||||
```
|
||||
|
||||
If `### Pending sync:` isn't in the response, nothing is in flight.
|
||||
|
||||
### When manual `codegraph sync` makes sense
|
||||
|
||||
Almost never. The edge cases:
|
||||
|
||||
- **The watcher is disabled.** Sandboxes that block local fs watchers, or you've set `CODEGRAPH_NO_DAEMON=1` to opt out of the shared daemon. In those cases `codegraph sync` is the manual fallback.
|
||||
- **Pre-flight before a CI run.** If you're scripting against the index outside an agent session, a single `codegraph sync` at the start of the script guarantees the index reflects the current working tree.
|
||||
|
||||
Otherwise: just use it. The watcher + banner + connect-sync covers the AI-assisted workflow end-to-end. If you're seeing files genuinely missed after the debounce window has passed, that's a bug — please file an issue with a reproduction.
|
||||
|
||||
> See the v0.9.5 release notes for the [staleness banner (#403)](https://github.com/colbymchenry/codegraph/releases/tag/v0.9.5) and the connect-time catch-up (#414); both shipped together.
|
||||
|
||||
## Check status
|
||||
|
||||
```bash
|
||||
codegraph status
|
||||
```
|
||||
|
||||
Reports node/edge/file counts, the active SQLite backend, and the journal mode. In an agent session, the MCP-side `codegraph_status` additionally surfaces the `### Pending sync:` block described above.
|
||||
|
||||
## What gets indexed
|
||||
|
||||
Every file whose extension maps to a [supported language](/codegraph/reference/languages/), minus dependency/build directories excluded by default (`node_modules`, `vendor`, `dist`, …), anything your `.gitignore` excludes, and files over 1 MB. See [Configuration](/codegraph/getting-started/configuration/).
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
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 |
|
||||
|
||||
CommonJS works too — `const { CodeGraph } = require('@colbymchenry/codegraph');`.
|
||||
|
||||
## Lower-level building blocks
|
||||
|
||||
The same entry point exports primitives for callers that drive the graph directly rather than through the `CodeGraph` facade: `DatabaseConnection`, `QueryBuilder`, `getDatabasePath`, `initGrammars` / `loadGrammarsForLanguages`, and `FileLock`.
|
||||
|
||||
```typescript
|
||||
import {
|
||||
CodeGraph,
|
||||
DatabaseConnection,
|
||||
QueryBuilder,
|
||||
getDatabasePath,
|
||||
initGrammars,
|
||||
loadGrammarsForLanguages,
|
||||
FileLock,
|
||||
} from '@colbymchenry/codegraph';
|
||||
```
|
||||
|
||||
## Embedding requirements
|
||||
|
||||
- **Install from npm** (`npm i @colbymchenry/codegraph`) so the matching per-platform package — which carries the compiled library — is fetched alongside the shim.
|
||||
- The API runs on **your** runtime, so it needs **Node 22.5+** for the built-in `node:sqlite` module (an Electron main process qualifies when its bundled Node is 22.5+). The CLI and MCP server are unaffected — they ship with a self-contained bundled runtime and need no Node at all.
|
||||
- TypeScript types ship with the package. Keep `@types/node` available and `skipLibCheck: true` (the common default).
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
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 a project + build its graph (one step)
|
||||
codegraph uninit [path] # Remove CodeGraph from a project (--force to skip prompt)
|
||||
codegraph index [path] # Full re-index from scratch (--force, --quiet, --verbose)
|
||||
codegraph sync [path] # Incremental update (--quiet)
|
||||
codegraph status [path] # Show statistics (--json)
|
||||
codegraph unlock [path] # Remove a stale lock file that's blocking indexing
|
||||
codegraph query <search> # Search symbols (--kind, --limit, --json)
|
||||
codegraph explore <query> # Relevant symbols' source + call paths in one shot (same output as the codegraph_explore MCP tool)
|
||||
codegraph node <symbol|file> # One symbol's source + callers, or read a file with line numbers (same output as codegraph_node)
|
||||
codegraph files [path] # Show file structure (--format, --filter, --pattern, --max-depth, --json)
|
||||
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 (see below)
|
||||
codegraph daemon # Manage background daemons — pick one to stop (alias: daemons)
|
||||
codegraph telemetry [on|off] # Show or change anonymous usage telemetry
|
||||
codegraph upgrade [version] # Update to the latest release (--check, --force)
|
||||
codegraph version # Print the installed version (also -v, --version)
|
||||
codegraph help [command] # Show help, optionally for one command
|
||||
```
|
||||
|
||||
The MCP server (`codegraph serve --mcp`) is launched automatically by your agent — you don't run it by hand. See [MCP Server](/codegraph/reference/mcp-server/).
|
||||
|
||||
## init, index, and sync
|
||||
|
||||
`codegraph init` creates the local `.codegraph/` directory **and** builds the full graph in one step. (The old `-i`/`--index` flag is now a no-op, accepted only so existing scripts don't break.) After that the file watcher keeps the graph current automatically — `index` (a full rebuild from scratch) and `sync` (an incremental update) are only needed when the watcher is disabled or you're scripting against the index outside an agent session.
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
`explore` and `node` are the CLI faces of the `codegraph_explore` and `codegraph_node` MCP tools — same output — so subagents and non-MCP harnesses can reach the graph from a shell.
|
||||
|
||||
## 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,59 @@
|
||||
---
|
||||
title: Integrations
|
||||
description: Supported agents, and manual MCP setup.
|
||||
---
|
||||
|
||||
The interactive installer auto-detects and configures each supported agent — wiring the CodeGraph MCP server into each. For the agents that use an instructions file, it also writes a short marker-fenced CodeGraph section (`CLAUDE.md`, `AGENTS.md`, or `GEMINI.md`) so subagents and non-MCP harnesses learn the `codegraph explore` command; `codegraph uninstall` removes it.
|
||||
|
||||
## Supported agents
|
||||
|
||||
- **Claude Code**
|
||||
- **Cursor**
|
||||
- **Codex CLI**
|
||||
- **opencode**
|
||||
- **Hermes Agent**
|
||||
- **Gemini CLI**
|
||||
- **Antigravity IDE**
|
||||
- **Kiro**
|
||||
|
||||
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 CodeGraph's tools in `~/.claude/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"mcp__codegraph__*"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
One wildcard auto-approves every CodeGraph tool. The server lists a single tool by default — `codegraph_explore` — but if you re-enable others via the `CODEGRAPH_MCP_TOOLS` environment variable, they're already permitted with no prompt.
|
||||
|
||||
:::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,33 @@
|
||||
---
|
||||
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 |
|
||||
| Objective-C | `.m`, `.mm`, `.h` | Partial support (classes, protocols, methods, `@property`, `#import`, message sends; `.mm` ObjC++ may parse incompletely) |
|
||||
| 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) |
|
||||
| Astro | `.astro` | Full support (frontmatter + script extraction, template component/call references, `src/pages/` 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) |
|
||||
| R | `.R`, `.r` | Full support (functions, S4/R5/R6 classes with methods, `library`/`require` imports, `source()` file references, call edges) |
|
||||
| Luau | `.luau` | Full support (Lua, plus typed signatures, `type` aliases, Roblox `require`) |
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: MCP Server
|
||||
description: The tools CodeGraph exposes to AI agents over MCP.
|
||||
---
|
||||
|
||||
CodeGraph runs as a [Model Context Protocol](https://modelcontextprotocol.io/) server. Agents configured by the installer launch it automatically — you don't start it by hand:
|
||||
|
||||
```bash
|
||||
codegraph serve --mcp
|
||||
```
|
||||
|
||||
When a `.codegraph/` index exists, the agent gets the tool below. In a workspace with **no** index, the server announces itself inactive and lists **no** tools — the agent works normally with its built-in tools, and indexing stays your decision.
|
||||
|
||||
## One tool by default: `codegraph_explore`
|
||||
|
||||
By default the server exposes a **single tool**, `codegraph_explore`. It's Read-equivalent: give it a natural-language question or a bag of symbol and file names, and it returns the **verbatim, line-numbered source** of the relevant symbols grouped by file — the same shape the `Read` tool gives you — plus the call paths between them (including dynamic-dispatch hops like callbacks, React re-render, and JSX children that grep can't follow) and a blast-radius summary of what depends on them. One call usually answers the whole question.
|
||||
|
||||
Exposing a single strong tool is deliberate. Measured agent behavior showed that one well-aimed tool steers agents to a direct answer better than a menu of narrower ones — fewer mis-picks — and agents reach for it both when answering questions and while editing code.
|
||||
|
||||
## The other tools
|
||||
|
||||
Seven more tools exist and stay fully functional, but are **unlisted by default** — everything they return already arrives inline on a `codegraph_explore` response (its blast-radius section, the relationship map, a symbol's body and its callee list):
|
||||
|
||||
| Tool | Purpose |
|
||||
|---|---|
|
||||
| `codegraph_node` | One symbol's source + caller/callee trail, or a whole file read with line numbers (Read-parity). Returns every overload's body for an ambiguous name. |
|
||||
| `codegraph_search` | Find symbols by name across the codebase (locations only) |
|
||||
| `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_files` | Get the indexed file structure (faster than filesystem scanning) |
|
||||
| `codegraph_status` | Check index health and statistics |
|
||||
|
||||
Re-enable any of them with the `CODEGRAPH_MCP_TOOLS` environment variable — a comma-separated allowlist of short names that replaces the default:
|
||||
|
||||
```bash
|
||||
CODEGRAPH_MCP_TOOLS=explore,node,search,callers
|
||||
```
|
||||
|
||||
Each also has a CLI equivalent (`codegraph node` / `query` / `callers` / `callees` / `impact` / `files` / `status`) for scripts and non-MCP harnesses.
|
||||
|
||||
## How agents should use it
|
||||
|
||||
CodeGraph *is* the pre-built search index. For "how does X work?", architecture, a flow ("how does X reach Y"), or where-is-X questions — and while editing code — an agent should answer with `codegraph_explore` and stop, typically with **zero file reads**, rather than re-deriving the answer with `grep` + `Read`. A direct CodeGraph answer is one to a few calls; a grep/read exploration is dozens.
|
||||
|
||||
The MCP server delivers this guidance to the main agent automatically, in the MCP `initialize` response. Because subagents and non-MCP harnesses never see that response, the installer also writes a short marker-fenced section into each agent's instructions file pointing at the `codegraph explore` CLI equivalent.
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
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
|
||||
|
||||
Your agent starts the server itself, so you don't launch it by hand. Make sure the project is initialized and indexed (`codegraph status`) and that the path in your MCP config is correct. If it still won't connect, re-run `codegraph install` to rewrite the config.
|
||||
|
||||
## 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 inside a `.gitignore`d or default-excluded directory (e.g. `node_modules`, `dist`).
|
||||
|
||||
## Sharing one checkout between Windows and WSL
|
||||
|
||||
Don't point both at the same `.codegraph/`: the background-server lock and the SQLite index are tied to the OS that wrote them, and SQLite locking across the WSL2/Windows filesystem boundary is unreliable. Give each side its own index in the same tree by setting `CODEGRAPH_DIR` to a distinct name on one of them — e.g. `CODEGRAPH_DIR=.codegraph-win` on Windows, leaving WSL on the default `.codegraph`. CodeGraph skips any sibling `.codegraph-*` directory when indexing and watching, so the two never trip over each other.
|
||||
@@ -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,457 @@
|
||||
---
|
||||
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, Hermes,
|
||||
Gemini, Antigravity, and Kiro 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 {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1px 1fr;
|
||||
column-gap: 1.5rem;
|
||||
align-items: center;
|
||||
padding: 2.6rem 2rem;
|
||||
}
|
||||
.feature + .feature {
|
||||
border-inline-start: 1px solid var(--cg-rule);
|
||||
}
|
||||
/* full-height vertical divider between the icon and the text */
|
||||
.feature::before {
|
||||
content: '';
|
||||
grid-column: 2;
|
||||
grid-row: 1 / 3;
|
||||
align-self: stretch;
|
||||
width: 1px;
|
||||
background: var(--cg-rule);
|
||||
}
|
||||
.ficon {
|
||||
grid-column: 1;
|
||||
grid-row: 1 / 3;
|
||||
align-self: center;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
color: var(--cg-ink);
|
||||
}
|
||||
.feature h2 {
|
||||
grid-column: 3;
|
||||
grid-row: 1;
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 0.6rem;
|
||||
}
|
||||
.feature p {
|
||||
grid-column: 3;
|
||||
grid-row: 2;
|
||||
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);
|
||||
}
|
||||
.feature {
|
||||
column-gap: 1rem;
|
||||
padding: 2rem 1.25rem;
|
||||
}
|
||||
.ficon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
.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,226 @@
|
||||
/* =====================================================================
|
||||
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;
|
||||
}
|
||||
|
||||
/* On wide screens Starlight right-aligns the content against the TOC
|
||||
(margin-inline: auto 0), piling all the empty space on the left. Center the
|
||||
content within its pane so it sits balanced between the sidebar and the TOC. */
|
||||
@media (min-width: 72rem) {
|
||||
.main-pane {
|
||||
--sl-content-margin-inline: auto;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user