python generate.py --root /path/to/repo # writes workspaces/<slug>/data.json and sets current
python server.py # http://127.0.0.1:8765 — reuses workspaces/current.json
npm run dev # http://localhost:5173Open the UI at http://localhost:5173/. Repo root comes from the active workspace after generate — you do not pass --root to server.py each time.
To use another project later: Settings → Workspace → Scanned repo → paste the path → Open (or python generate.py --root /path/to/other). Each repo keeps its own graph, notes, and chats under workspaces/<slug>/. Check Reindex only when you want a fresh data.json.
If the UI shows empty / proxy errors, you likely have duplicate servers. Clean both API (:8765) and Vite (:5173):
npm run stop # kill both
python server.py # replaces any leftover API listener by default
npm run devOr one-shot: npm run serve:clean / npm run dev:clean.
| Action | Result |
|---|---|
| Click node | Select / inspect |
| Double-click folder | Focus that subtree |
| Drag node / background | Reposition / pan |
| Scroll | Zoom |
| Pack / Stretch / Depth | Layout density |
| Up / Root | Leave focus |
Hide nodes from the inspector; unhide from the toolbar.
- Insights / Impact / Relations — CRG blast radius, callers, imports (needs Build).
- Overview / Trace — symbols and call paths from the CRG index.
- Notes — path-scoped notes (saved via API).
- AI — Send includes scanned repo name/path + git HEAD, CRG blurb, and semantic/FTS hits for the question. Retrieve does not call the model: it pins graph focus, selected file/folder, open workspace files (bodies), plus CRG symbol search (box text, or selected file name). Then Send. Needs Build (then Embed) for symbol hits.
- Workspace — open/edit files from the left rail or inspector.
- Command Palette (
Ctrl/Cmd+Kor the magnifying glass) — tabs:- Paths — filesystem names from
data.json(instant). - Symbols — CRG symbol FTS (needs Build).
- Semantic — meaning search via Settings backend (CRG Embed and/or FTS → often hybrid; or claude-context). Not Paths.
- Commands — app actions.
- All — mix of the above.
- Paths — filesystem names from
- Results for Symbols and Semantic are cached while the palette stays open, so switching tabs for the same query does not re-fetch.
- Hybrid — CRG combined full-text + vector embeddings (after Embed). Shown in the palette footer as the search mode.
- Serena — optional refine of hit line ranges after Semantic/Retrieve; does not discover or list results by itself. Start
node scripts/serena_sidecar.mjsand enable refine in Settings. - Semantic queries can take a few seconds on large repos; the palette shows a spinner while waiting.
- Settings → Indexing: filesystem graph (
generate.py/ data.json) is separate from CRG. If INDEX shows failed to parse status on Windows, restartpython server.py(bridge uses.venv/python -m code_review_graph, not the broken.exetrampoline), then Build. 0 nodes after a clean status still means you have not built yet.
- Path and selection note bodies are Markdown (GFM). Use Preview in the Notes tab; Overview renders Markdown too.
- Delete removes the current note (history keeps a copy). History × removes only that revision. ⧉ duplicates a revision and saves it as the current note.
- Document files… (Settings → AI → Document files, or Command Palette) runs an in-app LLM job over the filesystem tree and writes path notes with
meta.source = "llm-document",meta.kind = "documentation", andmeta.locked = true. Choose Full workspace or a Directory (relative path, e.g.src/components), and an action:- Document · missing only — files without notes
- Document · all unlocked — overwrite notes that are not locked
- Update · existing notes — second pass: feeds the current note + current source file back to the model (skips locked)
Locked notes are always skipped by Document/Update. Unlock in the Notes panel to edit or re-run. Progress appears in the notification bell. Optional quality gate (Guardian-compatible) loads rubrics from
GRANITE_GUIDELINES_DIRordocument.guidelines_dir(external folder — not shipped in this repo). Local scaffold:C:\Users\Amit\Models\granite-doc-stack\. If the generator looks like a reasoning model (Qwen3 / Qwen3.8, o-series, GPT-OSS, DeepSeek-R1), Settings → AI → Document files → Run job → Reasoning is sent (reasoning_efforton llama.cpp;thinkon Ollama). This is independent of chat reasoning (Settings → AI under Model). Off / Low / Medium / High. Quality gate never gets this field.<think>markup is stripped from written notes.
- Auto-documented notes show a Documentation · Locked badge in the Notes panel (read-only until Unlock).
- Focus a folder in the graph (e.g.
src/components) or type that path under Settings → AI → Document files → Directory…. - Action: Document · missing only → Document files…. Watch the notification bell.
- Open a documented file → Notes: badge Documentation · Locked, body preview-only.
- Unlock → edit if needed → Lock again (or leave unlocked).
- Change the source file, then run Update · existing notes on the same directory — unlocked notes revise; locked ones are skipped.
- Smoke (mocked LLM):
python scripts/smoke_notes_agents.py(phase 1 covers selected-folder document + lock meta).
- Settings → GitHub → Sync PRs & issues (or Inspector → GitHub → Sync) uses the
ghCLI to import notes keyedgh:pr:N/gh:issue:Nwith full comment threads and file patches. - Detail view: Markdown summary, scrollable thread, read-only Monaco diff for each file.
- Branch ops (confirm-gated): Switch (optional stash if dirty), Stash, Fetch, Rebase onto upstream. Never force-pushes.
- Graph cache: Switch saves/restores
data.json(+ CRG when present) under that repo’sworkspaces/<slug>/graphs/<branch>/<sha>/. Miss → runsgenerate.py. Cache graph saves the current HEAD without switching. - Inspector Code → History dropdown:
git log --followthengit show commit:pathin a read-only buffer (does not swap the graph).
- Cursor sessions (Settings → Knowledge → Import Cursor, or AI panel Import Cursor):
- Primary: Cursor’s internal chat DB (
%APPDATA%/Cursor/User/globalStorage/state.vscdbon Windows) — same bubble store as cursor-history. This includes thinking (thinking.text) and per-step tool calls (toolFormerData), ordered like the live chat. - Fallback:
~/.cursor/projects/<slug>/agent-transcripts/*.jsonl(redacted export; usually no thinking).<slug>is the scanned graph root encoded the Cursor way (e.g.C:\Users\…\Documents\servo→c-Users-…-Documents-servo). - Imports sessions for that project into repo-root threads (
path: ""). Cross-repo Cursor threads already in SQLite are left alone (not deleted). Re-import upgrades older JSONL threads to bubble threads when the same composer UUID is found.
- Primary: Cursor’s internal chat DB (
- LangSmith (pull-import + optional push-tracing):
- Settings → Knowledge → paste API key + project name (must match a LangSmith tracing project / session name exactly, e.g. from the LangSmith Projects list). Or set
LANGSMITH_API_KEY/LANGSMITH_PROJECT. - Save config, then Validate — should report
LangSmith OK, the resolved project, and an optional sample run name. - Import LangSmith pulls recent runs into root threads with
source: langsmithand atrace.
- Settings → Knowledge → paste API key + project name (must match a LangSmith tracing project / session name exactly, e.g. from the LangSmith Projects list). Or set
- Trace in-app chat to LangSmith (optional): enable the toggle, Save, then AI → Send. The reply stores
trace.runs[].idon the thread; expand Trace under the assistant message. Open History to confirm a SQLite revision was saved with the thread.
- Root Cursor imports appear in every AI tab (Inspector file AI and Assistant Ask), marked cursor + shared when you are on a file.
- Sidebar filters: All / Local / Cursor / LangSmith.
- Messages render as readable text (not raw JSON). Reasoning and Tool mini-cards stay in chronological order inside each assistant turn (thinking → tools → reply, as Cursor stored them). An eye icon shows leftover metadata.
- Timestamps from Cursor bubbles /
<timestamp>tags appear on messages and thread rows; titles prefer the composer name or first user query (not the UUID filename). - File-local threads stay path-scoped. New / Send always write to the current path (or the shared thread’s home path if you reply inside a shared Cursor thread).
- Re-import refreshes Cursor threads by
externalId(cursor:composer:<uuid>or legacycursor:<abspath>) and skips LangSmith dupes (langsmith:<runId>).
Chat storage is not remounted per git branch (that repo’s workspaces/<slug>/notes.db). Transcripts still come from Cursor’s agent-transcripts. New/saved notes and local chats are stamped with git: { branch, commit } for badges and filters (current branch + unscoped vs all). Path notes whose file is missing from the current graph appear under Orphan notes. Switching scanned repos loads that repo’s notes/chats.
- Thread list shows a source badge (
cursor/langsmith/local). Expand Trace when present. - LangSmith key is used for import and optional in-app tracing — it does not push Cursor IDE chats to smith.langchain.com.
- Settings → Knowledge → Snapshots: Capture copies
data.json(+ optional.code-review-graph) under that repo’sworkspaces/<slug>/snapshots/{id}/. Compare reports added/removed/changed file paths and CRG count delta. Restore is not implemented (compare-only).
The bell next to Settings collects toasts, CRG Build / Update / Embed progress, and bulk Document files job progress.
Settings → AI → Chat provider: OpenAI or Ollama (frontier + local model presets). Keys stay in the browser; requests go through the local Python server. Optional LangSmith tracing is under Settings → Knowledge (see Chat import & traces). Chat Reasoning (Off / Low / Medium / High) is on the composer and under Settings → AI (same localStorage). Document files uses a separate Reasoning row under Run job. Sent as reasoning_effort (llama.cpp / OpenAI o-series) or think (Ollama). Off omits the field. Thinking, when the server returns it, shows as a collapsible Reasoning card.