diff --git a/.github/workflows/docs-site.yml b/.github/workflows/docs-site.yml new file mode 100644 index 0000000..095f15f --- /dev/null +++ b/.github/workflows/docs-site.yml @@ -0,0 +1,87 @@ +# Builds the CodeGraph website (https://firlab.app/codegraph/) from a pull request's pages against +# firlab's public main, so a dead link, an unknown component, a page missing in one language, a +# missing screenshot, a banned word, a malformed home page or a link that leaves /codegraph/ fails +# before the merge rather than in publish-site.yml after it. Nothing is published and no secret is +# read, so a fork's pull request runs it the same way. Advisory: not part of CI Success. +# docs/site/README.md describes the whole path. +name: Docs site + +on: + pull_request: + paths: + - "docs/site/**" + - "!docs/site/README.md" + - "!docs/site/tools/**" + - "docs/cli.md" + - "docs/mcp.md" + - "docs/ui.md" + - "docs/languages.md" + - "docs/godot.md" + - "docs/troubleshooting.md" + - "docs/architecture.md" + - "docs/data-model.md" + - "docs/equivalence.md" + - "docs/grammar-manifest.md" + - "docs/embedded-extraction.md" + - "docs/benchmark.md" + - "docs/benchmark-results.md" + - ".github/workflows/docs-site.yml" + - ".github/workflows/publish-site.yml" + +concurrency: + group: docs-site-${{ github.event.pull_request.number }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + build: + name: Docs site · build + runs-on: ubuntu-24.04 + timeout-minutes: 15 + steps: + - name: Checkout codegraph-rust + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: codegraph-rust + persist-credentials: false + + - name: Checkout firlab + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: sunerpy/firlab + path: firlab + persist-credentials: false + + # The site installs on its own (its package.json pins pnpm); pnpm before setup-node so the + # pnpm cache resolves. + - name: Install pnpm + uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0 + with: + package_json_file: firlab/codegraph/package.json + + - name: Setup Node + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version-file: firlab/.node-version + cache: pnpm + cache-dependency-path: firlab/codegraph/pnpm-lock.yaml + + - name: Sync the pages + run: ./firlab/codegraph/scripts/sync-codegraph-docs.sh "$GITHUB_WORKSPACE/codegraph-rust" + + - name: Install the site's dependencies + working-directory: firlab/codegraph + run: pnpm install --frozen-lockfile + + - name: Build + working-directory: firlab/codegraph + run: pnpm build + + # The same check firlab's deploy runs before it publishes the site: both languages were + # emitted, every in-site link resolves, and every link, asset and sitemap entry stays under + # /codegraph/. + - name: Check both languages and the /codegraph/ base + working-directory: firlab/codegraph + run: ./scripts/check-dist.sh dist diff --git a/.github/workflows/publish-site.yml b/.github/workflows/publish-site.yml new file mode 100644 index 0000000..911e75e --- /dev/null +++ b/.github/workflows/publish-site.yml @@ -0,0 +1,111 @@ +# Pushes the pages of the CodeGraph website into sunerpy/firlab, which builds it and publishes it +# inside firlab.app at https://firlab.app/codegraph/ (firlab: `codegraph/`, +# `.github/workflows/deploy.yml`). docs/site/README.md describes the whole path. +# +# The sync pushes instead of the site pulling: the event that should update the site, a merge here, +# happens in this repository, and the credential stays here and reaches firlab only. The copy rules +# and checks live in firlab's sync script, which a local preview runs too, so this workflow and a +# preview produce the same tree. +# +# Needs FIRLAB_DOCS_TOKEN: a fine-grained personal access token for sunerpy/firlab only, with +# Contents read and write and nothing else. GitHub has no API that creates one, so it is made by +# hand (docs/site/README.md, "One-time setup"). Without it the first step fails and says so. +name: Publish site + +on: + push: + branches: [main] + paths: + - "docs/site/**" + - "!docs/site/README.md" + - "!docs/site/tools/**" + - "docs/cli.md" + - "docs/mcp.md" + - "docs/ui.md" + - "docs/languages.md" + - "docs/godot.md" + - "docs/troubleshooting.md" + - "docs/architecture.md" + - "docs/data-model.md" + - "docs/equivalence.md" + - "docs/grammar-manifest.md" + - "docs/embedded-extraction.md" + - "docs/benchmark.md" + - "docs/benchmark-results.md" + - ".github/workflows/docs-site.yml" + - ".github/workflows/publish-site.yml" + workflow_dispatch: + +# Queue, never cancel: a cancelled run could leave a pushed sync without its successor. +concurrency: + group: publish-site + cancel-in-progress: false + +permissions: + contents: read + +jobs: + publish: + name: Push the site's pages to firlab + runs-on: ubuntu-24.04 + timeout-minutes: 15 + steps: + - name: Require the firlab token + env: + FIRLAB_DOCS_TOKEN: ${{ secrets.FIRLAB_DOCS_TOKEN }} + run: | + if [ -z "${FIRLAB_DOCS_TOKEN}" ]; then + echo "::error::FIRLAB_DOCS_TOKEN is not set, so the site cannot be updated. docs/site/README.md, One-time setup, says how to create it." + exit 1 + fi + + - name: Checkout codegraph-rust + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: codegraph-rust + persist-credentials: false + + # Full history, so a rejected push can rebase onto a newer main. + - name: Checkout firlab + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: sunerpy/firlab + token: ${{ secrets.FIRLAB_DOCS_TOKEN }} + path: firlab + fetch-depth: 0 + + - name: Sync the pages + run: ./firlab/codegraph/scripts/sync-codegraph-docs.sh "$GITHUB_WORKSPACE/codegraph-rust" + + - name: Commit and push + working-directory: firlab + env: + SOURCE_SHA: ${{ github.sha }} + run: | + set -euo pipefail + # `git status`, not `git diff`: a new page is an untracked file, which `git diff` misses. + if [ -z "$(git status --porcelain -- codegraph/src)" ]; then + echo "the site is already up to date; nothing to push" + exit 0 + fi + + # The sync writes nowhere else; staging the tree by name keeps anything else out. + git add -- codegraph/src + git -c user.name='codegraph-docs[bot]' \ + -c user.email='codegraph-docs@users.noreply.github.com' \ + commit -m "docs(codegraph): sync from codegraph-rust@${SOURCE_SHA:0:7}" \ + -m "Source: https://github.com/sunerpy/codegraph-rust/commit/${SOURCE_SHA}" + + # The other product sites' syncs push to the same branch. They touch other directories, + # so a rejected push rebases onto the new tip and tries again. + for attempt in 1 2 3; do + if git push origin HEAD:main; then + exit 0 + fi + echo "push rejected (attempt ${attempt}); rebasing onto origin/main" + git -c user.name='codegraph-docs[bot]' \ + -c user.email='codegraph-docs@users.noreply.github.com' \ + pull --rebase origin main + done + echo "::error::the sync commit could not be pushed after 3 attempts" + exit 1 diff --git a/AGENTS.md b/AGENTS.md index cb601df..8d16119 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -121,6 +121,7 @@ handoff. Do not use a narrow test to claim a workspace-wide property. | release/install/checksum | shell/PowerShell fixtures, asset-name checks, archive smoke | README install section and release workflow contract | | viewer (`codegraph-ui`, `ui/`) | crate tests over indexed fixtures; `cli_ui`; `make ui-check` (rebuilds and byte-checks the committed bundle) | `ui.md`; `cli.md` for the command | | docs/community files | `python3 scripts/docs-check.py`; formatter; link/anchor checks | update the canonical page, not a duplicate summary | +| website pages (`docs/site/`) | `docs-check.py`; formatter; firlab's sync + build + `check-dist.sh` (`docs-site.yml`) | `docs/site/README.md`; both languages; link canonical references, never copy | If a change alters nodes, edges, reference resolution, file classification, or stored graph meaning, decide explicitly whether the extraction version must move. diff --git a/README.md b/README.md index 134f01a..136f829 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ native binary. No AI or vector runtime inside the indexer. [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT) [English](README.md) · [简体中文](docs/readme/README.zh-CN.md) · -[Documentation](docs/README.md) · [Contributing](CONTRIBUTING.md) +[Website](https://firlab.app/codegraph/en/) · [Documentation](docs/README.md) · +[Contributing](CONTRIBUTING.md) diff --git a/docs/README.md b/docs/README.md index 5e31dc5..af965d8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,6 +4,15 @@ The root [README](../README.md) is the landing page. This index points to the canonical technical references; update the owning page rather than duplicating volatile behavior elsewhere. +## Website + +[firlab.app/codegraph](https://firlab.app/codegraph/) (English at +[`/codegraph/en/`](https://firlab.app/codegraph/en/)) is the user guide, in Chinese +and English, with screenshots of the browser viewer. Its pages live in +[`site/`](site/README.md), next to the code they describe; that README explains how +a change reaches the site, the writing rules and how the screenshots are taken. The +site publishes the references below unchanged. + ## Use CodeGraph - [CLI reference](cli.md) — command/path contracts, installation targets, diff --git a/docs/godot.md b/docs/godot.md index 2d4b326..5d4c673 100644 --- a/docs/godot.md +++ b/docs/godot.md @@ -228,10 +228,10 @@ codegraph audit --orphans --exclude addons/ -p . # recommended: denoise vendor ``` `-p` selects the **project root**, not a result filter. To scope or denoise the -report, use the CLI-layer prefix filters `--include ` / `--exclude -` (both repeatable, `/`-normalized). For a typical Godot project, -`--exclude addons/` drops noise from vendored editor plugins; `--include -/` narrows to your own resources. +report, use the CLI-layer prefix filters `--include ` / +`--exclude ` (both repeatable, `/`-normalized). For a typical Godot +project, `--exclude addons/` drops noise from vendored editor plugins; +`--include /` narrows to your own resources. Because `.tres`/`.tscn`/`project.godot` files have no tree-sitter grammar, they get no `file:` graph node and their `ExtResource(…)` references stay in the diff --git a/docs/readme/README.zh-CN.md b/docs/readme/README.zh-CN.md index 9825c25..034f1a0 100644 --- a/docs/readme/README.zh-CN.md +++ b/docs/readme/README.zh-CN.md @@ -13,7 +13,8 @@ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](../../LICENSE-MIT) [English](../../README.md) · [简体中文](README.zh-CN.md) · -[文档](../README.md) · [参与贡献](../../CONTRIBUTING.md) +[网站](https://firlab.app/codegraph/) · [文档](../README.md) · +[参与贡献](../../CONTRIBUTING.md) diff --git a/docs/site/README.md b/docs/site/README.md new file mode 100644 index 0000000..fa0095e --- /dev/null +++ b/docs/site/README.md @@ -0,0 +1,154 @@ +# docs/site — the pages of firlab.app/codegraph + +This directory holds the words and screenshots of the CodeGraph website: Chinese at `docs/site/`, English at +`docs/site/en/`, one file per page and the same path in both languages. The site itself (the VitePress +configuration, the theme, the components and the deployment) lives in [`sunerpy/firlab`](https://github.com/sunerpy/firlab) +under `codegraph/`. The site has no domain of its own: firlab.app's GitHub Pages deploy publishes it at +. + +This file is for maintainers and is not published. + +## Paths + +Site paths below are relative to `https://firlab.app/codegraph/`. + +| Path here | Published at | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | +| `index.md`, `en/index.md` | `/`, `/en/` (home pages; the words are in their frontmatter, see "The home pages") | +| `guide/`, `reference/faq.md`, `privacy.md`, `developers.md` and the same paths under `en/` | the user guide | +| `../cli.md`, `../mcp.md`, `../ui.md`, `../languages.md`, `../godot.md`, `../troubleshooting.md` | `/en/reference/`, as they are; `/reference/` is a generated Chinese pointer | +| `../architecture.md`, `../data-model.md`, `../equivalence.md`, `../grammar-manifest.md`, `../embedded-extraction.md`, `../benchmark.md`, `../benchmark-results.md` | `/en/dev/`, with a generated Chinese pointer at `/dev/` | +| `public/` | the site root (`/codegraph-logo.svg`, `/screens/*.webp`) | +| `tools/`, this file | not published | + +The canonical references stay English, as `docs/AGENTS.md` asks. The site publishes them unchanged and gives each a +Chinese page that points to the English one, because VitePress's language switch maps the current path onto the other +locale and would otherwise lead to a 404. + +## How a change reaches the site + +1. A pull request that touches these files or the references above runs `.github/workflows/docs-site.yml`. It checks + out the public firlab repository, syncs this directory into it with firlab's + `codegraph/scripts/sync-codegraph-docs.sh`, builds the site and runs firlab's `codegraph/scripts/check-dist.sh`. + The step fails on any of these: + - a dead link, or a page that exists in one language only; + - an unknown component, a missing screenshot or a malformed home page; + - a banned word, or a link that leaves `/codegraph/`. + + It reads no secret, so a pull request from a fork runs it too. It is advisory and not part of `CI Success`. + +2. After the merge, `.github/workflows/publish-site.yml` runs the same sync script and commits the result to firlab's + `main` as `docs(codegraph): sync from codegraph-rust@`. It needs the repository secret `FIRLAB_DOCS_TOKEN` + (see "One-time setup"). +3. firlab's `deploy.yml` builds the main site and this one, checks this one, puts it at `dist/codegraph/` and deploys + firlab.app to GitHub Pages. + +The footer of every page names the codegraph-rust commit its content came from. + +## Preview + +```bash +git clone https://github.com/sunerpy/firlab ../firlab # once +../firlab/codegraph/scripts/sync-codegraph-docs.sh "$PWD" +cd ../firlab/codegraph && pnpm install --frozen-lockfile && pnpm dev # http://localhost:5173/codegraph/ +``` + +Run the sync again after each edit. It stops and names the problem when a page has no counterpart in the other +language, uses a component the site does not register, shows a screenshot that does not exist, or uses a word from the +lists below. A sync from an uncommitted tree marks the footer commit `-dirty`. Run `python3 scripts/docs-check.py` as +well: it checks every relative link and anchor here, the same way GitHub renders them. + +## Writing + +- **Both languages together.** The Chinese and English page have the same sections in the same order. +- **Relative `.md` links.** Link pages with paths such as `../guide/install.md`, and the canonical references by their + real path, such as `../../cli.md` from a Chinese guide page or `../../../cli.md` from an English one. GitHub and + `docs-check.py` follow them as written; the sync script rewrites them to the site's paths. Frontmatter links, which + components render, use site paths (`/guide/install`, `/en/guide/install`). +- **AS-BUILT.** Every command, flag, default and output must match the code and the canonical reference. Output blocks + are pasted from a real run, never written by hand. When the two disagree, fix the page. +- **No counts and no performance claims.** No language or tool totals and no latency, memory or throughput figures in + prose; the sync rejects "sub-millisecond" and 亚毫秒. A screenshot or an output block may show numbers, because it + shows one real run. +- **Plain written language.** Chinese pages use the register of Apple's and Microsoft's Chinese documentation, no + colloquial words (还没、没能、免得、搭的、咋、啥), a space between Chinese and Latin text, headings without a full stop. + English pages avoid "just", "gonna" and "stuff". The first sentence of a page says what the page helps with. +- **User pages name no internals:** no crate names and no `§`. `developers.md` is the exception. +- **Unreleased or preview features** are marked with `` and never described as generally available. +- **No real secrets or private hosts**, in text or in a screenshot. + +## Components + +Pages may use these components and no others; the sync rejects any other tag. + +| Component | Use | +| ----------------------------------------------------------------------------------- | --------------------------------------------------------- | +| `` | release state, shown as text | +| `` | a screenshot; `dark` is the same screen in the dark theme | +| `` | VitePress's own badge | +| `HomeIndex`, `HomeSteps`, `SplitBlock`, `HomePlatforms`, `HomePrivacy`, `HomeScope` | the home pages only; they render the `home:` frontmatter | + +## The home pages + +Both home pages keep their words in frontmatter: VitePress's `hero:` (name, text, tagline, buttons) and a `home:` +block that the components render. The build checks `home:` against firlab's +`codegraph/src/.vitepress/theme/data/home-schema.ts` and fails on a missing or an unknown field. + +| Key | Holds | +| ----------- | ---------------------------------------------------------------------------------------------------- | +| `facts` | the lines under the tagline: `term`, `text` (at least two) | +| `visual` | the hero capture: `desktop` with `light`, `dark`, `width`, `height`, `alt` | +| `index` | the feature index: `title`, `intro`, `groups[].items[]` (`title`, `body`, `status`, `link`) | +| `steps` | `title`, `items[]` (`title`, `body`, optional `command`; at least two) | +| `tools` | the agent split's table: `columns` (three), `rows[]` (`question`, `cli`, `mcp`), `caption` | +| `shots` | captures that `` names, keyed by `shot` | +| `languages` | the language split's table: `columns` (three), `rows[]` (`depth`, `extracted`, `members`), `caption` | +| `platforms` | `title`, `intro`, `columns`, `rows[]` (`name`, `status`, `cells`: one fewer than `columns`), `note` | +| `privacy` | `title`, `intro`, `sendsLabel`, `modes[]` (`name`, `sends`, `detail`) | +| `scope` | what CodeGraph does not do: `title`, `items[]` | + +`status` is `available` or `preview`. + +## Screenshots + +The screenshots are WebP files in `public/screens/`, named `viewer--.webp`, 1440 × 900 at device pixel +ratio 1. The viewer's interface is English only, so one set serves both languages. They come from the real viewer +reading this repository's own index: + +```bash +cargo build --release -p codegraph-rs +CODEGRAPH_CHROME=/path/to/chrome docs/site/tools/capture-screens.sh target/release/codegraph +``` + +`tools/capture-screens.sh` does four things: + +1. it extracts this repository at a fixed commit into `codegraph-rust/` inside a new temporary directory, which it + removes, index included, when it exits; +2. it writes the corpus's `.codegraph/config.toml`, which excludes the viewer bundle as `AGENTS.md` recommends; +3. it indexes the corpus and serves it with `codegraph ui` on `127.0.0.1:4791`; +4. it runs `tools/capture-screens.mjs`. + +That script drives Chrome over its DevTools protocol and installs nothing. It opens each view as a fresh page in the +light and the dark theme, and waits until the view has finished loading. It stops without saving on: + +- a console error, a failed request or a timeout; +- a view that does not show what it should; +- a symbol lookup that does not find exactly one match. + +`CODEGRAPH_SCREENS_COMMIT` changes the corpus commit and `CODEGRAPH_SCREENS_PORT` the port. + +Look at every image before committing it. Capture again when the viewer's text or layout changes, and update the +`width`/`height` in both home pages and in the `` tags if the size changes. + +## One-time setup + +`publish-site.yml` needs `FIRLAB_DOCS_TOKEN`: a fine-grained personal access token for `sunerpy/firlab` only, with +Contents read and write and nothing else. GitHub has no API that creates one, so it is made by hand in the GitHub web +interface and stored with: + +```sh +gh secret set FIRLAB_DOCS_TOKEN --repo sunerpy/codegraph-rust +``` + +Until it exists, `publish-site.yml` stops at its first step with an error that says so, and the site keeps the last +synced content. diff --git a/docs/site/developers.md b/docs/site/developers.md new file mode 100644 index 0000000..8bab99e --- /dev/null +++ b/docs/site/developers.md @@ -0,0 +1,50 @@ +# 参与开发 + +本页面向希望从源码构建、修改 CodeGraph 或改进本站点的开发者。 + +CodeGraph 以 MIT 许可开源,代码、问题和拉取请求都在 [GitHub](https://github.com/sunerpy/codegraph-rust) 上。它是 TypeScript 项目 [colbymchenry/codegraph](https://github.com/colbymchenry/codegraph) 的 Rust 移植版本,独立开发并持续跟进上游;[上游同步记录](https://github.com/sunerpy/codegraph-rust/blob/main/docs/upstream-sync/UPSTREAM.md)列出了已移植的内容。 + +## 构建与测试 + +```sh +git clone https://github.com/sunerpy/codegraph-rust +cd codegraph-rust +cargo build --release # target/release/codegraph +make check # 格式、lint、测试和防护检查:与 CI 相同的门禁 +make pre-ci # make check,外加查看器前端检查和发布包冒烟测试 +``` + +Rust 版本固定在 `rust-toolchain.toml` 中;编译 SQLite 和各语言的语法需要 C 编译器。`ui/` 中的查看器前端只有在重新构建时才需要 Node 和 npm;构建产物已提交到仓库,因此 `cargo build` 从不运行 Node。 + +## 代码组织 + +工作区由一组 crate 组成,依赖方向只有一个:从共享类型一直到命令行。 + +| Crate | 负责 | +| ------------------- | ------------------------------------- | +| `codegraph-core` | 共享类型、配置、节点 ID、日志 | +| `codegraph-extract` | 语言识别,以及基于 tree-sitter 的提取 | +| `codegraph-store` | SQLite 表结构、迁移、全文检索和查询 | +| `codegraph-resolve` | 导入和名称匹配,以及框架解析器 | +| `codegraph-graph` | 图遍历、影响范围、搜索排序 | +| `codegraph-mcp` | MCP 服务及其工具 | +| `codegraph-watch` | 增量同步和文件监听 | +| `codegraph-daemon` | 后台进程及其锁和登记 | +| `codegraph-ui` | 浏览器查看器的服务端和内嵌前端 | +| `codegraph-cli` | `codegraph` 命令和 Agent 安装器 | +| `codegraph-bench` | 等价性校验和基准测试,不随版本发布 | + +[架构](../architecture.md)和[数据模型](../data-model.md)两页说明了从文件到答案的流程以及其中用到的表。 + +## 每次改动都要保证 + +- **输出确定**:同样的源码和配置得到同样的索引,`sync` 与完整重建结果一致。 +- **golden 逐字节稳定**:提取结果与参考产物逐字节比对;有意改变输出时,按[等价性说明](../equivalence.md)重新生成。 +- **不含模型**:构建中不能引入任何 AI、embedding 或向量相关的依赖,有专门的防护脚本检查。 +- **出错即停止**:有歧义或不安全的答案保持未解析或直接拒绝。 + +完整规则(包括提交信息和发布流程)见[贡献者约定](https://github.com/sunerpy/codegraph-rust/blob/main/AGENTS.md)和 [CONTRIBUTING.md](https://github.com/sunerpy/codegraph-rust/blob/main/CONTRIBUTING.md)。 + +## 修改本站点 + +本站点的文字和截图保存在仓库的 `docs/site/` 下,与它们描述的代码放在一起,因此一个改变界面的拉取请求可以同时更新页面。站点本身(主题、组件和发布流程)位于 [sunerpy/firlab](https://github.com/sunerpy/firlab)。`docs/site/README.md` 说明了如何预览改动、写作规则以及截图方法。 diff --git a/docs/site/en/developers.md b/docs/site/en/developers.md new file mode 100644 index 0000000..90aacc2 --- /dev/null +++ b/docs/site/en/developers.md @@ -0,0 +1,64 @@ +# Contributing + +This page is for people who want to build CodeGraph from source, change it, or improve this site. + +CodeGraph is open source under the MIT licence. The code, the issue tracker and the pull requests are on +[GitHub](https://github.com/sunerpy/codegraph-rust). It is a Rust port of the TypeScript project +[colbymchenry/codegraph](https://github.com/colbymchenry/codegraph), developed independently and kept in step with +it; the [upstream ledger](https://github.com/sunerpy/codegraph-rust/blob/main/docs/upstream-sync/UPSTREAM.md) +records what has been ported. + +## Build and test + +```sh +git clone https://github.com/sunerpy/codegraph-rust +cd codegraph-rust +cargo build --release # target/release/codegraph +make check # formatting, lints, tests, guardrails: the same gate as CI +make pre-ci # make check, plus the viewer frontend and a release-archive smoke test +``` + +The Rust version is pinned in `rust-toolchain.toml`; a C compiler is needed for SQLite and the grammars. The viewer +frontend in `ui/` needs Node and npm only to rebuild it; the built bundle is committed, so `cargo build` never runs +Node. + +## How the code is organised + +The workspace is a set of crates with one direction of dependency, from shared types up to the command line: + +| Crate | Owns | +| ------------------- | ----------------------------------------------------------- | +| `codegraph-core` | shared types, configuration, node ids, logging | +| `codegraph-extract` | language detection and extraction with tree-sitter | +| `codegraph-store` | the SQLite schema, migrations, full-text search and queries | +| `codegraph-resolve` | import and name resolution, and framework resolvers | +| `codegraph-graph` | traversal, impact, search ranking | +| `codegraph-mcp` | the MCP server and its tools | +| `codegraph-watch` | incremental sync and file watching | +| `codegraph-daemon` | the background process, its locks and registries | +| `codegraph-ui` | the browser viewer's server and its embedded frontend | +| `codegraph-cli` | the `codegraph` command, the agent installer | +| `codegraph-bench` | the equivalence oracle and benchmarks; not shipped | + +The [architecture](../../architecture.md) and [data model](../../data-model.md) pages describe the flow from a file to an +answer and the tables in between. + +## What every change keeps + +- **Deterministic output.** The same source and configuration produce the same index, and `sync` converges with a + full rebuild. +- **Byte-stable goldens.** Extraction output is compared byte for byte against reference artifacts; the + [equivalence page](../../equivalence.md) explains how to regenerate them for an intended change. +- **No model.** No AI, embedding or vector dependency may enter the build; a guardrail script enforces it. +- **Fail closed.** An ambiguous or unsafe answer stays unresolved or is refused. + +The [contributor contract](https://github.com/sunerpy/codegraph-rust/blob/main/AGENTS.md) and +[CONTRIBUTING.md](https://github.com/sunerpy/codegraph-rust/blob/main/CONTRIBUTING.md) have the full rules, +including commit messages and the release process. + +## Changing this site + +The words and screenshots of this site live in the repository under `docs/site/`, next to the code they describe, so +a pull request that changes what you see also updates the page. The site itself (theme, components and publishing) +lives in [sunerpy/firlab](https://github.com/sunerpy/firlab). `docs/site/README.md` explains how to preview a change, +the writing rules and how the screenshots are taken. diff --git a/docs/site/en/guide/agents.md b/docs/site/en/guide/agents.md new file mode 100644 index 0000000..f0f72d3 --- /dev/null +++ b/docs/site/en/guide/agents.md @@ -0,0 +1,112 @@ +# Connect a coding agent + +This page shows how to give a coding agent or an editor access to CodeGraph's index over MCP, and what the agent can +then ask. + +CodeGraph runs as an MCP server. An agent that has it configured asks structural questions with tool calls instead of +searching and reading files one by one, and gets back the relevant source together with the calls between it. + +## Write the configuration for you + +```sh +codegraph install --yes +``` + +`install` finds the agents installed on this computer and adds a `codegraph` entry to each one's MCP configuration. +The entry starts `codegraph serve --mcp`. Running it again updates the entry in place, and other MCP servers in the +same file are left alone. + +Supported agents and editors: Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Gemini CLI, Antigravity IDE, +Kiro, Trae, Qoder, Zed, Zuno, VS Code (GitHub Copilot), GitHub Copilot CLI and JetBrains IDEs (GitHub Copilot). + +| You want to | Run | +| -------------------------------------------------------- | ------------------------------------------------ | +| choose the agents | `codegraph install --target=claude,cursor --yes` | +| write the project's own config instead of the global one | `codegraph install --target=auto --local` | +| see the entry without writing anything | `codegraph install --print-config cursor` | +| install and index the current project in one step | `codegraph install --yes --init` | +| remove the entries again | `codegraph uninstall` | + +Some editors start the server outside the project and do not tell it which project is open. Kiro, Zed and VS Code +read a global entry that cannot name a project, so it can only answer for indexes passed in each call. For those, +`codegraph init --target=` inside a project writes a project-level entry that names the project, which also +turns on live updates for it. Cursor's global entry names the open folder itself. The +[CLI reference](../../../cli.md#codegraph-install--uninstall--wire-up-ai-agents) lists the file each agent uses. + +## Add the agent skill + +```sh +codegraph skill install +``` + +The skill is a short instruction file that tells an agent when to use which CodeGraph tool. `codegraph skill status` +shows which agents have it and whether it is current; `codegraph skill update` refreshes it after an upgrade. + +## Configure it by hand + +Any MCP client can start the server itself: + +```json +{ + "mcpServers": { + "codegraph": { + "command": "codegraph", + "args": ["serve", "--mcp"] + } + } +} +``` + +The server talks MCP over standard input and output. To pin it to one project regardless of where the client starts +it, add `"-p", "/path/to/project"` to `args`. + +## Which project the server answers for + +Started without `-p`, the server looks for a project in this order: + +1. the nearest directory with an index at or above its working directory; +2. if there is none and the working directory is a repository or workspace root, the one indexed project below it, as + long as there is exactly one; +3. the workspace the client announces when it connects, if that workspace is indexed. + +If none of these gives a project, every tool still works, but each call must name the project with `projectPath`. The +server never guesses between several indexed projects. [MCP reference](../../../mcp.md#project-resolution) + +## What the agent can ask + +| Question | MCP tool | Same thing on the command line | +| ---------------------------- | ------------------- | -------------------------------- | +| How does this area work? | `codegraph_explore` | `codegraph explore ""` | +| Show me this symbol or file | `codegraph_node` | `codegraph node ` | +| Where is it defined? | `codegraph_search` | `codegraph search ` | +| Who calls it? | `codegraph_callers` | `codegraph callers ` | +| What does it call? | `codegraph_callees` | `codegraph callees ` | +| What does changing it reach? | `codegraph_impact` | `codegraph impact ` | +| Is the index current? | `codegraph_status` | `codegraph status` | +| Which files are indexed? | `codegraph_files` | `codegraph files` | +| Are there import cycles? | `codegraph_check` | `codegraph check` | +| Give me the whole graph | `codegraph_export` | `codegraph export` | + +An agent sees the first four tools in its tool list; the others can still be called. Set `CODEGRAPH_MCP_TOOLS` to +list more, for example `CODEGRAPH_MCP_TOOLS=explore,node,search,callers,impact`. Every tool is read-only and marked as +such, so agents that honour MCP's hints do not ask for confirmation. + +## Over HTTP + +Editors that prefer HTTP, and remote development over SSH, can use the streamable-HTTP transport: + +```sh +codegraph serve --http # listens on 127.0.0.1:8111 +codegraph serve --http --detach # the same, in the background +codegraph http list # running HTTP servers +codegraph http stop 127.0.0.1:8111 +``` + +The HTTP server has no authentication. It listens on the local machine unless you pass another address with +`--http-addr`; keep it there, or put your own access control in front of it. +[MCP reference](../../../mcp.md) + +## Keeping answers current + +For each indexed project it serves, the server starts or joins one background process that watches the files and +updates the index. Every agent and editor on that project shares it. [Keeping the index current](keeping-current.md) diff --git a/docs/site/en/guide/configuration.md b/docs/site/en/guide/configuration.md new file mode 100644 index 0000000..2027739 --- /dev/null +++ b/docs/site/en/guide/configuration.md @@ -0,0 +1,67 @@ +# Configuration + +This page lists the settings that change what CodeGraph indexes and how it ranks results. + +CodeGraph works without configuration. Settings live in two optional files inside the project's `.codegraph/` +directory, and a few environment variables tune the background process. + +## `.codegraph/config.toml` + +```toml +[app] +name = "my-project" + +[indexing] +exclude = ["static/", "docs/generated/"] +deprioritize = ["vendor/**"] +``` + +When the file exists it must have an `[app]` table with a `name`; without it every command stops with a +`missing field` error. Every other setting is optional: + +| Setting | Default | What it does | +| ------------------------ | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `app.name` | — | A name for the project. | +| `app.log_level` | `info` | How much CodeGraph logs to standard error. | +| `indexing.exclude` | none | Paths left out of the index, written like `.gitignore` rules (`static/`, `gen*`). | +| `indexing.include` | none | Paths indexed even though `.gitignore` leaves them out, for source a second version-control system keeps out of Git. `exclude` still wins, and dependency directories such as `node_modules` are never brought back. | +| `indexing.ignore_dirs` | dependency, build and cache directories such as `node_modules`, `target`, `dist` and `.venv` | Directory names skipped at any depth. A list here **replaces** the default list, so repeat the defaults you want to keep. | +| `indexing.ignore_paths` | Android `res/` resource directories | Path patterns skipped by default, in `.gitignore` form. | +| `indexing.max_file_size` | `1048576` (1 MiB) | Larger files are recorded without being parsed. | +| `indexing.deprioritize` | none | Paths that stay indexed but rank below your own code in `search` and `explore`. | +| `watch.enabled` | `true` | Whether the background process watches the files. | +| `watch.debounce_ms` | `2000` | How long the watcher waits for a burst of changes to settle. | + +The project's `.gitignore` applies too: what Git ignores, CodeGraph does not index. A change to `config.toml` or to +the root `.gitignore` takes effect without a restart; run `codegraph sync` if no background process is running. + +## `.codegraph/codegraph.json` + +Map file extensions CodeGraph does not know to a language it parses: + +```json +{ + "extensions": { + ".blade": "php", + ".x": "lua" + } +} +``` + +Keys are matched without the leading dot and case-insensitively. A language name CodeGraph does not know is skipped, +and a malformed file is ignored with an error in the log rather than stopping indexing. +[CLI reference](../../../cli.md#custom-extension-mapping-codegraphcodegraphjson) + +## Environment variables + +| Variable | Use | +| ---------------------------------- | -------------------------------------------------------------------------- | +| `CODEGRAPH_NO_DAEMON=1` | Run in the foreground and start no background process, for CI and scripts. | +| `CODEGRAPH_NO_WATCH=1` | Keep the background process but stop it watching files. | +| `CODEGRAPH_WATCH_DEBOUNCE_MS` | The watcher's pause, in milliseconds. | +| `CODEGRAPH_DAEMON_IDLE_TIMEOUT_MS` | How long the background process stays after its last client leaves. | +| `CODEGRAPH_MCP_TOOLS` | Which MCP tools an agent sees in its tool list. | +| `CODEGRAPH_DIR` | Use another directory name inside the project instead of `.codegraph`. | +| `CODEGRAPH_UI=1` | Turn on the browser viewer (preview). | + +The [CLI reference](../../../cli.md#environment-variable-reference) has the complete list with ranges and defaults. diff --git a/docs/site/en/guide/install.md b/docs/site/en/guide/install.md new file mode 100644 index 0000000..a6e6d67 --- /dev/null +++ b/docs/site/en/guide/install.md @@ -0,0 +1,133 @@ +# Install + +This page covers installing CodeGraph, keeping it up to date and removing it again. + +CodeGraph is one executable named `codegraph`. Releases are published on +[GitHub Releases](https://github.com/sunerpy/codegraph-rust/releases) for Linux, macOS and Windows; the package is not +on crates.io. + +## Linux and macOS + +```sh +curl -fsSL https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.sh | sh +``` + +The script picks the archive for your platform, refuses to continue unless the archive's SHA-256 matches the +release's `SHA256SUMS`, and installs `codegraph` into `$HOME/.local/bin`. It needs `curl` or `wget`, `tar`, and +`sha256sum` or `shasum`. It does not edit your shell profile: when the directory is not on your `PATH`, it says so, +and adding it is up to you. + +Set `CODEGRAPH_INSTALL_DIR` to install somewhere else. + +## Windows + +In PowerShell 5.1 or later: + +```powershell +irm https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.ps1 | iex +``` + +The script verifies the archive the same way and installs `codegraph.exe` into `%LOCALAPPDATA%\Programs\codegraph`. +It adds that directory to your **user** `PATH` if it is not there yet; open a new terminal for the change to apply. +`CODEGRAPH_INSTALL_DIR` changes the directory here too. + +In Git Bash, MSYS2 or Cygwin, use the PowerShell script: the shell script stops and points you to it. + +## Install a specific version + +Both scripts install the latest release unless `CODEGRAPH_VERSION` names one. To make an install reproducible, take +the script from the same tag: + +```sh +curl -fsSL https://raw.githubusercontent.com/sunerpy/codegraph-rust/vX.Y.Z/scripts/install.sh \ + | CODEGRAPH_VERSION=vX.Y.Z sh +``` + +```powershell +$env:CODEGRAPH_VERSION = "vX.Y.Z" +irm https://raw.githubusercontent.com/sunerpy/codegraph-rust/vX.Y.Z/scripts/install.ps1 | iex +``` + +## Download an archive yourself + +Every release carries six archives, one per platform: + +| Platform | Target | Archive | +| ------------------- | ---------------------------- | --------- | +| Linux x86_64 | `x86_64-unknown-linux-musl` | `.tar.gz` | +| Linux ARM64 | `aarch64-unknown-linux-musl` | `.tar.gz` | +| macOS Intel | `x86_64-apple-darwin` | `.tar.gz` | +| macOS Apple Silicon | `aarch64-apple-darwin` | `.tar.gz` | +| Windows x86_64 | `x86_64-pc-windows-msvc` | `.zip` | +| Windows ARM64 | `aarch64-pc-windows-msvc` | `.zip` | + +The Linux builds are statically linked, so they need no system library. Extract the archive and put `codegraph` on +your `PATH`. + +Each release also has `SHA256SUMS`, and every archive carries a build attestation. To check where an archive was built: + +```sh +sha256sum -c SHA256SUMS --ignore-missing +gh attestation verify codegraph-X.Y.Z-x86_64-unknown-linux-musl.tar.gz \ + --repo sunerpy/codegraph-rust \ + --signer-workflow sunerpy/codegraph-rust/.github/workflows/release.yml \ + --deny-self-hosted-runners +``` + +## Build from source + +With a Rust toolchain and a C compiler (SQLite and the language grammars are compiled from source): + +```sh +cargo install --locked --git https://github.com/sunerpy/codegraph-rust codegraph-rs +``` + +The package is `codegraph-rs`; the command it installs is `codegraph`. The repository pins the Rust version it is +tested with in `rust-toolchain.toml`. + +## Check the install + +```sh +codegraph --version +``` + +## Update + +```sh +codegraph self-update # the latest release +codegraph self-update --check # only report whether a newer release exists +codegraph self-update --tag vX.Y.Z # a specific release +``` + +`self-update` downloads the archive for your platform from GitHub Releases, verifies it and replaces the running +executable. When `codegraph` lives in a directory you cannot write to, run it with the rights that directory needs. + +A new release may change how the index is built. When it does, `codegraph status` reports the index as outdated, and +`codegraph sync` rebuilds it. Use `codegraph index --force` only when a command tells you the index needs recovery. +The [CLI reference](../../../cli.md#extraction-version-upgrades) has the details. + +## Uninstall + +Remove what CodeGraph wrote, then the executable: + +1. **Stop what is running.** `codegraph http list` shows background HTTP servers with their log files. Note the log + path, stop the server with `codegraph http stop
`, then delete the log; the stopped server is no longer + listed. Quit the agents and editors that use CodeGraph, which ends their MCP servers. +2. **Remove the agent configuration.** `codegraph uninstall` removes the CodeGraph entry from your agents' configs (add + `--local` for configs inside a project), and `codegraph skill uninstall` removes the skill if you installed it. +3. **Remove each index.** `codegraph uninit --force ` stops that project's background process and deletes + its database and settings. The `.codegraph/` directory stays behind with a few state files and any viewer trails + you saved; delete the directory to leave nothing. +4. **Remove shell completions**, if you installed them with `codegraph completions --install`. Delete the + completion file; for zsh and elvish, also the line you added to your shell configuration; for PowerShell, also the + line it added to `Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1` in your user folder (or to the + file `CODEGRAPH_PS_PROFILE` named). The + [completions reference](../../../cli.md#codegraph-completions--shell-completions) names the files. +5. **Remove files you asked for**: diagnostic logs written with `--debug-log ` and graphs written with + `codegraph export -o ` stay where you put them. +6. **Delete the executable**: `$HOME/.local/bin/codegraph`, or `codegraph.exe` in `%LOCALAPPDATA%\Programs\codegraph` + on Windows, or the directory you chose with `CODEGRAPH_INSTALL_DIR`. With `cargo install`, run + `cargo uninstall codegraph-rs`. On Windows, also remove that directory from your user `PATH`. + +Neither `uninstall` nor `uninit` removes the executable. [Data and network](../privacy.md) lists everything CodeGraph +writes, including the small registry files running MCP servers keep in your user state directory. diff --git a/docs/site/en/guide/keeping-current.md b/docs/site/en/guide/keeping-current.md new file mode 100644 index 0000000..d5ec798 --- /dev/null +++ b/docs/site/en/guide/keeping-current.md @@ -0,0 +1,57 @@ +# Keeping the index current + +This page explains how the index follows your edits, how to update it yourself, and how to use CodeGraph in CI. + +## In the background + +When an agent or editor starts `codegraph serve --mcp` for an indexed project, CodeGraph starts one background +process for that project, or joins the one already running. It watches the project's files and re-indexes the ones +that change, after a short pause that groups a burst of saves into one update (two seconds by default). Every agent, +editor and terminal on the project shares that process, and it exits on its own a few minutes after the last one +disconnects. + +The watcher skips the directories the index skips (`.gitignore`, `node_modules`, `target` and the other defaults), so +large dependency trees cost nothing. Editing `.codegraph/config.toml`, `.codegraph/codegraph.json` or the root +`.gitignore` takes effect without a restart. + +The index trails a save by about a second. In that window a tool may read a file whose stored line numbers no longer +match its bytes. CodeGraph checks every file before it shows source from it, and a changed file is shown whole or +not at all, never cut at stale line numbers. The answer says which files were affected. + +Watching is turned off automatically where it cannot work well: on WSL for projects under `/mnt/`, and when the +project root would be your home directory or the filesystem root. + +## By hand + +```sh +codegraph sync . # re-index what changed, drop what was deleted +codegraph status . # is the index current, and what changed since +codegraph index --force . # rebuild from scratch, only when a command asks for it +``` + +`sync` compares each file's size and modification time with the index, re-reads only what changed, and updates every +reference those changes can move. Its result is the same as a full rebuild; the project's tests check that byte for +byte. In a Git repository, `status` finds changed files through Git when it can trust it, which keeps it fast on +large trees. + +## In CI and scripts + +```sh +export CODEGRAPH_NO_DAEMON=1 # stay in the foreground; start no background process +codegraph init . # or `codegraph sync .` on a cached index +codegraph affected src/pricing.ts -p . --filter 'tests/*' +``` + +`affected` takes changed files and lists the files that depend on them, transitively, and the test files among them, +so a pipeline can run only the tests a change can reach. `--depth` limits how far it follows dependents. + +With `CODEGRAPH_NO_DAEMON=1`, `serve --mcp` also stays in the foreground. Only one such server may keep a project's +index up to date at a time; a second one exits and names the first. `serve --no-watch` keeps a server's first +catch-up but stops it from watching afterwards. + +## When something is stuck + +- `codegraph status .` explains an index it cannot use and prints the command that fixes it. +- `codegraph unlock .` removes a lock left behind by a process that crashed. It leaves a live process's lock alone. +- The [CLI reference](../../../cli.md#daemon-watch--environment-variables) lists every environment variable that tunes + the background process, and [Troubleshooting](../../../troubleshooting.md) shows how to record a diagnostic log. diff --git a/docs/site/en/guide/quick-start.md b/docs/site/en/guide/quick-start.md new file mode 100644 index 0000000..214fe6e --- /dev/null +++ b/docs/site/en/guide/quick-start.md @@ -0,0 +1,214 @@ +# Quick start + +This page indexes a small project and asks it the questions CodeGraph is for, with the output you should see. + +You need CodeGraph installed ([Install](install.md)). The commands below run in the project directory: `init` and +`status` take the project as a positional `.`, and the queries take it with `-p .`. They work the same way in your own +repository. + +## A sample project + +The examples use a four-file TypeScript shop. Create it in an empty directory to follow along: + +::: details The four files + +`src/cart.ts` + +```typescript +export interface Item { + name: string; + price: number; + quantity: number; +} + +export class Cart { + private items: Item[] = []; + + add(item: Item): void { + this.items.push(item); + } + + subtotal(): number { + return this.items.reduce((sum, item) => sum + item.price * item.quantity, 0); + } +} +``` + +`src/pricing.ts` + +```typescript +const DISCOUNTS: Record = { SPRING: 0.1, MEMBER: 0.05 }; + +export function applyDiscount(amount: number, code?: string): number { + const rate = code ? (DISCOUNTS[code] ?? 0) : 0; + return roundCents(amount * (1 - rate)); +} + +export function tax(amount: number): number { + return roundCents(amount * 0.08); +} + +function roundCents(value: number): number { + return Math.round(value * 100) / 100; +} +``` + +`src/checkout.ts` + +```typescript +import { Cart } from "./cart"; +import { applyDiscount, tax } from "./pricing"; + +export function checkout(cart: Cart, code?: string): number { + const discounted = applyDiscount(cart.subtotal(), code); + return discounted + tax(discounted); +} +``` + +`src/main.ts` + +```typescript +import { Cart } from "./cart"; +import { checkout } from "./checkout"; + +const cart = new Cart(); +cart.add({ name: "notebook", price: 4.5, quantity: 2 }); +cart.add({ name: "pen", price: 1.2, quantity: 3 }); +console.log(checkout(cart, "SPRING")); +``` + +::: + +## 1. Build the index + +```sh +cd shop +codegraph init . +``` + +```text +Scanning files… +Initialized in /tmp/shop +Indexed 4 files +22 nodes, 39 edges in 94ms +``` + +`init` creates `.codegraph/` in the project and indexes every file it recognises. Files ignored by `.gitignore`, and +dependency and build directories such as `node_modules` and `target`, are left out. Add `.codegraph/` to your +`.gitignore`: it is a local cache, rebuilt from the source at any time. + +## 2. Check it + +```sh +codegraph status . +``` + +```text +CodeGraph Status + +Project: /tmp/shop + +Index Statistics: + Files: 4 + Nodes: 22 + Edges: 39 + DB Size: 0.16 MB + Backend: rusqlite - bundled SQLite + Journal: wal + + DB Path: /tmp/shop/.codegraph/codegraph.db + Daemon: stopped + +Nodes by Kind: + class 1 + constant 2 + file 4 + function 4 + import 4 + interface 1 + method 2 + property 4 + +Files by Language: + typescript 4 + +Index is up to date +``` + +`status --json` gives the same facts for scripts, including whether the index is current or which files changed +since it was built. + +## 3. Read one symbol + +```sh +codegraph node applyDiscount -p . +``` + +````text +## applyDiscount (function) + +**Location:** src/pricing.ts:3 +**Signature:** `(amount: number, code?: string): number` + +```typescript +3 export function applyDiscount(amount: number, code?: string): number { +4 const rate = code ? (DISCOUNTS[code] ?? 0) : 0; +5 return roundCents(amount * (1 - rate)); +6 } +``` +### Trail — codegraph_node any of these to follow it (no Read needed) +**Calls →** roundCents (src/pricing.ts:12) +**Called by ←** checkout (src/checkout.ts:4), checkout.ts (src/checkout.ts:1) +```` + +`node` prints a symbol's source with what it calls and what calls it, so you can keep following the trail. Given a +file path instead, it prints the file with line numbers and the files that depend on it. Output is Markdown, because +the same text goes to coding agents. + +## 4. Ask about an area + +```sh +codegraph explore "how does checkout compute the total" -p . +``` + +````text +## Exploration: how does checkout compute the total + +Found 10 symbols across 4 files. + +### Blast radius — what depends on these (update/verify before editing) + +- `checkout` (src/checkout.ts:4) — 1 caller in `src/main.ts`; no tests found within 3 caller hops + +### Source Code + +> The code below is the **verbatim, current on-disk source** of these files — re-read from disk on this call and line-numbered, byte-for-byte identical to what the Read tool returns. It is NOT a summary, outline, or stale cache. Treat each block as a Read you have already performed: do not Read a file shown here. + +#### src/cart.ts — Cart(class), subtotal(method) + +```typescript +1 export interface Item { +… +``` +```` + +The output continues with the source of all four files. `explore` takes a question or a list of names, finds the +symbols involved, and returns their source grouped by file, what depends on them, and the calls between them. It is +the command line's view of `codegraph_explore`, the tool coding agents call most. + +## 5. Follow calls and changes + +| Command | Lists | +| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| `codegraph search applyDiscount -p .` | the symbols whose name matches, best match first, with their location and signature | +| `codegraph callers applyDiscount -p .` | what calls or imports it: here `checkout` and the file `checkout.ts` | +| `codegraph callees checkout -p .` | what it calls: `applyDiscount`, `subtotal`, `tax`, and the `Cart` type it uses | +| `codegraph impact applyDiscount -p .` | everything a change would reach, through callers of callers, grouped by file: here `checkout`, `checkout.ts` and `main.ts` | + +Each of them takes `--json` for scripts. + +## Next steps + +- [Connect a coding agent](agents.md) so it can ask these questions itself. +- [Open the browser viewer](viewer.md) to read the same index visually. +- [Keep the index current](keeping-current.md) as you edit. diff --git a/docs/site/en/guide/viewer.md b/docs/site/en/guide/viewer.md new file mode 100644 index 0000000..7e17699 --- /dev/null +++ b/docs/site/en/guide/viewer.md @@ -0,0 +1,114 @@ +# The browser viewer + +This page shows how to open CodeGraph's browser viewer and what each of its views is for. + +The viewer reads a project's existing index and shows it in a browser on your own computer: a symbol with its callers, +source and callees side by side, a file's outline, the call path from one function to another, the repository as a +map of modules, a type's hierarchy and the code nothing reaches. It is a **preview**: it is switched off unless you +turn it on, and the views may still change. + +## Open it + +```sh +CODEGRAPH_UI=1 codegraph ui # the indexed project you are in +CODEGRAPH_UI=1 codegraph ui ~/code/my-app # another indexed project +CODEGRAPH_UI=1 codegraph ui --no-open # print the address; do not open a browser +CODEGRAPH_UI=1 codegraph ui --read-only # also refuse to save trails +``` + +Without `CODEGRAPH_UI=1` the command is refused and left out of `--help`. The viewer listens on `127.0.0.1`, on port +4747 or the next free one after it (`--port` picks one), and stops with `Ctrl+C`. + +It never builds or changes the index: index the project first with `codegraph init`. The only thing it writes is a +**trail** you choose to save, a walk through the code kept under `.codegraph/ui/trails/`. + +Press `Ctrl+K` (`⌘K` on macOS) anywhere to search for a symbol or a file, or to ask for a path such as +`how does checkout reach tax`. + +## Start + + + +The viewer opens on a start page built from what the index already holds. Under the project name and its index state +are three ways in: **Open the map**, **Search** and **Read a flow**. The cards below show: + +- what the graph holds, by node and edge kind; +- the trails you saved; +- the production symbols the most code depends on; +- where the code starts: the files that run something at their top level, or the routes when the index holds routes; +- the test files that reach the most other files; +- the indexed files by language. + +Every name opens its symbol or file, and **All entry points** lists every entry point, grouped by file. + +## Symbol + + + +The middle column is the symbol's source, with every call it makes marked in the margin and linked to the column on +the right, which lists what it calls. The left column lists its callers, grouped by file. Under them, **blast radius** +counts what a change would reach: direct callers, callers within three hops, and the production and test files among +them. Every name opens that symbol, and the trail bar at the top keeps the path you took. + +## Type hierarchy + + + +For a class, interface or trait, the Symbol view adds its hierarchy: what it extends and implements above, and what +extends or implements it below. A call through such a type is flagged when it dispatches to several implementations, +because no single static target exists. + +## File + + + +A file's outline lists its symbols in source order with how much points in and out of each. The side columns are the +files that import it and the files it imports; names outside the index, such as standard-library paths, are listed +but not linked. **Whole-file source** shows the file line by line with its calls. + +## Flow + + + +Flow answers "how does A reach B": each card is one hop, opened at the line that makes the next call, and the table +below lists every hop with where the call is and how confidently it was resolved. This capture is CodeGraph's own +`codegraph explore` command reaching the engine that also serves the MCP tool. When no chain of calls connects the +two, the view says so and names the usual reasons, such as a callback or a reflective call. + +## Map + + + +The map groups files into modules and lays them out by dependency: each module sits one layer above the modules it +depends on, so the foundations end up at the bottom and the entry points at the top. Line weight is how many calls, +imports and type references cross between two modules. Choose the folder and grouping depth on the right; **Copy +image** and **Download SVG** export the map as drawn. + +## Dead code + + + +Dead code lists symbols that nothing in the index reaches, largest first. The panel on the right explains what the +list leaves out and why: exported symbols, test files, symbols in component files whose markup can reach them, and +others. What remains has no static reference, which is not proof that it is unused: macros, trait objects and +reflection can still reach it. + +## Start, entry points, screens and steps + +The start page summarises the index: what it holds, the most depended-on symbols, where execution starts, and the +tests that reach furthest. **Entry points** lists those starting places in full, with saved trails first. + +**Screens** and **Steps** need graph facts this version does not record yet: Screens reports that it found no screen +navigation, and Steps says it cannot draw steps. The [viewer reference](../../../ui.md#differences-from-upstream) +lists what is still missing. + +## Themes + +The viewer follows your system's light or dark setting until you choose one with the theme control at the bottom of +the left rail. Below 600 px wide a tab bar replaces the rail, and the Symbol view shows one pane at a time. + +## How it stays safe + +The viewer listens on `127.0.0.1` only. It refuses requests whose `Host` or `Origin` is not its own, and writes that +lack its header. It opens only files the index names inside the project. The +[viewer reference](../../../ui.md#boundary) lists every check. diff --git a/docs/site/en/guide/what-is-codegraph.md b/docs/site/en/guide/what-is-codegraph.md new file mode 100644 index 0000000..431d6a5 --- /dev/null +++ b/docs/site/en/guide/what-is-codegraph.md @@ -0,0 +1,65 @@ +# What is CodeGraph + +This page explains what CodeGraph answers, how it builds those answers, and where its answers stop. + +CodeGraph reads a repository once with tree-sitter, records every symbol and every call, import and reference +between symbols in a local SQLite index, and answers structural questions from that index: + +- Where is this function defined, and what does it look like? +- Who calls it, and what does it call? +- If I change it, which symbols and files are affected, including callers of callers? +- How does one function reach another? +- Which tests reach this code? + +Text search finds strings. It cannot tell a call from a comment that mentions the same name, a method from a +same-named method on another type, or a direct caller from a caller three hops away. CodeGraph answers from the +parsed structure instead. + +## How it works + +1. **Parse.** Each file is parsed with a grammar for its language. Functions, classes, methods, imports, call sites + and references become nodes and edges. +2. **Resolve.** References are matched to their definitions across files, through imports first and then by name. + Every edge records how it was matched and with what confidence, and a reference that matches nothing stays + unresolved. +3. **Store.** Nodes, edges and a full-text search index go into SQLite inside the project's `.codegraph/` directory. + SQLite is built into the executable. +4. **Query.** Every command and tool reads that index. Nothing re-scans the repository to answer a question. +5. **Stay current.** A background process watches the project and re-indexes the files that change. + [Keeping the index current](keeping-current.md) covers it. + +## One index, three ways in + +| Way in | For | Starts with | +| -------------- | ------------------------- | -------------------------------------------------------------------------- | +| Command line | you, scripts and CI | `codegraph explore`, `codegraph search`, `codegraph impact` | +| MCP server | coding agents and editors | `codegraph serve --mcp`, written into agent configs by `codegraph install` | +| Browser viewer | reading unfamiliar code | `CODEGRAPH_UI=1 codegraph ui` (preview) | + +The command line and the MCP tools run the same engine. `codegraph explore` prints exactly what the +`codegraph_explore` tool returns to an agent, so you can check what an agent was told. + +## The same answer every time + +CodeGraph contains no model: no embeddings, no vector search and no language model. Parsing and resolution are +deterministic, so the same files and configuration produce the same index, and the same question returns the same +answer, on any machine. An incremental `codegraph sync` converges with a full rebuild, and the project's test suite +checks that byte for byte. + +## What it does not do + +- **No similarity search.** It answers questions about the structure that is in the code. It does not find code by + "roughly what it means". +- **No judgement.** It shows relationships and reach. Whether the code is correct is still a question for your + compiler, linter and tests. +- **No runtime knowledge.** Reflection, callbacks registered at runtime and calls built from strings leave no static + edge, so a path through them does not appear. A call through an interface or trait with several implementations is + reported as such rather than tied to one of them. +- **A fixed set of languages.** A file in a language CodeGraph does not parse is not in the graph. The + [language reference](../../../languages.md) lists what each tier extracts. + +## Next steps + +- [Install](install.md) +- [Quick start](quick-start.md) +- [Connect a coding agent](agents.md) diff --git a/docs/site/en/index.md b/docs/site/en/index.md new file mode 100644 index 0000000..5d82e27 --- /dev/null +++ b/docs/site/en/index.md @@ -0,0 +1,283 @@ +--- +layout: home +title: "CodeGraph: a local code knowledge graph for agents and people" +titleTemplate: false +description: CodeGraph parses a repository with tree-sitter into a local index of symbols and calls, and answers who calls a function, what a change reaches and how one function reaches another, on the command line, over MCP and in a browser viewer. No model involved. + +hero: + name: CodeGraph + text: Who calls this, and what does changing it reach + tagline: CodeGraph parses a repository with tree-sitter into a local index of symbols, calls and imports, and answers structural questions from it, on the command line, for coding agents over MCP, and in a browser viewer. There is no model inside, so the same repository gives the same answer on every machine. + actions: + - theme: brand + text: Install + link: /en/guide/install + - theme: alt + text: Quick start + link: /en/guide/quick-start + - theme: alt + text: GitHub + link: https://github.com/sunerpy/codegraph-rust + +home: + facts: + - term: Runs on + text: Linux, macOS and Windows, on x86_64 and ARM64. One executable with SQLite built in. + - term: Your code + text: The index stays in the project's .codegraph directory. Indexing and queries never go online. + + visual: + desktop: + light: /screens/viewer-symbol-light.webp + dark: /screens/viewer-symbol-dark.webp + width: 1440 + height: 900 + alt: The CodeGraph viewer showing the method IndexPaths::resolve, with its callers on the left, its source in the middle and the functions it calls on the right. + + index: + title: What CodeGraph does + intro: The browser viewer is a preview and is switched off unless you turn it on; everything else is part of the regular command set. + groups: + - name: Ask + items: + - title: Explore an area + body: Ask a question or name a few symbols; get their source grouped by file, what depends on them, and the calls between them. + status: available + link: /en/guide/quick-start + - title: Read a symbol or a file + body: A symbol's source with what it calls and what calls it, or a file with line numbers and the files that depend on it. + status: available + link: /en/guide/quick-start + - title: Callers, callees and impact + body: One step either way, or everything a change reaches through callers of callers. + status: available + link: /en/guide/quick-start + - title: Affected tests + body: From a list of changed files, the files that depend on them and the tests among them. + status: available + link: /en/guide/keeping-current + - name: Connect + items: + - title: MCP for coding agents + body: Read-only tools over standard input and output, written into each installed agent's config by one command. + status: available + link: /en/guide/agents + - title: MCP over HTTP + body: The same tools over streamable HTTP on the local machine, for editors and remote development. + status: available + link: /en/guide/agents + - title: Agent skill + body: Instructions that tell an agent which tool to use when, installed into each agent's skill directory. + status: available + link: /en/guide/agents + - name: Stay current + items: + - title: Watch and update + body: One background process per project, shared by every client, re-indexes the files you change. + status: available + link: /en/guide/keeping-current + - title: Incremental sync + body: Re-reads only what changed and ends up identical to a full rebuild. + status: available + link: /en/guide/keeping-current + - name: See + items: + - title: Browser viewer + body: Symbols, files, call paths, a module map, type hierarchies and unreached code, in light and dark. + status: preview + link: /en/guide/viewer + - name: Languages + items: + - title: Full symbol extraction + body: TypeScript, JavaScript, Python, Go, Rust, Java, C, C++, C#, PHP, Ruby, Swift, Kotlin and more. + status: available + link: /en/reference/languages + - title: Templates and components + body: Vue, Svelte, Astro, Razor and Liquid files, and MyBatis mapper XML. + status: available + link: /en/reference/languages + - title: Godot projects + body: Scenes, resources, scripts, autoloads and signal handlers, with a resource audit. + status: available + link: /en/reference/godot + + steps: + title: From install to the first answer + items: + - title: Install + command: curl -fsSL https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.sh | sh + body: Or the PowerShell script on Windows, or an archive from the releases page. + - title: Index a project + command: codegraph init . + body: Builds the index in the project's .codegraph directory. Later updates read only what changed. + - title: Ask a question + command: codegraph explore "how does checkout compute the total" -p . + body: Returns the relevant source, what depends on it and the calls between it. + - title: Connect your agent + command: codegraph install --yes + body: Adds the MCP server to the config of every agent it finds. + + tools: + columns: [Question, Command line, MCP tool] + rows: + - question: How does this area work? + cli: codegraph explore + mcp: codegraph_explore + - question: Show me this symbol or file + cli: codegraph node + mcp: codegraph_node + - question: Where is it defined? + cli: codegraph search + mcp: codegraph_search + - question: Who calls it? + cli: codegraph callers + mcp: codegraph_callers + - question: What does changing it reach? + cli: codegraph impact + mcp: codegraph_impact + caption: Both sides run the same engine, so an agent and you get the same answer. Every tool is read-only. + + shots: + flow: + light: /screens/viewer-flow-light.webp + dark: /screens/viewer-flow-dark.webp + width: 1440 + height: 900 + alt: The viewer's Flow view from cmd_explore to explore_file_header, one card per call and a table of every hop with its confidence. + + languages: + columns: [Depth, What is extracted, Languages] + rows: + - depth: Full symbols + extracted: Functions, classes, methods, imports, calls and references + members: TypeScript, TSX, JavaScript, JSX, ArkTS, Python, Go, Rust, Java, C, C++, C#, PHP, Ruby, Swift, Kotlin, Dart, Scala, Lua, Luau, Objective-C, R, Solidity, Nix, Terraform, Erlang, GDScript, Pascal, CFML + - depth: Embedded + extracted: The scripts and template markup inside a host file + members: Vue, Svelte, Astro, Razor, Liquid, MyBatis XML + - depth: File level + extracted: Files and the references between them + members: YAML, Twig, Properties, and Godot scene, resource and project files + caption: A file in a language outside this table is not in the graph. Extensions can be mapped onto these languages in .codegraph/codegraph.json. + + platforms: + title: Platforms + intro: Every release has an archive for each platform, a SHA256SUMS file and a build attestation per archive. + columns: [Platform, Target, Archive] + rows: + - name: Linux x86_64 + status: available + cells: [x86_64-unknown-linux-musl, .tar.gz] + - name: Linux ARM64 + status: available + cells: [aarch64-unknown-linux-musl, .tar.gz] + - name: macOS Intel + status: available + cells: [x86_64-apple-darwin, .tar.gz] + - name: macOS Apple Silicon + status: available + cells: [aarch64-apple-darwin, .tar.gz] + - name: Windows x86_64 + status: available + cells: [x86_64-pc-windows-msvc, .zip] + - name: Windows ARM64 + status: available + cells: [aarch64-pc-windows-msvc, .zip] + note: The Linux builds are statically linked and need no system library. Building from source needs a Rust toolchain and a C compiler. + + privacy: + title: What stays on your machine + intro: CodeGraph depends on no hosted service. + sendsLabel: Goes online + modes: + - name: Indexing and queries + sends: Nothing + detail: The index is a SQLite database inside the project. Parsing, resolution and every query run locally. + - name: Agents, editors and the viewer + sends: Nothing + detail: The MCP server talks to the program that started it; the HTTP server and the viewer listen on the local machine. + - name: Install and updates + sends: Downloads from GitHub + detail: The install scripts and codegraph self-update fetch releases from GitHub Releases. + + scope: + title: What it does not do + items: + - It runs no model, no embeddings and no vector search; it answers from the parsed structure only. + - It does not judge code. Whether it is correct stays with your compiler, linter and tests. + - It does not see run time. Reflection, runtime callbacks and calls built from strings leave no edge. + - It does not guess at languages it cannot parse. +--- + + + + + + + +## For coding agents + +An agent with CodeGraph asks one structural question instead of searching and reading files one at a time, and gets +back the relevant source together with the calls between it. Answers come from the parsed code, so they are the +same on every run. + +`codegraph install --yes` writes the MCP server into the config of Claude Code, Cursor, Codex CLI, Kiro, Zed, VS Code +and the other agents it supports. + +[Connect a coding agent](guide/agents.md) · [MCP reference](../../mcp.md) + + + + + +## For you, in the browser + +The viewer reads the same index: a symbol with its callers and callees, the call path from one function to another, +the repository as a map of modules, the hierarchy of a type, and the code nothing reaches. It runs on your computer +and only reads. + +[The browser viewer](guide/viewer.md) + + + + + +## Many languages, at an honest depth + +Most languages get full symbol extraction. Components and templates get their embedded scripts and markup, and a few +formats are tracked at file level. The table says which is which, rather than one number for all of them. + +[Supported languages](../../languages.md) · [Godot](../../godot.md) + + + + + + + +## Install + +::: code-group + +```sh [Linux and macOS] +curl -fsSL https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.sh | sh +``` + +```powershell [Windows] +irm https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.ps1 | iex +``` + +```sh [From source] +cargo install --locked --git https://github.com/sunerpy/codegraph-rust codegraph-rs +``` + +::: + +The scripts check every archive against the release's `SHA256SUMS` before installing it. The +[install guide](guide/install.md) covers pinning a version, updating and removing CodeGraph. + + + +## Feedback + +Bug reports and feature requests go to [GitHub Issues](https://github.com/sunerpy/codegraph-rust/issues). CodeGraph is +MIT-licensed. diff --git a/docs/site/en/privacy.md b/docs/site/en/privacy.md new file mode 100644 index 0000000..c3e776c --- /dev/null +++ b/docs/site/en/privacy.md @@ -0,0 +1,50 @@ +# Data and network + +This page lists everything CodeGraph reads, writes and connects to, so you can decide where to run it. + +## What it reads + +The files of the project you index, within the rules described in [Configuration](guide/configuration.md): what +`.gitignore`, `config.toml` and the default skip lists leave out is never read. + +## What it writes + +| Where | What | Written by | +| --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| `/.codegraph/` | The SQLite index, its settings and the background process's lock, socket and log | `init`, `index`, `sync`, and the background process | +| `/.codegraph/ui/trails/` | Trails you chose to save in the viewer | the viewer, only when you save one | +| `/.codegraph/diagnostics/` | Diagnostic logs | `init`, `index` and `sync`, only with `--debug` | +| The file you name | A diagnostic log | `--debug-log ` on `init`, `index` or `sync` | +| The file you name | The whole graph as JSON | `codegraph export -o ` | +| Your agents' and editors' config files | The `codegraph` MCP entry, and instruction blocks between `` and `` | `codegraph install` | +| A project's own agent config files (`.vscode/mcp.json`, `.zed/settings.json` and so on) | A `codegraph` entry pinned to that project | `codegraph init --target=` | +| Your agents' skill directories | The CodeGraph skill | `codegraph skill install` | +| Your shell's completion directory | A completion script | `codegraph completions --install` | +| `%USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`, or the file in `CODEGRAPH_PS_PROFILE` | One line that loads the PowerShell completion script | `codegraph completions powershell --install` | +| Your user state directory: `$XDG_STATE_HOME/codegraph/`, else `~/.local/state/codegraph/`; `%LOCALAPPDATA%\codegraph\` on Windows | One small file per running MCP server, so `codegraph mcp list` and `codegraph http list` can find them, and a log per HTTP server started with `--detach` | `serve --mcp` and `serve --http`. Entries are cleared once the server has exited; the logs stay until you delete them | +| The system temp directory | The background process's socket, only on filesystems that cannot hold one inside `.codegraph/` | the background process | +| The `codegraph` executable | The new version | `codegraph self-update` | + +On a WSL Windows drive the project directory is `.codegraph-wsl/` instead of `.codegraph/`, and `CODEGRAPH_DIR` +chooses another name. + +[Uninstall](guide/install.md#uninstall) removes all of it. + +## What goes online + +| Action | Connects to | +| ---------------------------------------------- | ----------------------------- | +| Indexing, sync, every query and every MCP tool | nothing | +| `codegraph self-update`, the install scripts | GitHub, to download a release | + +## What listens for connections + +| Server | Listens on | Notes | +| ------------------------ | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `codegraph serve --mcp` | nothing | It talks over standard input and output with the program that started it. | +| The background process | a local socket in `.codegraph/` (or the system temp directory where the filesystem cannot hold one) | Only processes on the same machine can connect; the project's MCP servers use it. | +| `codegraph serve --http` | `127.0.0.1:8111` | `--http-addr` can choose another address, including one other machines can reach. It has **no authentication**, and it accepts any `Host` header unless `CODEGRAPH_HTTP_ALLOWED_HOSTS` lists the allowed ones. Keep it on the local machine, or put your own access control in front of it. | +| `codegraph ui` | `127.0.0.1` only | It refuses requests from other sites and opens only files the index names. | + +The index and its answers contain your source code. Anyone who can reach a CodeGraph server can read the code it +indexes. diff --git a/docs/site/en/reference/faq.md b/docs/site/en/reference/faq.md new file mode 100644 index 0000000..e479989 --- /dev/null +++ b/docs/site/en/reference/faq.md @@ -0,0 +1,64 @@ +# Frequently asked questions + +This page answers the questions people ask most often when they start using CodeGraph. + +## Does CodeGraph use AI, or send my code anywhere? + +No. CodeGraph contains no model of any kind, and indexing and queries run entirely on your computer. The only commands +that go online are the install scripts and `codegraph self-update`, which download releases from GitHub. +[Data and network](../privacy.md) lists everything CodeGraph reads, writes and opens. + +## Should I commit `.codegraph/`? + +No. It is a local cache that can be rebuilt from the source at any time, and its contents depend on the machine. Add +`.codegraph/` to your `.gitignore`. + +## A call I can see in the code is missing. Why? + +Usually one of these: + +- the call goes through something only known at run time: a callback, reflection, a name built from a string; +- the name matches several definitions and the context does not decide between them; +- the file is in a language CodeGraph does not parse, is excluded by `.gitignore` or `config.toml`, or is larger than + `indexing.max_file_size`; +- the file changed and has not been re-indexed yet: `codegraph status` shows pending changes. + +`codegraph node ` shows what the index knows about a symbol, which narrows down which case it is. + +## It says the index belongs to a different filesystem location. + +The project was moved or copied together with its `.codegraph/` directory. An index is tied to the location it was +built in, so CodeGraph refuses to use it elsewhere rather than answer about the wrong files. Run +`codegraph init ` in the new location to replace it. + +## It says the index was built by a newer CodeGraph version. + +A newer release built this index, and the copy of CodeGraph reading it is older. CodeGraph will not guess at a format +it does not know. Update every copy, including the one your agent or editor starts, with `codegraph self-update` or +the install script. After an update, restart the agents and editors that were already running. + +## My agent asks for `projectPath` on every call. + +The MCP server did not find a project to default to. Index the project with `codegraph init`, start the agent from +inside the project, or pin the project in the agent's config with `-p `. +[Connect a coding agent](../guide/agents.md#which-project-the-server-answers-for) + +## A command reports a lock, or seems stuck. + +Another CodeGraph process may be writing to the same index; wait for it to finish. If a process crashed and left its +lock behind, `codegraph unlock ` removes it and leaves the lock of a live process alone. For a slow index, +`codegraph index --debug-log index.jsonl` records what each file took; [Troubleshooting](../../../troubleshooting.md) +explains the log. + +## Does it work on Windows and WSL? + +Yes. Windows has its own builds for x86_64 and ARM64. Under WSL, a new index for a project on a Windows drive +(`/mnt/c/…`) goes into its own directory, `.codegraph-wsl/`, because SQLite's locking does not work across the Windows +and WSL boundary; an index already in `.codegraph/` there is kept. File watching under `/mnt/` is off. + +## How do I report a problem? + +Open an issue on [GitHub](https://github.com/sunerpy/codegraph-rust/issues) with the version (`codegraph --version`), +your platform, the command and its output. For indexing problems, attach the diagnostic log described in +[Troubleshooting](../../../troubleshooting.md). It records project-relative paths and timings, not source text, file +contents or environment variables. diff --git a/docs/site/guide/agents.md b/docs/site/guide/agents.md new file mode 100644 index 0000000..fd7fdee --- /dev/null +++ b/docs/site/guide/agents.md @@ -0,0 +1,94 @@ +# 接入编码 Agent + +本页说明如何让编码 Agent 或编辑器通过 MCP 使用 CodeGraph 的索引,以及接入后 Agent 可以问哪些问题。 + +CodeGraph 以 MCP 服务的形式运行。配置好的 Agent 用工具调用提出结构性问题,不必逐个搜索和读取文件,得到的回答直接包含相关源码以及它们之间的调用关系。 + +## 自动写入配置 + +```sh +codegraph install --yes +``` + +`install` 会找出本机已安装的 Agent,在各自的 MCP 配置中添加一个 `codegraph` 条目,用来启动 `codegraph serve --mcp`。重复运行会原地更新这个条目,同一文件中的其他 MCP 服务保持不变。 + +支持的 Agent 和编辑器:Claude Code、Cursor、Codex CLI、opencode、Hermes Agent、Gemini CLI、Antigravity IDE、Kiro、Trae、Qoder、Zed、Zuno、VS Code(GitHub Copilot)、GitHub Copilot CLI 和 JetBrains IDE(GitHub Copilot)。 + +| 需要 | 运行 | +| ---------------------------------- | ------------------------------------------------ | +| 指定 Agent | `codegraph install --target=claude,cursor --yes` | +| 写入项目自己的配置,而不是全局配置 | `codegraph install --target=auto --local` | +| 只查看要写入的条目,不实际写入 | `codegraph install --print-config cursor` | +| 安装并为当前项目建立索引 | `codegraph install --yes --init` | +| 移除这些条目 | `codegraph uninstall` | + +有些编辑器在项目之外启动 MCP 服务,也不告诉它打开的是哪个项目。Kiro、Zed 和 VS Code 读取的全局条目无法指定项目,只能回答每次调用中显式指定的索引。对这些编辑器,在项目中运行 `codegraph init --target=<编辑器>`,会写入一个指定该项目的项目级条目,同时为该项目启用实时更新。Cursor 的全局条目会自动指向当前打开的文件夹。[CLI 参考](../../cli.md#codegraph-install--uninstall--wire-up-ai-agents)列出了各 Agent 使用的配置文件。 + +## 安装 Agent Skill + +```sh +codegraph skill install +``` + +Skill 是一份简短的说明文件,告诉 Agent 在什么情况下使用哪个 CodeGraph 工具。`codegraph skill status` 显示哪些 Agent 已安装以及是否为最新;升级后运行 `codegraph skill update` 即可更新。 + +## 手动配置 + +任何 MCP 客户端都可以自行启动这个服务: + +```json +{ + "mcpServers": { + "codegraph": { + "command": "codegraph", + "args": ["serve", "--mcp"] + } + } +} +``` + +服务通过标准输入和标准输出通信。如果希望不论客户端在哪里启动服务,都固定使用同一个项目,请在 `args` 中加上 `"-p", "/path/to/project"`。 + +## 服务为哪个项目作答 + +不带 `-p` 启动时,服务按以下顺序寻找项目: + +1. 工作目录本身或其上层中最近的、已建立索引的目录; +2. 如果没有找到,而工作目录是仓库或工作区的根目录,则使用其下唯一一个已建立索引的项目(必须恰好只有一个); +3. 客户端连接时声明的工作区,前提是该工作区已建立索引。 + +如果都没有找到,所有工具仍然可用,但每次调用都必须用 `projectPath` 指定项目。存在多个已建立索引的项目时,服务不会替你猜测。[MCP 参考](../../mcp.md#project-resolution) + +## Agent 可以问什么 + +| 问题 | MCP 工具 | 对应的命令行 | +| ---------------------- | ------------------- | ---------------------------- | +| 这块代码是怎么工作的? | `codegraph_explore` | `codegraph explore "<问题>"` | +| 查看这个符号或文件 | `codegraph_node` | `codegraph node <名称>` | +| 它在哪里定义? | `codegraph_search` | `codegraph search <名称>` | +| 谁调用了它? | `codegraph_callers` | `codegraph callers <名称>` | +| 它调用了什么? | `codegraph_callees` | `codegraph callees <名称>` | +| 改动它会影响哪里? | `codegraph_impact` | `codegraph impact <名称>` | +| 索引是否最新? | `codegraph_status` | `codegraph status` | +| 哪些文件已建立索引? | `codegraph_files` | `codegraph files` | +| 有没有循环导入? | `codegraph_check` | `codegraph check` | +| 导出整张图 | `codegraph_export` | `codegraph export` | + +Agent 的工具列表中默认显示前四个工具,其余工具仍然可以调用。设置 `CODEGRAPH_MCP_TOOLS` 可以显示更多工具,例如 `CODEGRAPH_MCP_TOOLS=explore,node,search,callers,impact`。所有工具都是只读的,并按 MCP 的约定做了标注,遵循这些标注的 Agent 不会为调用请求确认。 + +## 通过 HTTP + +偏好 HTTP 的编辑器,以及通过 SSH 进行的远程开发,可以使用 streamable HTTP 传输: + +```sh +codegraph serve --http # 监听 127.0.0.1:8111 +codegraph serve --http --detach # 同上,在后台运行 +codegraph http list # 正在运行的 HTTP 服务 +codegraph http stop 127.0.0.1:8111 +``` + +HTTP 服务没有身份验证。除非用 `--http-addr` 指定其他地址,它只监听本机;请保持这样的设置,或在它前面加上你自己的访问控制。[MCP 参考](../../mcp.md) + +## 让回答保持最新 + +服务为它负责的每个已建立索引的项目启动或加入一个后台进程,由它监听文件并更新索引。同一项目上的所有 Agent 和编辑器共用这个进程。详见[保持索引最新](keeping-current.md)。 diff --git a/docs/site/guide/configuration.md b/docs/site/guide/configuration.md new file mode 100644 index 0000000..1046b2e --- /dev/null +++ b/docs/site/guide/configuration.md @@ -0,0 +1,62 @@ +# 配置 + +本页列出影响 CodeGraph 索引范围和结果排序的设置。 + +CodeGraph 不需要任何配置即可使用。设置保存在项目 `.codegraph/` 目录下的两个可选文件中,另有几个环境变量用于调整后台进程。 + +## `.codegraph/config.toml` + +```toml +[app] +name = "my-project" + +[indexing] +exclude = ["static/", "docs/generated/"] +deprioritize = ["vendor/**"] +``` + +这个文件存在时必须包含 `[app]` 表和其中的 `name`,否则所有命令都会以 `missing field` 错误停止。其余设置都是可选的: + +| 设置 | 默认值 | 作用 | +| ------------------------ | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `app.name` | — | 项目名称。 | +| `app.log_level` | `info` | CodeGraph 向标准错误输出日志的详细程度。 | +| `indexing.exclude` | 无 | 不纳入索引的路径,写法与 `.gitignore` 规则相同(`static/`、`gen*`)。 | +| `indexing.include` | 无 | 即使被 `.gitignore` 排除也要索引的路径,适用于由另一套版本控制系统管理、未纳入 Git 的源码。`exclude` 的优先级更高,`node_modules` 等依赖目录始终不会被重新纳入。 | +| `indexing.ignore_dirs` | `node_modules`、`target`、`dist`、`.venv` 等依赖、构建和缓存目录 | 在任意层级跳过的目录名。在这里写入的列表会**替换**默认列表,需要保留的默认目录请一并写上。 | +| `indexing.ignore_paths` | Android 的 `res/` 资源目录 | 默认跳过的路径规则,写法与 `.gitignore` 相同。 | +| `indexing.max_file_size` | `1048576`(1 MiB) | 超过此大小的文件只记录,不解析。 | +| `indexing.deprioritize` | 无 | 仍然索引,但在 `search` 和 `explore` 中排在你自己的代码之后的路径。 | +| `watch.enabled` | `true` | 后台进程是否监听文件。 | +| `watch.debounce_ms` | `2000` | 监听等待一连串变化平息的时间。 | + +项目的 `.gitignore` 同样生效:Git 忽略的文件,CodeGraph 不会索引。修改 `config.toml` 或根目录的 `.gitignore` 后无需重启即可生效;如果没有后台进程在运行,请执行 `codegraph sync`。 + +## `.codegraph/codegraph.json` + +把 CodeGraph 不认识的文件扩展名映射到它能解析的语言: + +```json +{ + "extensions": { + ".blade": "php", + ".x": "lua" + } +} +``` + +扩展名匹配时不区分大小写,开头的点可有可无。CodeGraph 不认识的语言名称会被跳过;文件格式错误时会被忽略,并在日志中记录错误,不会中断索引。[CLI 参考](../../cli.md#custom-extension-mapping-codegraphcodegraphjson) + +## 环境变量 + +| 变量 | 用途 | +| ---------------------------------- | ---------------------------------------------- | +| `CODEGRAPH_NO_DAEMON=1` | 在前台运行,不启动后台进程,适用于 CI 和脚本。 | +| `CODEGRAPH_NO_WATCH=1` | 保留后台进程,但不再监听文件。 | +| `CODEGRAPH_WATCH_DEBOUNCE_MS` | 监听的等待时间,单位为毫秒。 | +| `CODEGRAPH_DAEMON_IDLE_TIMEOUT_MS` | 最后一个使用者离开后,后台进程继续保留的时间。 | +| `CODEGRAPH_MCP_TOOLS` | Agent 工具列表中显示哪些 MCP 工具。 | +| `CODEGRAPH_DIR` | 在项目中改用其他目录名代替 `.codegraph`。 | +| `CODEGRAPH_UI=1` | 开启浏览器查看器(预览)。 | + +完整列表、取值范围和默认值见 [CLI 参考](../../cli.md#environment-variable-reference)。 diff --git a/docs/site/guide/install.md b/docs/site/guide/install.md new file mode 100644 index 0000000..d5568a1 --- /dev/null +++ b/docs/site/guide/install.md @@ -0,0 +1,107 @@ +# 安装 + +本页介绍如何安装 CodeGraph、保持更新,以及如何完整卸载。 + +CodeGraph 是一个名为 `codegraph` 的可执行文件。Linux、macOS 和 Windows 的版本发布在 [GitHub Releases](https://github.com/sunerpy/codegraph-rust/releases),没有发布到 crates.io。 + +## Linux 和 macOS + +```sh +curl -fsSL https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.sh | sh +``` + +脚本会选择适合当前平台的压缩包,只有在压缩包的 SHA-256 与该版本 `SHA256SUMS` 中的记录一致时才继续,然后把 `codegraph` 安装到 `$HOME/.local/bin`。脚本需要 `curl` 或 `wget`、`tar`,以及 `sha256sum` 或 `shasum`。它不会修改 shell 配置文件:如果该目录不在 `PATH` 中,脚本会提示,由你自行添加。 + +设置 `CODEGRAPH_INSTALL_DIR` 可以安装到其他目录。 + +## Windows + +在 PowerShell 5.1 或更高版本中运行: + +```powershell +irm https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.ps1 | iex +``` + +脚本以同样的方式校验压缩包,把 `codegraph.exe` 安装到 `%LOCALAPPDATA%\Programs\codegraph`。如果该目录还不在**用户** `PATH` 中,脚本会把它加进去;重新打开终端后生效。这里同样可以用 `CODEGRAPH_INSTALL_DIR` 指定目录。 + +在 Git Bash、MSYS2 或 Cygwin 中请使用 PowerShell 脚本:shell 脚本会停止并提示改用它。 + +## 安装指定版本 + +两个脚本默认安装最新版本,设置 `CODEGRAPH_VERSION` 可以指定版本。需要可复现的安装时,请从同一个标签获取脚本: + +```sh +curl -fsSL https://raw.githubusercontent.com/sunerpy/codegraph-rust/vX.Y.Z/scripts/install.sh \ + | CODEGRAPH_VERSION=vX.Y.Z sh +``` + +```powershell +$env:CODEGRAPH_VERSION = "vX.Y.Z" +irm https://raw.githubusercontent.com/sunerpy/codegraph-rust/vX.Y.Z/scripts/install.ps1 | iex +``` + +## 自行下载压缩包 + +每个版本包含六个压缩包,每个平台一个: + +| 平台 | Target | 压缩包 | +| ------------------- | ---------------------------- | --------- | +| Linux x86_64 | `x86_64-unknown-linux-musl` | `.tar.gz` | +| Linux ARM64 | `aarch64-unknown-linux-musl` | `.tar.gz` | +| macOS Intel | `x86_64-apple-darwin` | `.tar.gz` | +| macOS Apple Silicon | `aarch64-apple-darwin` | `.tar.gz` | +| Windows x86_64 | `x86_64-pc-windows-msvc` | `.zip` | +| Windows ARM64 | `aarch64-pc-windows-msvc` | `.zip` | + +Linux 版本是静态链接的,不依赖任何系统库。解压后把 `codegraph` 放到 `PATH` 中即可。 + +每个版本还附带 `SHA256SUMS`,每个压缩包都有构建来源证明(attestation)。校验方法: + +```sh +sha256sum -c SHA256SUMS --ignore-missing +gh attestation verify codegraph-X.Y.Z-x86_64-unknown-linux-musl.tar.gz \ + --repo sunerpy/codegraph-rust \ + --signer-workflow sunerpy/codegraph-rust/.github/workflows/release.yml \ + --deny-self-hosted-runners +``` + +## 从源码构建 + +需要 Rust 工具链和 C 编译器(SQLite 和各语言的语法都从源码编译): + +```sh +cargo install --locked --git https://github.com/sunerpy/codegraph-rust codegraph-rs +``` + +包名是 `codegraph-rs`,安装的命令是 `codegraph`。仓库在 `rust-toolchain.toml` 中固定了测试所用的 Rust 版本。 + +## 检查安装 + +```sh +codegraph --version +``` + +## 更新 + +```sh +codegraph self-update # 最新版本 +codegraph self-update --check # 只检查是否有新版本 +codegraph self-update --tag vX.Y.Z # 指定版本 +``` + +`self-update` 从 GitHub Releases 下载适合当前平台的压缩包,校验后替换正在运行的可执行文件。如果 `codegraph` 所在目录需要更高权限才能写入,请以相应权限运行。 + +新版本可能会改变索引的构建方式。这种情况下,`codegraph status` 会报告索引已过期,运行 `codegraph sync` 即可重建。只有在命令明确提示索引需要恢复时,才使用 `codegraph index --force`。详见 [CLI 参考](../../cli.md#extraction-version-upgrades)。 + +## 卸载 + +先移除 CodeGraph 写入的内容,再删除可执行文件: + +1. **停止正在运行的服务**:`codegraph http list` 列出后台 HTTP 服务及其日志文件。先记下日志路径,再用 `codegraph http stop <地址>` 停止服务,然后删除该日志;服务停止后不会再出现在列表中。退出使用 CodeGraph 的 Agent 和编辑器,它们的 MCP 服务会随之结束。 +2. **移除 Agent 配置**:`codegraph uninstall` 从各 Agent 的配置中移除 CodeGraph 条目(项目内的配置加 `--local`);如果安装过 Skill,运行 `codegraph skill uninstall`。 +3. **移除每个项目的索引**:`codegraph uninit --force <项目>` 会停止该项目的后台进程,删除数据库和设置。之后 `.codegraph/` 目录仍会保留几个状态文件以及你在查看器中保存的 Trail;删除这个目录即可不留任何内容。 +4. **移除 shell 补全**:如果用 `codegraph completions --install` 安装过补全,删除补全文件;zsh 和 elvish 还要删除你添加到 shell 配置中的那一行;PowerShell 还要删除它添加到用户目录下 `Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`(或 `CODEGRAPH_PS_PROFILE` 指定的文件)中的那一行。[补全参考](../../cli.md#codegraph-completions--shell-completions)列出了这些文件。 +5. **删除你指定位置的文件**:用 `--debug-log <文件>` 写出的诊断日志和用 `codegraph export -o <文件>` 导出的图,都保留在你指定的位置。 +6. **删除可执行文件**:`$HOME/.local/bin/codegraph`,Windows 上是 `%LOCALAPPDATA%\Programs\codegraph` 中的 `codegraph.exe`,或你用 `CODEGRAPH_INSTALL_DIR` 指定的目录。通过 `cargo install` 安装的,运行 `cargo uninstall codegraph-rs`。Windows 上还要从用户 `PATH` 中移除该目录。 + +`uninstall` 和 `uninit` 都不会删除可执行文件。[数据与网络](../privacy.md)列出了 CodeGraph 写入的全部内容,包括运行中的 MCP 服务在用户状态目录中保留的小型登记文件。 diff --git a/docs/site/guide/keeping-current.md b/docs/site/guide/keeping-current.md new file mode 100644 index 0000000..962072d --- /dev/null +++ b/docs/site/guide/keeping-current.md @@ -0,0 +1,41 @@ +# 保持索引最新 + +本页说明索引如何跟上你的编辑、如何手动更新,以及如何在 CI 中使用 CodeGraph。 + +## 在后台自动更新 + +Agent 或编辑器为已建立索引的项目启动 `codegraph serve --mcp` 时,CodeGraph 会为该项目启动一个后台进程,或加入已经在运行的那个。它监听项目文件,重新索引发生变化的文件;为了把连续多次保存合并成一次更新,它会先等待片刻(默认两秒)。同一项目上的所有 Agent、编辑器和终端共用这个进程,最后一个使用者断开几分钟后,它会自行退出。 + +监听会跳过索引同样跳过的目录(`.gitignore` 中的内容、`node_modules`、`target` 以及其他默认目录),因此庞大的依赖目录不会带来额外开销。修改 `.codegraph/config.toml`、`.codegraph/codegraph.json` 或根目录的 `.gitignore` 后无需重启即可生效。 + +索引大约比保存晚一秒。在这段时间里,工具读到的文件可能与索引中记录的行号已经对不上。CodeGraph 在展示任何文件的源码之前都会检查该文件,发生变化的文件要么完整展示,要么不展示,绝不会按过期的行号截取。回答会说明哪些文件受到了影响。 + +在无法可靠监听的地方,监听会自动关闭:WSL 中 `/mnt/` 下的项目,以及项目根目录恰好是你的主目录或文件系统根目录的情况。 + +## 手动更新 + +```sh +codegraph sync . # 重新索引发生变化的文件,移除已删除的文件 +codegraph status . # 索引是否最新,以及之后有哪些变化 +codegraph index --force . # 从头重建,仅在命令要求时使用 +``` + +`sync` 把每个文件的大小和修改时间与索引对比,只重新读取发生变化的文件,并更新这些变化可能影响到的所有引用。它的结果与完整重建完全一致,项目的测试逐字节检查这一点。在 Git 仓库中,只要 Git 的信息可信,`status` 就会借助 Git 找出变化的文件,因此在大型仓库中也很快。 + +## 在 CI 和脚本中使用 + +```sh +export CODEGRAPH_NO_DAEMON=1 # 保持在前台运行,不启动后台进程 +codegraph init . # 已有缓存的索引时改用 `codegraph sync .` +codegraph affected src/pricing.ts -p . --filter 'tests/*' +``` + +`affected` 接受一组改动过的文件,列出依赖它们的文件(逐层传递)以及其中的测试文件,流水线因此可以只运行改动可能影响到的测试。`--depth` 限制沿依赖方向追踪的层数。 + +设置 `CODEGRAPH_NO_DAEMON=1` 后,`serve --mcp` 同样在前台运行。同一时间只能有一个这样的服务负责更新某个项目的索引,第二个会退出并指明第一个是谁。`serve --no-watch` 保留服务启动时的那次追赶更新,但之后不再监听。 + +## 遇到问题时 + +- `codegraph status .` 会说明它无法使用索引的原因,并给出修复命令。 +- `codegraph unlock .` 移除崩溃的进程留下的锁,不会动仍在运行的进程的锁。 +- [CLI 参考](../../cli.md#daemon-watch--environment-variables)列出了调整后台进程的全部环境变量,[故障排查](../../troubleshooting.md)说明如何记录诊断日志。 diff --git a/docs/site/guide/quick-start.md b/docs/site/guide/quick-start.md new file mode 100644 index 0000000..cf6cf7a --- /dev/null +++ b/docs/site/guide/quick-start.md @@ -0,0 +1,205 @@ +# 快速开始 + +本页为一个小项目建立索引,演示 CodeGraph 擅长回答的问题,并给出你应当看到的输出。 + +开始前请先安装 CodeGraph(见[安装](install.md))。下面的命令都在项目目录中运行:`init` 和 `status` 用位置参数 `.` 指定项目,查询命令用 `-p .` 指定。在你自己的仓库中用法相同。 + +## 示例项目 + +示例使用一个由四个文件组成的 TypeScript 小商店。如需跟着操作,请在一个空目录中创建这些文件: + +::: details 四个文件 + +`src/cart.ts` + +```typescript +export interface Item { + name: string; + price: number; + quantity: number; +} + +export class Cart { + private items: Item[] = []; + + add(item: Item): void { + this.items.push(item); + } + + subtotal(): number { + return this.items.reduce((sum, item) => sum + item.price * item.quantity, 0); + } +} +``` + +`src/pricing.ts` + +```typescript +const DISCOUNTS: Record = { SPRING: 0.1, MEMBER: 0.05 }; + +export function applyDiscount(amount: number, code?: string): number { + const rate = code ? (DISCOUNTS[code] ?? 0) : 0; + return roundCents(amount * (1 - rate)); +} + +export function tax(amount: number): number { + return roundCents(amount * 0.08); +} + +function roundCents(value: number): number { + return Math.round(value * 100) / 100; +} +``` + +`src/checkout.ts` + +```typescript +import { Cart } from "./cart"; +import { applyDiscount, tax } from "./pricing"; + +export function checkout(cart: Cart, code?: string): number { + const discounted = applyDiscount(cart.subtotal(), code); + return discounted + tax(discounted); +} +``` + +`src/main.ts` + +```typescript +import { Cart } from "./cart"; +import { checkout } from "./checkout"; + +const cart = new Cart(); +cart.add({ name: "notebook", price: 4.5, quantity: 2 }); +cart.add({ name: "pen", price: 1.2, quantity: 3 }); +console.log(checkout(cart, "SPRING")); +``` + +::: + +## 1. 建立索引 + +```sh +cd shop +codegraph init . +``` + +```text +Scanning files… +Initialized in /tmp/shop +Indexed 4 files +22 nodes, 39 edges in 94ms +``` + +`init` 在项目中创建 `.codegraph/`,并索引它能识别的所有文件。`.gitignore` 忽略的文件,以及 `node_modules`、`target` 等依赖和构建目录,不会被索引。请把 `.codegraph/` 加入 `.gitignore`:它是本地缓存,随时可以从源码重建。 + +## 2. 检查索引 + +```sh +codegraph status . +``` + +```text +CodeGraph Status + +Project: /tmp/shop + +Index Statistics: + Files: 4 + Nodes: 22 + Edges: 39 + DB Size: 0.16 MB + Backend: rusqlite - bundled SQLite + Journal: wal + + DB Path: /tmp/shop/.codegraph/codegraph.db + Daemon: stopped + +Nodes by Kind: + class 1 + constant 2 + file 4 + function 4 + import 4 + interface 1 + method 2 + property 4 + +Files by Language: + typescript 4 + +Index is up to date +``` + +`status --json` 以脚本可读的形式给出同样的信息,包括索引是否最新,以及建立索引后有哪些文件发生了变化。 + +## 3. 查看一个符号 + +```sh +codegraph node applyDiscount -p . +``` + +````text +## applyDiscount (function) + +**Location:** src/pricing.ts:3 +**Signature:** `(amount: number, code?: string): number` + +```typescript +3 export function applyDiscount(amount: number, code?: string): number { +4 const rate = code ? (DISCOUNTS[code] ?? 0) : 0; +5 return roundCents(amount * (1 - rate)); +6 } +``` +### Trail — codegraph_node any of these to follow it (no Read needed) +**Calls →** roundCents (src/pricing.ts:12) +**Called by ←** checkout (src/checkout.ts:4), checkout.ts (src/checkout.ts:1) +```` + +`node` 打印符号的源码,以及它调用了什么、被什么调用,方便继续沿着调用链查看。传入文件路径时,它会打印带行号的文件内容和依赖该文件的其他文件。输出是 Markdown 格式,因为同样的文本也会提供给编码 Agent。 + +## 4. 了解一块代码 + +```sh +codegraph explore "how does checkout compute the total" -p . +``` + +````text +## Exploration: how does checkout compute the total + +Found 10 symbols across 4 files. + +### Blast radius — what depends on these (update/verify before editing) + +- `checkout` (src/checkout.ts:4) — 1 caller in `src/main.ts`; no tests found within 3 caller hops + +### Source Code + +> The code below is the **verbatim, current on-disk source** of these files — re-read from disk on this call and line-numbered, byte-for-byte identical to what the Read tool returns. It is NOT a summary, outline, or stale cache. Treat each block as a Read you have already performed: do not Read a file shown here. + +#### src/cart.ts — Cart(class), subtotal(method) + +```typescript +1 export interface Item { +… +``` +```` + +输出接着列出四个文件的源码。`explore` 接受一个问题或几个名称,找出涉及的符号,按文件返回它们的源码、依赖它们的代码,以及它们之间的调用。它是 `codegraph_explore` 在命令行中的对应命令,而 `codegraph_explore` 是编码 Agent 调用最多的工具。 + +## 5. 跟踪调用和改动 + +| 命令 | 列出 | +| -------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| `codegraph search applyDiscount -p .` | 名称匹配的符号,最匹配的排在最前,附带位置和签名 | +| `codegraph callers applyDiscount -p .` | 调用或导入它的代码:这里是 `checkout` 和文件 `checkout.ts` | +| `codegraph callees checkout -p .` | 它调用的代码:`applyDiscount`、`subtotal`、`tax`,以及它用到的类型 `Cart` | +| `codegraph impact applyDiscount -p .` | 改动它会影响的全部代码,沿调用方的调用方逐层展开,按文件分组:这里是 `checkout`、`checkout.ts` 和 `main.ts` | + +这些命令都支持 `--json`,供脚本使用。 + +## 下一步 + +- [接入编码 Agent](agents.md),让它自己提出这些问题。 +- [打开浏览器查看器](viewer.md),以可视化方式阅读同一份索引。 +- [保持索引最新](keeping-current.md),在编辑代码时跟上变化。 diff --git a/docs/site/guide/viewer.md b/docs/site/guide/viewer.md new file mode 100644 index 0000000..7f5ca12 --- /dev/null +++ b/docs/site/guide/viewer.md @@ -0,0 +1,85 @@ +# 浏览器查看器 + +本页说明如何打开 CodeGraph 的浏览器查看器,以及每个视图的用途。 + +查看器读取项目已有的索引,在你本机的浏览器中展示:一个符号的调用方、源码和被调用方并排显示,一个文件的大纲,一个函数到另一个函数的调用路径,按模块划分的仓库结构图,类型的继承层级,以及没有任何代码到达的符号。它目前是**预览**功能:默认关闭,需要手动开启,各视图今后仍可能调整。查看器界面只有英文。 + +## 打开查看器 + +```sh +CODEGRAPH_UI=1 codegraph ui # 当前所在的已建立索引的项目 +CODEGRAPH_UI=1 codegraph ui ~/code/my-app # 另一个已建立索引的项目 +CODEGRAPH_UI=1 codegraph ui --no-open # 只打印地址,不打开浏览器 +CODEGRAPH_UI=1 codegraph ui --read-only # 同时拒绝保存 Trail +``` + +未设置 `CODEGRAPH_UI=1` 时,这个命令会被拒绝,也不会出现在 `--help` 中。查看器监听 `127.0.0.1`,使用 4747 端口或其后第一个空闲端口(`--port` 可以指定),按 `Ctrl+C` 停止。 + +它从不建立或修改索引:请先用 `codegraph init` 为项目建立索引。它唯一会写入的内容是你主动保存的 **Trail**(在代码中的一段浏览路径),保存在 `.codegraph/ui/trails/` 下。 + +在任何页面按 `Ctrl+K`(macOS 上是 `⌘K`)都可以搜索符号或文件,也可以直接询问路径,例如 `how does checkout reach tax`。 + +## Start(首页) + + + +查看器打开时显示首页,内容全部来自已有的索引。项目名称和索引状态下方有三个入口:**Open the map**(打开结构图)、**Search**(搜索)和 **Read a flow**(阅读调用路径)。下方的卡片依次列出: + +- 图中包含的内容,按节点类型和边类型统计; +- 你保存的 Trail; +- 被最多代码依赖的生产代码符号; +- 代码从哪里开始运行:在顶层执行代码的文件;索引中有路由时,列出路由; +- 能到达最多其他文件的测试文件; +- 按语言统计的已索引文件。 + +点击任何名称都会打开对应的符号或文件;**All entry points**(全部入口)按文件分组列出所有入口。 + +## Symbol(符号) + + + +中间一栏是符号的源码,它发出的每个调用都在页边标出,并连到右侧一栏,右侧列出它调用的内容。左侧一栏按文件分组列出调用方,下方的 **Blast radius**(影响范围)统计改动会波及的范围:直接调用方、三层以内的调用方,以及其中的生产代码文件和测试文件。点击任何名称都会打开对应的符号,顶部的 Trail 栏记录你走过的路径。 + +## Type hierarchy(类型层级) + + + +对于类、接口或 trait,Symbol 视图会增加它的层级:上方是它继承和实现的类型,下方是继承或实现它的类型。经由这类类型分发到多个实现的调用会被标出,因为它没有唯一的静态目标。 + +## File(文件) + + + +文件大纲按源码顺序列出其中的符号,以及每个符号被引用和引用外部的数量。两侧分别是导入它的文件和它导入的文件;索引之外的名称(例如标准库路径)会列出,但没有链接。**Whole-file source**(整个文件)按行显示文件内容及其中的调用。 + +## Flow(调用路径) + + + +Flow 回答「A 是怎样调用到 B 的」:每张卡片是一步,在发出下一次调用的那一行打开,下方的表格列出每一步的调用位置和匹配置信度。这张截图展示的是 CodeGraph 自身的 `codegraph explore` 命令调用到同时为 MCP 工具服务的引擎。如果两者之间没有调用链,视图会如实说明,并列出常见原因,例如回调或反射调用。 + +## Map(结构图) + + + +结构图把文件归入模块,并按依赖关系排列:每个模块位于它所依赖的模块之上一层,因此基础模块在最下方,入口在最上方。连线的粗细表示两个模块之间的调用、导入和类型引用的数量。可以在右侧选择目录和分组深度;**Copy image** 和 **Download SVG** 按当前显示导出结构图。 + +## Dead code(未被到达的代码) + + + +Dead code 列出索引中没有任何代码到达的符号,按大小排列。右侧面板说明清单排除了哪些符号以及原因,例如导出的符号、测试文件中的符号、组件文件中可能被模板引用的符号等。剩下的符号没有静态引用,但这并不能证明它们没有被使用:宏、trait 对象和反射仍可能到达它们。 + +## Start、Entry points、Screens 和 Steps + +Start 页面概括整个索引:索引包含的内容、被依赖最多的符号、执行的起点,以及覆盖范围最广的测试。**Entry points** 完整列出这些起点,已保存的 Trail 排在最前。 + +**Screens** 和 **Steps** 需要当前版本尚未记录的信息:Screens 会显示没有找到页面跳转,Steps 会说明无法绘制步骤。[查看器参考](../../ui.md#differences-from-upstream)列出了尚未支持的内容。 + +## 主题 + +查看器跟随系统的浅色或深色设置,也可以用左侧栏底部的主题控件手动选择。窗口宽度小于 600 px 时,底部标签栏取代左侧栏,Symbol 视图一次只显示一个窗格。 + +## 安全边界 + +查看器只监听 `127.0.0.1`。`Host` 或 `Origin` 不属于它自己的请求,以及缺少专用请求头的写入请求,都会被拒绝。它只打开索引中记录的、位于项目内的文件。[查看器参考](../../ui.md#boundary)列出了全部检查。 diff --git a/docs/site/guide/what-is-codegraph.md b/docs/site/guide/what-is-codegraph.md new file mode 100644 index 0000000..fd31e59 --- /dev/null +++ b/docs/site/guide/what-is-codegraph.md @@ -0,0 +1,48 @@ +# CodeGraph 是什么 + +本页说明 CodeGraph 能回答哪些问题、答案从何而来,以及它的边界在哪里。 + +CodeGraph 用 tree-sitter 解析一次仓库,把所有符号以及符号之间的调用、导入和引用记录到本机的 SQLite 索引中,再基于这份索引回答结构性问题: + +- 这个函数在哪里定义,内容是什么? +- 谁调用了它,它又调用了什么? +- 改动它会影响哪些符号和文件,包括调用方的调用方? +- 一个函数是怎样一步步调用到另一个函数的? +- 哪些测试能覆盖到这段代码? + +文本搜索只认字符串,分不清真正的调用和注释里出现的同名文字,分不清某个方法和另一个类型上的同名方法,也分不清直接调用方和三层之外的调用方。CodeGraph 依据解析出的结构作答。 + +## 工作方式 + +1. **解析**:按语言用对应的语法解析每个文件,把函数、类、方法、导入、调用点和引用变成节点和边。 +2. **匹配引用**:跨文件把引用匹配到定义,先看导入,再按名称匹配。每条边都记录匹配方式和置信度,匹配不到任何定义的引用保持未解析。 +3. **存储**:节点、边和全文检索索引写入项目 `.codegraph/` 目录下的 SQLite 数据库。SQLite 已内置在可执行文件中。 +4. **查询**:所有命令和工具都读取这份索引,回答问题时不会重新扫描仓库。 +5. **保持最新**:后台进程监听项目文件,重新索引发生变化的文件,详见[保持索引最新](keeping-current.md)。 + +## 一份索引,三个入口 + +| 入口 | 适用对象 | 从这里开始 | +| ------------ | ------------------- | ------------------------------------------------------------------- | +| 命令行 | 你本人、脚本和 CI | `codegraph explore`、`codegraph search`、`codegraph impact` | +| MCP 服务 | 编码 Agent 和编辑器 | `codegraph serve --mcp`,由 `codegraph install` 写入各 Agent 的配置 | +| 浏览器查看器 | 阅读不熟悉的代码 | `CODEGRAPH_UI=1 codegraph ui`(预览) | + +命令行和 MCP 工具运行的是同一个引擎。`codegraph explore` 打印的内容与 `codegraph_explore` 工具返回给 Agent 的内容完全一致,你可以直接核对 Agent 看到了什么。 + +## 每次都是同一个答案 + +CodeGraph 不包含任何模型:没有 embedding,没有向量检索,也没有语言模型。解析和引用匹配都是确定的,同样的文件和配置得到同样的索引,同样的问题在任何机器上都返回同样的答案。增量的 `codegraph sync` 与完整重建的结果一致,项目的测试逐字节检查这一点。 + +## 它不做什么 + +- **不做相似度检索**:它回答代码中真实存在的结构,不能按「意思相近」查找代码。 +- **不评判代码**:它给出关系和影响范围,代码是否正确仍由编译器、lint 工具和测试判断。 +- **看不到运行时行为**:反射、运行时注册的回调和由字符串拼出的调用没有静态的边,经过它们的路径不会出现。经由接口或 trait 分发到多个实现的调用会如实标出,不会被归到其中某一个实现上。 +- **语言范围是固定的**:CodeGraph 不能解析的语言,其文件不会进入图中。各档能提取的内容见[语言参考](../../languages.md)。 + +## 下一步 + +- [安装](install.md) +- [快速开始](quick-start.md) +- [接入编码 Agent](agents.md) diff --git a/docs/site/index.md b/docs/site/index.md new file mode 100644 index 0000000..13c1fd5 --- /dev/null +++ b/docs/site/index.md @@ -0,0 +1,275 @@ +--- +layout: home +title: "CodeGraph:供 Agent 和开发者使用的本地代码知识图谱" +titleTemplate: false +description: CodeGraph 用 tree-sitter 把代码仓库解析成本机的符号与调用索引,回答谁调用了某个函数、改动会影响哪里、一个函数如何调用到另一个函数,可在命令行、MCP 和浏览器查看器中使用,不依赖任何模型。 + +hero: + name: CodeGraph + text: 谁调用了它,改动它会影响哪里 + tagline: CodeGraph 用 tree-sitter 把代码仓库解析成本机的符号、调用和导入索引,并据此回答结构性问题:在命令行中,为编码 Agent 通过 MCP,也在浏览器查看器中。它不包含任何模型,同一个仓库在任何机器上都得到同样的答案。 + actions: + - theme: brand + text: 安装 + link: /guide/install + - theme: alt + text: 快速开始 + link: /guide/quick-start + - theme: alt + text: GitHub + link: https://github.com/sunerpy/codegraph-rust + +home: + facts: + - term: 运行平台 + text: Linux、macOS 和 Windows,x86_64 与 ARM64。单个可执行文件,内置 SQLite。 + - term: 你的代码 + text: 索引保存在项目的 .codegraph 目录中,建立索引和查询都不联网。 + + visual: + desktop: + light: /screens/viewer-symbol-light.webp + dark: /screens/viewer-symbol-dark.webp + width: 1440 + height: 900 + alt: CodeGraph 查看器显示方法 IndexPaths::resolve:左侧是它的调用方,中间是源码,右侧是它调用的函数。查看器界面为英文。 + + index: + title: CodeGraph 能做什么 + intro: 浏览器查看器目前是预览功能,需要手动开启;其余功能都属于常规命令。 + groups: + - name: 查询 + items: + - title: 了解一块代码 + body: 提一个问题或给出几个名称,按文件返回相关符号的源码、依赖它们的代码,以及它们之间的调用。 + status: available + link: /guide/quick-start + - title: 查看符号或文件 + body: 符号的源码及其调用和被调用关系,或带行号的文件内容以及依赖它的文件。 + status: available + link: /guide/quick-start + - title: 调用方、被调用方和影响范围 + body: 向上或向下一层,或沿调用方的调用方找出改动会影响的全部代码。 + status: available + link: /guide/quick-start + - title: 受影响的测试 + body: 根据改动的文件,列出依赖它们的文件以及其中的测试。 + status: available + link: /guide/keeping-current + - name: 接入 + items: + - title: 面向编码 Agent 的 MCP + body: 通过标准输入输出提供只读工具,一条命令即可写入每个已安装 Agent 的配置。 + status: available + link: /guide/agents + - title: 通过 HTTP 提供 MCP + body: 在本机通过 streamable HTTP 提供同样的工具,适用于编辑器和远程开发。 + status: available + link: /guide/agents + - title: Agent Skill + body: 告诉 Agent 在什么情况下使用哪个工具的说明,安装到各 Agent 的 Skill 目录。 + status: available + link: /guide/agents + - name: 保持最新 + items: + - title: 监听并更新 + body: 每个项目一个后台进程,由所有使用者共享,重新索引你修改过的文件。 + status: available + link: /guide/keeping-current + - title: 增量同步 + body: 只重新读取发生变化的文件,结果与完整重建一致。 + status: available + link: /guide/keeping-current + - name: 查看 + items: + - title: 浏览器查看器 + body: 符号、文件、调用路径、模块结构图、类型层级和未被到达的代码,支持浅色和深色主题。 + status: preview + link: /guide/viewer + - name: 语言 + items: + - title: 完整的符号提取 + body: TypeScript、JavaScript、Python、Go、Rust、Java、C、C++、C#、PHP、Ruby、Swift、Kotlin 等。 + status: available + link: /en/reference/languages + - title: 模板和组件 + body: Vue、Svelte、Astro、Razor 和 Liquid 文件,以及 MyBatis mapper XML。 + status: available + link: /en/reference/languages + - title: Godot 项目 + body: 场景、资源、脚本、自动加载和信号处理函数,并提供资源审计。 + status: available + link: /en/reference/godot + + steps: + title: 从安装到第一个答案 + items: + - title: 安装 + command: curl -fsSL https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.sh | sh + body: Windows 上使用 PowerShell 脚本,也可以从发布页下载压缩包。 + - title: 为项目建立索引 + command: codegraph init . + body: 在项目的 .codegraph 目录中建立索引,之后的更新只读取发生变化的文件。 + - title: 提一个问题 + command: codegraph explore "how does checkout compute the total" -p . + body: 返回相关的源码、依赖它的代码,以及其中的调用关系。 + - title: 接入你的 Agent + command: codegraph install --yes + body: 把 MCP 服务写入它找到的每个 Agent 的配置。 + + tools: + columns: [问题, 命令行, MCP 工具] + rows: + - question: 这块代码是怎么工作的? + cli: codegraph explore + mcp: codegraph_explore + - question: 查看这个符号或文件 + cli: codegraph node + mcp: codegraph_node + - question: 它在哪里定义? + cli: codegraph search + mcp: codegraph_search + - question: 谁调用了它? + cli: codegraph callers + mcp: codegraph_callers + - question: 改动它会影响哪里? + cli: codegraph impact + mcp: codegraph_impact + caption: 两侧运行的是同一个引擎,Agent 和你得到的答案相同。所有工具都是只读的。 + + shots: + flow: + light: /screens/viewer-flow-light.webp + dark: /screens/viewer-flow-dark.webp + width: 1440 + height: 900 + alt: 查看器的 Flow 视图,从 cmd_explore 到 explore_file_header,每次调用一张卡片,下方的表格列出每一步及其置信度。查看器界面为英文。 + + languages: + columns: [深度, 提取内容, 语言] + rows: + - depth: 完整符号 + extracted: 函数、类、方法、导入、调用和引用 + members: TypeScript、TSX、JavaScript、JSX、ArkTS、Python、Go、Rust、Java、C、C++、C#、PHP、Ruby、Swift、Kotlin、Dart、Scala、Lua、Luau、Objective-C、R、Solidity、Nix、Terraform、Erlang、GDScript、Pascal、CFML + - depth: 嵌入内容 + extracted: 宿主文件中嵌入的脚本和模板标记 + members: Vue、Svelte、Astro、Razor、Liquid、MyBatis XML + - depth: 文件级 + extracted: 文件以及文件之间的引用 + members: YAML、Twig、Properties,以及 Godot 的场景、资源和项目文件 + caption: 表中没有的语言,其文件不会进入图中。可以在 .codegraph/codegraph.json 中把其他扩展名映射到这些语言。 + + platforms: + title: 平台 + intro: 每个版本为每个平台提供一个压缩包,并附带 SHA256SUMS 文件和每个压缩包的构建来源证明。 + columns: [平台, Target, 压缩包] + rows: + - name: Linux x86_64 + status: available + cells: [x86_64-unknown-linux-musl, .tar.gz] + - name: Linux ARM64 + status: available + cells: [aarch64-unknown-linux-musl, .tar.gz] + - name: macOS Intel + status: available + cells: [x86_64-apple-darwin, .tar.gz] + - name: macOS Apple Silicon + status: available + cells: [aarch64-apple-darwin, .tar.gz] + - name: Windows x86_64 + status: available + cells: [x86_64-pc-windows-msvc, .zip] + - name: Windows ARM64 + status: available + cells: [aarch64-pc-windows-msvc, .zip] + note: Linux 版本是静态链接的,不依赖任何系统库。从源码构建需要 Rust 工具链和 C 编译器。 + + privacy: + title: 哪些内容留在你的电脑上 + intro: CodeGraph 不依赖任何托管服务。 + sendsLabel: 联网内容 + modes: + - name: 建立索引和查询 + sends: 不联网 + detail: 索引是项目中的一个 SQLite 数据库,解析、引用匹配和所有查询都在本机进行。 + - name: Agent、编辑器和查看器 + sends: 不联网 + detail: MCP 服务只与启动它的程序通信,HTTP 服务和查看器只在本机监听。 + - name: 安装和更新 + sends: 从 GitHub 下载 + detail: 安装脚本和 codegraph self-update 从 GitHub Releases 下载发布版本。 + + scope: + title: 它不做什么 + items: + - 不运行任何模型,没有 embedding,也没有向量检索;只根据解析出的结构作答。 + - 不评判代码。代码是否正确仍由编译器、lint 工具和测试判断。 + - 看不到运行时行为。反射、运行时回调和由字符串拼出的调用不会形成边。 + - 不会猜测它无法解析的语言。 +--- + + + + + + + +## 面向编码 Agent + +接入 CodeGraph 的 Agent 只需提出一个结构性问题,不必逐个搜索和读取文件,得到的回答直接包含相关源码以及它们之间的调用关系。答案来自解析出的代码,每次运行都相同。 + +`codegraph install --yes` 会把 MCP 服务写入 Claude Code、Cursor、Codex CLI、Kiro、Zed、VS Code 以及其他受支持 Agent 的配置。 + +[接入编码 Agent](guide/agents.md) · [MCP 参考](../mcp.md) + + + + + +## 在浏览器中查看 + +查看器读取同一份索引:一个符号的调用方和被调用方、一个函数到另一个函数的调用路径、按模块划分的仓库结构图、类型的继承层级,以及没有任何代码到达的代码。它在你的电脑上运行,只读取,不修改。 + +[浏览器查看器](guide/viewer.md) + + + + + +## 支持多种语言,并如实说明深度 + +大多数语言提供完整的符号提取;组件和模板提取其中嵌入的脚本和标记;少数格式只记录到文件级。表格分别列出,不用一个笼统的数字概括。 + +[支持的语言](../languages.md) · [Godot](../godot.md) + + + + + + + +## 安装 + +::: code-group + +```sh [Linux 和 macOS] +curl -fsSL https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.sh | sh +``` + +```powershell [Windows] +irm https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.ps1 | iex +``` + +```sh [从源码] +cargo install --locked --git https://github.com/sunerpy/codegraph-rust codegraph-rs +``` + +::: + +安装脚本在安装前会用该版本的 `SHA256SUMS` 校验每个压缩包。[安装指南](guide/install.md)介绍了如何安装指定版本、更新和卸载。 + + + +## 反馈 + +问题报告和功能建议请提交到 [GitHub Issues](https://github.com/sunerpy/codegraph-rust/issues)。CodeGraph 以 MIT 许可发布。 diff --git a/docs/site/privacy.md b/docs/site/privacy.md new file mode 100644 index 0000000..8fd0e12 --- /dev/null +++ b/docs/site/privacy.md @@ -0,0 +1,47 @@ +# 数据与网络 + +本页列出 CodeGraph 读取、写入和连接的全部内容,方便你决定在哪里运行它。 + +## 读取什么 + +你为其建立索引的项目中的文件,范围遵循[配置](guide/configuration.md)中说明的规则:被 `.gitignore`、`config.toml` 和默认跳过列表排除的内容从不读取。 + +## 写入什么 + +| 位置 | 内容 | 写入者 | +| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- | +| `<项目>/.codegraph/` | SQLite 索引、索引设置,以及后台进程的锁、socket 和日志 | `init`、`index`、`sync` 和后台进程 | +| `<项目>/.codegraph/ui/trails/` | 你在查看器中主动保存的 Trail | 查看器,仅在你保存时 | +| `<项目>/.codegraph/diagnostics/` | 诊断日志 | `init`、`index` 和 `sync`,仅在使用 `--debug` 时 | +| 你指定的文件 | 诊断日志 | `init`、`index` 或 `sync` 的 `--debug-log <文件>` | +| 你指定的文件 | JSON 格式的整张图 | `codegraph export -o <文件>` | +| Agent 和编辑器的配置文件 | `codegraph` MCP 条目,以及位于 `` 和 `` 之间的说明 | `codegraph install` | +| 项目自己的 Agent 配置文件(`.vscode/mcp.json`、`.zed/settings.json` 等) | 固定指向该项目的 `codegraph` 条目 | `codegraph init --target=<编辑器>` | +| 各 Agent 的 Skill 目录 | CodeGraph Skill | `codegraph skill install` | +| shell 的补全目录 | 补全脚本 | `codegraph completions --install` | +| `%USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`,或 `CODEGRAPH_PS_PROFILE` 指定的文件 | 加载 PowerShell 补全脚本的一行 | `codegraph completions powershell --install` | +| 用户状态目录:`$XDG_STATE_HOME/codegraph/`,否则为 `~/.local/state/codegraph/`;Windows 上为 `%LOCALAPPDATA%\codegraph\` | 每个运行中的 MCP 服务一个小文件,供 `codegraph mcp list` 和 `codegraph http list` 查找;以及每个用 `--detach` 启动的 HTTP 服务的日志 | `serve --mcp` 和 `serve --http`。服务退出后条目会被清除,日志则保留到你删除为止 | +| 系统临时目录 | 后台进程的 socket,仅在 `.codegraph/` 所在的文件系统无法容纳 socket 时 | 后台进程 | +| `codegraph` 可执行文件 | 新版本 | `codegraph self-update` | + +在 WSL 的 Windows 驱动器上,项目目录是 `.codegraph-wsl/` 而不是 `.codegraph/`;`CODEGRAPH_DIR` 可以指定其他名称。 + +按[卸载](guide/install.md#卸载)的步骤可以移除以上全部内容。 + +## 联网行为 + +| 操作 | 连接到 | +| --------------------------------------- | ------------------------ | +| 建立索引、同步、所有查询和所有 MCP 工具 | 不联网 | +| `codegraph self-update`、安装脚本 | GitHub,用于下载发布版本 | + +## 监听连接 + +| 服务 | 监听位置 | 说明 | +| ------------------------ | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `codegraph serve --mcp` | 不监听 | 通过标准输入和标准输出与启动它的程序通信。 | +| 后台进程 | `.codegraph/` 中的本地 socket(文件系统无法容纳时改用系统临时目录) | 只有同一台机器上的进程可以连接,供该项目的 MCP 服务使用。 | +| `codegraph serve --http` | `127.0.0.1:8111` | `--http-addr` 可以改用其他地址,包括其他机器能访问到的地址。它**没有身份验证**,而且除非 `CODEGRAPH_HTTP_ALLOWED_HOSTS` 列出了允许的主机,否则接受任何 `Host` 请求头。请让它只在本机监听,或在它前面加上你自己的访问控制。 | +| `codegraph ui` | 仅 `127.0.0.1` | 拒绝来自其他网站的请求,只打开索引中记录的文件。 | + +索引及其回答都包含你的源码。任何能访问到 CodeGraph 服务的人,都能读取它所索引的代码。 diff --git a/docs/site/public/codegraph-logo.svg b/docs/site/public/codegraph-logo.svg new file mode 100644 index 0000000..323438f --- /dev/null +++ b/docs/site/public/codegraph-logo.svg @@ -0,0 +1,8 @@ + + + + + + + diff --git a/docs/site/public/screens/viewer-dead-dark.webp b/docs/site/public/screens/viewer-dead-dark.webp new file mode 100644 index 0000000..9bac850 Binary files /dev/null and b/docs/site/public/screens/viewer-dead-dark.webp differ diff --git a/docs/site/public/screens/viewer-dead-light.webp b/docs/site/public/screens/viewer-dead-light.webp new file mode 100644 index 0000000..099a500 Binary files /dev/null and b/docs/site/public/screens/viewer-dead-light.webp differ diff --git a/docs/site/public/screens/viewer-file-dark.webp b/docs/site/public/screens/viewer-file-dark.webp new file mode 100644 index 0000000..9e9c582 Binary files /dev/null and b/docs/site/public/screens/viewer-file-dark.webp differ diff --git a/docs/site/public/screens/viewer-file-light.webp b/docs/site/public/screens/viewer-file-light.webp new file mode 100644 index 0000000..273c484 Binary files /dev/null and b/docs/site/public/screens/viewer-file-light.webp differ diff --git a/docs/site/public/screens/viewer-flow-dark.webp b/docs/site/public/screens/viewer-flow-dark.webp new file mode 100644 index 0000000..262c13b Binary files /dev/null and b/docs/site/public/screens/viewer-flow-dark.webp differ diff --git a/docs/site/public/screens/viewer-flow-light.webp b/docs/site/public/screens/viewer-flow-light.webp new file mode 100644 index 0000000..7c232a3 Binary files /dev/null and b/docs/site/public/screens/viewer-flow-light.webp differ diff --git a/docs/site/public/screens/viewer-hierarchy-dark.webp b/docs/site/public/screens/viewer-hierarchy-dark.webp new file mode 100644 index 0000000..d2e377e Binary files /dev/null and b/docs/site/public/screens/viewer-hierarchy-dark.webp differ diff --git a/docs/site/public/screens/viewer-hierarchy-light.webp b/docs/site/public/screens/viewer-hierarchy-light.webp new file mode 100644 index 0000000..81f080a Binary files /dev/null and b/docs/site/public/screens/viewer-hierarchy-light.webp differ diff --git a/docs/site/public/screens/viewer-home-dark.webp b/docs/site/public/screens/viewer-home-dark.webp new file mode 100644 index 0000000..5d4e8f5 Binary files /dev/null and b/docs/site/public/screens/viewer-home-dark.webp differ diff --git a/docs/site/public/screens/viewer-home-light.webp b/docs/site/public/screens/viewer-home-light.webp new file mode 100644 index 0000000..b4fa82a Binary files /dev/null and b/docs/site/public/screens/viewer-home-light.webp differ diff --git a/docs/site/public/screens/viewer-map-dark.webp b/docs/site/public/screens/viewer-map-dark.webp new file mode 100644 index 0000000..04d3d07 Binary files /dev/null and b/docs/site/public/screens/viewer-map-dark.webp differ diff --git a/docs/site/public/screens/viewer-map-light.webp b/docs/site/public/screens/viewer-map-light.webp new file mode 100644 index 0000000..2dbba98 Binary files /dev/null and b/docs/site/public/screens/viewer-map-light.webp differ diff --git a/docs/site/public/screens/viewer-symbol-dark.webp b/docs/site/public/screens/viewer-symbol-dark.webp new file mode 100644 index 0000000..6740d91 Binary files /dev/null and b/docs/site/public/screens/viewer-symbol-dark.webp differ diff --git a/docs/site/public/screens/viewer-symbol-light.webp b/docs/site/public/screens/viewer-symbol-light.webp new file mode 100644 index 0000000..c57545a Binary files /dev/null and b/docs/site/public/screens/viewer-symbol-light.webp differ diff --git a/docs/site/reference/faq.md b/docs/site/reference/faq.md new file mode 100644 index 0000000..a6c18bb --- /dev/null +++ b/docs/site/reference/faq.md @@ -0,0 +1,46 @@ +# 常见问题 + +本页回答刚开始使用 CodeGraph 时最常遇到的问题。 + +## CodeGraph 用了 AI 吗?会把我的代码发到别处吗? + +没有,也不会。CodeGraph 不包含任何模型,索引和查询完全在你的电脑上进行。只有安装脚本和 `codegraph self-update` 会联网,用于从 GitHub 下载发布版本。[数据与网络](../privacy.md)列出了 CodeGraph 读取、写入和连接的全部内容。 + +## 要把 `.codegraph/` 提交到仓库吗? + +不需要。它是本地缓存,随时可以从源码重建,内容也与所在机器有关。请把 `.codegraph/` 加入 `.gitignore`。 + +## 代码里明明有的调用,为什么查不到? + +通常是以下原因之一: + +- 调用要到运行时才能确定:回调、反射、由字符串拼出的名称; +- 名称能匹配到多个定义,而上下文无法判断是哪一个; +- 文件所用的语言 CodeGraph 不能解析,或者被 `.gitignore`、`config.toml` 排除,或者大于 `indexing.max_file_size`; +- 文件刚修改,尚未重新索引:`codegraph status` 会显示待处理的变化。 + +`codegraph node <名称>` 会显示索引中关于某个符号的全部信息,可以据此判断是哪种情况。 + +## 提示索引属于另一个文件系统位置 + +项目连同 `.codegraph/` 目录一起被移动或复制了。索引与建立它的位置绑定,CodeGraph 不会在别处使用它,以免回答的是错误的文件。请在新位置运行 `codegraph init <项目>` 替换它。 + +## 提示索引由更新的 CodeGraph 版本建立 + +这份索引由较新的版本建立,而读取它的 CodeGraph 版本较旧。CodeGraph 不会猜测它不认识的格式。请用 `codegraph self-update` 或安装脚本更新所有副本,包括 Agent 或编辑器启动的那一个;更新后,重启已经在运行的 Agent 和编辑器。 + +## Agent 每次调用都要求提供 `projectPath` + +MCP 服务没有找到可以默认使用的项目。请用 `codegraph init` 为项目建立索引,在项目目录中启动 Agent,或在 Agent 的配置中用 `-p <项目>` 固定项目。[接入编码 Agent](../guide/agents.md#服务为哪个项目作答) + +## 命令提示有锁,或者长时间没有反应 + +可能有另一个 CodeGraph 进程正在写入同一份索引,请等待它完成。如果有进程崩溃后留下了锁,`codegraph unlock <项目>` 会移除它,仍在运行的进程的锁不受影响。索引速度慢时,`codegraph index --debug-log index.jsonl` 会记录每个文件的耗时,日志的含义见[故障排查](../../troubleshooting.md)。 + +## 能在 Windows 和 WSL 中使用吗? + +可以。Windows 有 x86_64 和 ARM64 两个版本。在 WSL 中,位于 Windows 驱动器上(`/mnt/c/…`)的项目,新建的索引会放在单独的 `.codegraph-wsl/` 目录中,因为 SQLite 的锁在 Windows 与 WSL 之间无法生效;该位置已有的 `.codegraph/` 索引会继续使用。`/mnt/` 下不会监听文件。 + +## 如何报告问题? + +在 [GitHub](https://github.com/sunerpy/codegraph-rust/issues) 上提交 issue,附上版本号(`codegraph --version`)、平台、所用命令及其输出。索引相关的问题请附上[故障排查](../../troubleshooting.md)中介绍的诊断日志。日志记录的是项目内的相对路径和耗时,不包含源码文本、文件内容和环境变量。 diff --git a/docs/site/tools/capture-screens.mjs b/docs/site/tools/capture-screens.mjs new file mode 100644 index 0000000..29960be --- /dev/null +++ b/docs/site/tools/capture-screens.mjs @@ -0,0 +1,264 @@ +#!/usr/bin/env node +/* + * The website's screenshots of the browser viewer: docs/site/public/screens/-.webp. + * + * The viewer must already be serving the screenshot corpus. `capture-screens.sh` next to this + * file builds that corpus, starts the viewer and runs this script; docs/site/README.md explains + * the procedure. + * + * node docs/site/tools/capture-screens.mjs http://127.0.0.1:4791 [out-dir] + * + * Every capture is 1440 × 900 at device pixel ratio 1, saved as WebP at quality 85, once in the + * light theme and once in the dark one. Each one is a fresh document load, and the script waits + * for that document's load event, for every request to finish (the live /api/events stream + * aside), for no loading marker to remain and for 600 ms without a DOM change. It then checks the + * address and a piece of text the view must show. It stops, writing nothing further, on a + * timeout, a wrong address, a missing text, a console error, an uncaught exception, a failed or + * non-2xx request, or a symbol lookup that does not find exactly one match. + * + * Only Chrome's DevTools protocol is used, over Node's built-in WebSocket; nothing is installed. + * CODEGRAPH_CHROME names the Chrome or Chromium executable. + */ +import { spawn } from "node:child_process"; +import { existsSync, mkdirSync, writeFileSync } from "node:fs"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const here = dirname(fileURLToPath(import.meta.url)); +const [base, outArg] = process.argv.slice(2); +if (!base) { + console.error("usage: node capture-screens.mjs [out-dir]"); + process.exit(2); +} +const CHROME = process.env.CODEGRAPH_CHROME; +if (!CHROME || !existsSync(CHROME)) { + console.error("set CODEGRAPH_CHROME to a Chrome or Chromium executable"); + process.exit(2); +} +const outDir = resolve(outArg ?? join(here, "../public/screens")); +mkdirSync(outDir, { recursive: true }); +const PORT = Number(process.env.CDP_PORT || 19631); +const WIDTH = 1440; +const HEIGHT = 900; +const THEMES = ["light", "dark"]; + +/** Symbols looked up by name, kind and file, so a capture never depends on a hard-coded id. */ +const SYMBOLS = { + resolve: { + query: "IndexPaths::resolve", + qualifiedName: "IndexPaths::resolve", + kind: "method", + file: "crates/codegraph-core/src/index_paths.rs", + }, + frameworkResolver: { + query: "FrameworkResolver", + qualifiedName: "FrameworkResolver", + kind: "trait", + file: "crates/codegraph-resolve/src/framework.rs", + }, +}; + +/** name, route (after `#`), text the view must show. The list is exhaustive. */ +const CAPTURES = [ + ["viewer-home", () => "/", "Index composition"], + ["viewer-symbol", (ids) => `/s/${ids.resolve}`, "Called by"], + ["viewer-hierarchy", (ids) => `/s/${ids.frameworkResolver}`, "Type hierarchy"], + ["viewer-file", () => "/file/crates/codegraph-core/src/index_paths.rs", "Outline"], + ["viewer-flow", () => "/flow?from=cmd_explore&to=explore_file_header", "Every hop"], + ["viewer-map", () => "/map?root=crates&depth=1", "Architecture map"], + ["viewer-dead", () => "/dead", "What the list leaves out"], +]; + +async function lookup({ query, qualifiedName, kind, file }) { + const response = await fetch(`${base}/api/search?q=${encodeURIComponent(query)}&limit=50`); + if (!response.ok) throw new Error(`search for ${query} answered ${response.status}`); + const body = await response.json(); + const matches = (body.groups ?? []) + .flatMap((group) => group.items) + .filter( + (item) => item.qualifiedName === qualifiedName && item.kind === kind && item.file === file, + ); + if (matches.length !== 1) { + throw new Error( + `${kind} ${qualifiedName} in ${file}: expected one match, found ${matches.length}`, + ); + } + return matches[0].id; +} + +const pause = (ms) => new Promise((done) => setTimeout(done, ms)); + +const chrome = spawn( + CHROME, + [ + "--headless=new", + "--no-sandbox", + "--disable-dev-shm-usage", + "--hide-scrollbars", + `--remote-debugging-port=${PORT}`, + "about:blank", + ], + { stdio: ["ignore", "ignore", "pipe"] }, +); + +let failed = false; +try { + let wsUrl; + for (let i = 0; i < 100 && !wsUrl; i++) { + try { + wsUrl = (await (await fetch(`http://127.0.0.1:${PORT}/json/version`)).json()) + .webSocketDebuggerUrl; + } catch { + await pause(150); + } + } + if (!wsUrl) throw new Error("Chrome's DevTools endpoint did not come up"); + + const ws = new WebSocket(wsUrl); + await new Promise((done, fail) => { + ws.onopen = done; + ws.onerror = fail; + }); + let nextId = 0; + const pending = new Map(); + const events = []; + ws.onmessage = (message) => { + const data = JSON.parse(message.data); + if (data.id && pending.has(data.id)) { + const { ok, fail } = pending.get(data.id); + pending.delete(data.id); + if (data.error) fail(new Error(JSON.stringify(data.error))); + else ok(data.result); + } else if (data.method) { + events.push(data); + } + }; + const send = (method, params = {}, sessionId) => + new Promise((ok, fail) => { + const id = ++nextId; + pending.set(id, { ok, fail }); + ws.send(JSON.stringify({ id, method, params, sessionId })); + }); + const { targetId } = await send("Target.createTarget", { url: "about:blank" }); + const { sessionId } = await send("Target.attachToTarget", { targetId, flatten: true }); + const cmd = (method, params) => send(method, params, sessionId); + await cmd("Page.enable"); + await cmd("Runtime.enable"); + await cmd("Network.enable"); + await cmd("Emulation.setDeviceMetricsOverride", { + width: WIDTH, + height: HEIGHT, + deviceScaleFactor: 1, + mobile: false, + }); + await cmd("Emulation.setEmulatedMedia", { + features: [{ name: "prefers-reduced-motion", value: "reduce" }], + }); + await cmd("Page.addScriptToEvaluateOnNewDocument", { + source: `;(() => { window.__lastMutation = performance.now(); + new MutationObserver(() => { window.__lastMutation = performance.now(); }) + .observe(document, { subtree: true, childList: true, attributes: true, characterData: true }); })();`, + }); + + const evaluate = async (expression) => { + const result = await cmd("Runtime.evaluate", { + expression, + awaitPromise: true, + returnByValue: true, + }); + if (result.exceptionDetails) { + throw new Error( + result.exceptionDetails.exception?.description ?? result.exceptionDetails.text, + ); + } + return result.result?.value; + }; + + /** Requests of the current document: id → url; the live event stream never finishes. */ + const inFlight = new Map(); + const problems = []; + let seen = 0; + function drain() { + for (; seen < events.length; seen++) { + const { method, params } = events[seen]; + if (method === "Network.requestWillBeSent" && !params.request.url.includes("/api/events")) { + inFlight.set(params.requestId, params.request.url); + } else if (method === "Network.responseReceived" && inFlight.has(params.requestId)) { + const { status, url } = params.response; + if (status >= 400) problems.push(`HTTP ${status} for ${url}`); + } else if (method === "Network.loadingFinished") { + inFlight.delete(params.requestId); + } else if (method === "Network.loadingFailed") { + if (inFlight.has(params.requestId)) + problems.push(`request failed: ${inFlight.get(params.requestId)} (${params.errorText})`); + inFlight.delete(params.requestId); + } else if (method === "Runtime.exceptionThrown") { + problems.push( + `uncaught exception: ${params.exceptionDetails.exception?.description ?? params.exceptionDetails.text}`, + ); + } else if (method === "Runtime.consoleAPICalled" && params.type === "error") { + problems.push( + `console error: ${params.args.map((arg) => arg.value ?? arg.description).join(" ")}`, + ); + } + } + } + + async function load(route) { + await cmd("Page.navigate", { url: "about:blank" }); + drain(); + inFlight.clear(); + const mark = events.length; + await cmd("Page.navigate", { url: `${base}/#${route}` }); + const started = Date.now(); + while (!events.slice(mark).some((event) => event.method === "Page.loadEventFired")) { + if (Date.now() - started > 20000) throw new Error(`#${route}: the page did not load`); + await pause(50); + } + while (Date.now() - started < 20000) { + drain(); + const quiet = + inFlight.size === 0 && + (await evaluate(`document.readyState === 'complete' + && !document.querySelector('[aria-busy="true"], .skeleton, .loadingrow') + && !document.body.innerText.includes('Reading the ') + && performance.now() - (window.__lastMutation ?? 0) > 600`)); + if (quiet) return; + await pause(100); + } + throw new Error(`#${route}: the view did not settle within 20 s`); + } + + const ids = {}; + for (const [key, symbol] of Object.entries(SYMBOLS)) ids[key] = await lookup(symbol); + + // localStorage belongs to the viewer's origin, so the theme is set from one of its pages. + await load("/"); + for (const theme of THEMES) { + await evaluate(`localStorage.setItem('codegraph-ui.theme', '${theme}'); true`); + for (const [name, route, expected] of CAPTURES) { + const hash = route(ids); + await load(hash); + drain(); + if (problems.length > 0) throw new Error(`${name}-${theme}: ${problems.join("; ")}`); + if ((await evaluate("location.hash")) !== `#${hash}`) + throw new Error(`${name}-${theme}: the address moved away from #${hash}`); + if (!(await evaluate(`document.body.innerText.includes(${JSON.stringify(expected)})`))) { + throw new Error(`${name}-${theme}: the view does not show "${expected}"`); + } + if ((await evaluate("document.documentElement.dataset.theme")) !== theme) { + throw new Error(`${name}-${theme}: the page is not in the ${theme} theme`); + } + const shot = await cmd("Page.captureScreenshot", { format: "webp", quality: 85 }); + const file = join(outDir, `${name}-${theme}.webp`); + writeFileSync(file, Buffer.from(shot.data, "base64")); + console.log(file); + } + } +} catch (error) { + console.error(error instanceof Error ? error.message : error); + failed = true; +} finally { + chrome.kill("SIGKILL"); +} +process.exit(failed ? 1 : 0); diff --git a/docs/site/tools/capture-screens.sh b/docs/site/tools/capture-screens.sh new file mode 100755 index 0000000..0b6f373 --- /dev/null +++ b/docs/site/tools/capture-screens.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# +# Rebuild the screenshot corpus and capture the website's viewer screenshots into +# docs/site/public/screens/. docs/site/README.md describes the procedure. +# +# USAGE +# CODEGRAPH_CHROME=/path/to/chrome docs/site/tools/capture-screens.sh [codegraph-binary] [out-dir] +# +# The corpus is this repository at CODEGRAPH_SCREENS_COMMIT, extracted into codegraph-rust/ inside a +# new temporary directory with the viewer bundle excluded, indexed by the given binary and served by +# its viewer on 127.0.0.1:CODEGRAPH_SCREENS_PORT. The temporary directory, the index in it included, +# is removed on exit. Needs git, tar, curl, mktemp and Node 22 or later. + +set -euo pipefail + +here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +repo="$(cd "$here/../../.." && pwd)" +bin="${1:-codegraph}" +out="${2:-$repo/docs/site/public/screens}" +commit="${CODEGRAPH_SCREENS_COMMIT:-f7424cd3747e117aee526f774b0602291ce2b1e5}" +port="${CODEGRAPH_SCREENS_PORT:-4791}" + +# A directory this run creates, so nothing from an earlier run reaches the corpus and nothing +# that existed before is deleted. +work="$(mktemp -d "${TMPDIR:-/tmp}/codegraph-screens.XXXXXX")" +corpus="$work/codegraph-rust" +viewer="" +cleanup() { + if [ -n "$viewer" ]; then + kill "$viewer" 2>/dev/null || true + wait "$viewer" 2>/dev/null || true + fi + rm -rf -- "$work" +} +trap cleanup EXIT + +mkdir -p "$corpus/.codegraph" +git -C "$repo" archive "$commit" | tar -x -C "$corpus" +# The archive carries no local config; without this exclusion the minified viewer bundle adds +# thousands of one- and two-letter symbols (AGENTS.md). +printf '[app]\nname = "codegraph-rust"\n\n[indexing]\nexclude = ["crates/codegraph-ui/viewer/"]\n' \ + >"$corpus/.codegraph/config.toml" +CODEGRAPH_NO_DAEMON=1 "$bin" init "$corpus" + +CODEGRAPH_UI=1 "$bin" ui "$corpus" --no-open --port "$port" >"$work/viewer.log" 2>&1 & +viewer=$! +# shellcheck disable=SC2016 # $1 is expanded by the inner shell, which receives the port. +if ! timeout 30 sh -c 'until curl -sf "http://127.0.0.1:$1/api/stats" >/dev/null; do sleep 1; done' _ "$port"; then + echo "error: the viewer did not answer on port $port; its output:" >&2 + cat "$work/viewer.log" >&2 + exit 1 +fi + +node "$here/capture-screens.mjs" "http://127.0.0.1:$port" "$out"