@zhn2605/topo 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -76
- package/dist/grammars/tree-sitter-cpp.wasm +0 -0
- package/dist/topo.js +1739 -415
- package/dist/web/assets/answer-3GChwEmV.js +2 -0
- package/dist/web/assets/{elk.bundled-DHL5Qd5-.js → elk.bundled-Bx4dyQBB.js} +1 -1
- package/dist/web/assets/index-CX9S_hg9.js +23 -0
- package/dist/web/assets/index-D-MaOEzL.css +1 -0
- package/dist/web/index.html +2 -2
- package/dist/web/snapshot.html +44 -37
- package/package.json +2 -2
- package/dist/web/assets/index-Bx25CC1b.js +0 -17
- package/dist/web/assets/index-CJ5z47qU.css +0 -1
package/README.md
CHANGED
|
@@ -1,50 +1,112 @@
|
|
|
1
1
|
# Topo
|
|
2
2
|
|
|
3
|
-
**AI speed, human reasoning.** Topo
|
|
3
|
+
**AI speed, human reasoning.** Topo draws your codebase as a map of blocks (files, classes, functions, methods) and the calls between them. Use it for two things:
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- **Before a change:** see how an area works (what runs first, what it calls, who depends on it) without reading every file.
|
|
6
|
+
- **After an agent's change:** review it on the same map. What changed, what depends on it, and what's risky, ranked, instead of scrolling a flat diff.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
It works with any agent and any editor. It only reads git, and clicking a block opens it in your own editor at the right line.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- **Change map:** changed blocks (added, modified, deleted, signature changed) as the roots of the view, with dependents shaded by distance (blast radius).
|
|
12
|
-
- **Structural diff:** renames detected as renames, signature changes shown old → new, and new or removed call edges ("`checkout` now calls `db.query`").
|
|
13
|
-
- **Risk-ordered queue:** each changed block gets a score with plain reasons ("7 dependents (4 direct)", "public signature changed", "1 uncertain edge").
|
|
14
|
-
- **Honest edges:** calls resolved by the TypeScript type checker are solid; dynamic dispatch and inferred edges are dashed.
|
|
15
|
-
- **Flow view:** entry point on the left, callees to the right in the order the code calls them, loops marked ↻. Each block shows its first 8 callees, with the rest behind "+N more".
|
|
16
|
-
- **Trimmed by default:** files nearly everything imports (config, shared types, a network wrapper) are hidden and listed as "also uses: Config, Net" instead. Tests are hidden too.
|
|
17
|
-
- **Lenses:** switch between *How it runs*, *Who uses this*, *Dependencies*, *Change impact* and *Unfiltered*, or define your own (below).
|
|
18
|
-
- **Your layout sticks:** drag blocks where you want them; positions are saved per view in `.topo/layout.json`.
|
|
19
|
-
- **Depth navigation:** search (`/`), depth, callers/callees, per-branch expand/collapse, re-rooting with breadcrumbs and back/forward.
|
|
10
|
+
> Early, and moving fast. Languages: TypeScript/JavaScript, Luau (Roblox), Python, Rust, C/C++.
|
|
20
11
|
|
|
21
12
|
## Quick start
|
|
22
13
|
|
|
23
|
-
|
|
14
|
+
Needs Node 24+ and git.
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npx @zhn2605/topo map . # explore the repo you're in
|
|
18
|
+
npx @zhn2605/topo review main # review your changes against main
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or install it once and use `topo`:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
npm i -g @zhn2605/topo
|
|
25
|
+
topo map .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Both open the map in your browser. Everything runs locally; the server only listens on 127.0.0.1.
|
|
29
|
+
|
|
30
|
+
## Using the map
|
|
31
|
+
|
|
32
|
+
- **Press ⌘K or `/`** for the one box that does everything: type a name to jump to a block, a word to find an action (switch the view, show layers, reset the layout), or a question to ask Topo ("how does checkout work?").
|
|
33
|
+
- **Right-click a block** for what you can do with it: open in your editor, make it the root, show what it calls or who calls it, ask about it.
|
|
34
|
+
- **Switch views** with the button in the map's corner: *How it runs* (entry point to callees, in call order), *Who uses this*, *Dependencies*, *Change impact*, *Unfiltered*.
|
|
35
|
+
- **The left panel** lists entry points (or, when reviewing, the changes ordered by risk), territories and agent activity. Fold it away or drag its edge to resize.
|
|
36
|
+
- **Agent requests** come in under the bell at the top right. Requests stay until you approve or deny them; news fades after a few seconds.
|
|
37
|
+
- **Drag blocks** where you want them. Your layout is saved per view in `.topo/layout.json`.
|
|
38
|
+
|
|
39
|
+
## What it shows
|
|
40
|
+
|
|
41
|
+
- **Changes as the starting point:** added, modified, deleted and signature-changed blocks, with everything that depends on them shaded by distance.
|
|
42
|
+
- **A structural diff:** renames shown as renames, signatures old → new, and new or removed calls ("`checkout` now calls `db.query`").
|
|
43
|
+
- **Risk with reasons:** each change gets a score you can read: "7 dependents (4 direct)", "public signature changed", "1 uncertain edge".
|
|
44
|
+
- **Honest edges:** calls the type checker resolved are solid lines; inferred or dynamic ones are dashed.
|
|
45
|
+
- **Less noise by default:** files nearly everything imports (config, shared types, a network wrapper) and tests are hidden, listed as "also uses: Config, Net" instead.
|
|
46
|
+
|
|
47
|
+
## Commands
|
|
24
48
|
|
|
25
49
|
```sh
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
pnpm topo map /path/to/repo # explore how a program works, no diff needed
|
|
50
|
+
topo map [path] # explore a codebase (no git needed)
|
|
51
|
+
topo review <base> # review the working tree (or --head <ref>) against a branch or commit
|
|
52
|
+
topo diff <base> # the change list in the terminal (--markdown for a PR comment)
|
|
53
|
+
topo graph [path] # graph summary (--json for the full graph)
|
|
54
|
+
topo export <base> # the review map as one HTML file that opens from disk
|
|
55
|
+
topo layers --suggest # draft .topo/layers.json from your folders
|
|
56
|
+
topo hook # print a Claude Code hook so your agent's edits show up live
|
|
34
57
|
```
|
|
35
58
|
|
|
36
|
-
`--
|
|
59
|
+
`--repo` points at another repo, or a subfolder of one (one game in a monorepo, say). `--lens <name>` opens with a view. Set your editor with `--editor "nvim +{line} {file}"` or `TOPO_EDITOR` (default `code -g {file}:{line}`). Run `topo <command> --help` for the rest.
|
|
37
60
|
|
|
38
61
|
## Languages
|
|
39
62
|
|
|
40
|
-
- **TypeScript / JavaScript:** the TypeScript 7 type checker resolves calls
|
|
41
|
-
- **Luau / Lua (Roblox):** tree-sitter finds functions and
|
|
42
|
-
- **Python:**
|
|
43
|
-
- **Rust:**
|
|
63
|
+
- **TypeScript / JavaScript:** the TypeScript 7 type checker resolves calls, one project per `tsconfig.json`, so monorepo path aliases work.
|
|
64
|
+
- **Luau / Lua (Roblox):** tree-sitter finds functions and calls. Requires resolve through [`luau-lsp`](https://github.com/JohnnyMorganz/luau-lsp) and your Rojo project (`@game/...` aliases included) when it's installed, for example with rokit; otherwise relative requires only. `*.server.luau` and `*.client.luau` scripts are the entry points.
|
|
65
|
+
- **Python:** functions, classes and methods; calls resolve through scope, `self.` and imports (src layouts and monorepo packages included). Untyped `obj.method()` calls are left out rather than guessed.
|
|
66
|
+
- **Rust:** the module tree (`mod`, `use` with re-exports and globs, `crate::`, `super::`), `Type::f`, `self.` in impls, and `impl Trait for Type`. In a Tauri app, the frontend's `invoke("name")` links to its `#[tauri::command]`.
|
|
67
|
+
- **C / C++:** functions, classes and methods (a header declaration and its `Type::m` definition are one block). Calls resolve through `this`, `Ns::f`, constructors, and `obj.m()` when `obj`'s type is known; free functions through the `#include` closure. Virtual dispatch, function pointers and macros are left out. Build, vendor and generated files are skipped.
|
|
68
|
+
|
|
69
|
+
## Ask Topo and agents
|
|
70
|
+
|
|
71
|
+
If the `claude` CLI is on your PATH, questions in the ⌘K box go to Topo's own Claude Code process. It can only use Topo's map tools, so it answers questions, changes the view and makes territories, but never edits code. Ask "how does X work" and it shows a walkthrough: the blocks that matter, numbered in the order they run, as a guided tour. Its length follows the question: a handful of steps for the gist, every step when you ask for all of it. The map glides to each block in turn, a marker travels the call that leads there, and a card under the block says what happens in it (← / → or Play to move on, Esc to leave; "Tour this walkthrough" in ⌘K starts it again). The card switches the map between *Just these blocks* and *With neighbours*, the same blocks with what they call and what calls them. Without `claude`, the box falls back to plain search.
|
|
72
|
+
|
|
73
|
+
The Ask Topo panel opens on a short welcome until you close it: *Walk me through these changes* (or *how this runs* on a map), *How does … work?* and *Plan a change to …*. Asked on the review map, "walk me through this" tours the changes on that map, with a few sentences per block on what it does and what changed. A plan comes back as steps on the map and territories with their tasks written out; no agent starts until you say go.
|
|
74
|
+
|
|
75
|
+
When a request could go more than one way ("split this repo up for a few agents": how many, split by what?), Topo asks first, the way Claude Code does: a question or two with choices as buttons under its reply, plus a box for your own answer. Pick and it carries on.
|
|
76
|
+
|
|
77
|
+
When reviewing, **Tour the changes** (the button on the *To review* tab, or ⌘K) plays the same tour on the review map itself, over the changes it shows, callers before what they call; *Tour all N* on the card takes in every change. Each card shows what changed: the risk and its reasons, the signature old → new, calls gained and lost, the agent's reason if it gave one, and Viewed / Ask for changes. Esc brings you back to the review. Asking Topo "walk me through the change" does the same with a sentence per step.
|
|
78
|
+
|
|
79
|
+
**Viewed** marks a changed block as seen, so a long review keeps your place: *To review* dims it and counts how many you've viewed, and the mark clears itself if the block changes again (after an agent's next pass you re-read only what's new). Marks are yours alone, saved in `.topo/reviews.json`, which Topo gitignores. **Ask for changes** sends a note on that block straight to the agent that made it; on a block no agent made, it reads *Hand to an agent* and starts a worker with your note as the task.
|
|
80
|
+
|
|
81
|
+
**Territories** are regions of the map you hand an agent: a label, the task, and the blocks it covers (saved in `.topo/territories.json`). *Launch* starts an agent CLI headless on that task with Topo's tools, and its edits show up on the map as it makes them. Edits outside its territory aren't blocked, just flagged. Agents working in git worktrees (Claude Code subagents, Codex, `git worktree add`) show up too.
|
|
82
|
+
|
|
83
|
+
**Which agents.** Launch works with any of these that are on your PATH; each territory picks one under *Runs with*:
|
|
84
|
+
|
|
85
|
+
| Agent | Asks you mid-run | Continue a run | Edits on the map from |
|
|
86
|
+
|---|---|---|---|
|
|
87
|
+
| Claude Code (`claude`) | yes, as cards under the bell | yes | its PostToolUse hook |
|
|
88
|
+
| Gemini CLI (`gemini`) | no: runs in its own sandbox (`auto_edit`; *Never ask* = `yolo`) | no | its JSON stream |
|
|
89
|
+
| Codex (`codex`) | no: runs in its own sandbox (`workspace-write`; *Never ask* = bypass) | yes | its JSON stream |
|
|
90
|
+
|
|
91
|
+
Ask Topo (the ⌘K box's agent) needs Claude Code; without it the box is plain search. Model overrides: `TOPO_WORKER_MODEL` (Claude, default `sonnet`), `TOPO_GEMINI_MODEL`, `TOPO_CODEX_MODEL`.
|
|
92
|
+
|
|
93
|
+
**Keys are yours.** Topo never asks for, stores or sees an API key. Each CLI signs in the way it normally does: `claude` with your Claude login or `ANTHROPIC_API_KEY`, `gemini` with `GEMINI_API_KEY` or a Google login, `codex` with `codex login`. Set that up once in the CLI and Topo's launches use it.
|
|
94
|
+
|
|
95
|
+
**Permissions.** The top of the Territories tab (or ⌘K, *Agent permissions*) sets what launched agents may do without asking: *Allow safe commands* (the default: reading, searching, editing, and read-only commands like `ls`, `cat`, `grep` and `git log`), *Ask for every command*, or *Never ask*. For Claude Code, anything else comes to you as a card under the bell. *Always allow* on a card saves the same rule Claude Code's own "don't ask again" saves, in the repo's `.claude/settings.local.json`, so it holds when you run `claude` yourself too. Gemini and Codex can't ask mid-run, so the setting picks their sandbox mode instead. The choice is saved in `.topo/settings.json` and applies to the next launch. Starting Topo with `--dangerously-skip-permissions` means *Never ask* for that session; the UI shows a red pill whenever nothing asks.
|
|
96
|
+
|
|
97
|
+
### Connect your own agent (MCP)
|
|
98
|
+
|
|
99
|
+
A running `topo map` or `topo review` serves the same map over MCP, so your agent can ask it instead of grepping:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
claude mcp add --transport http topo http://127.0.0.1:4477/mcp
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Tools include `find`, `callers`, `callees`, `blast_radius`, `get_block`, `view`, `get_layers`, `get_territory`, `request_territory` and `report_change`. The HTTP and live-events API is documented in [docs/api.md](https://github.com/zhn2605/topo/blob/mvp/docs/api.md).
|
|
44
106
|
|
|
45
107
|
## Lenses
|
|
46
108
|
|
|
47
|
-
A lens is a saved view: which edges to follow, which way, how deep, what to hide. Add your own in `.topo/lenses.json
|
|
109
|
+
A lens is a saved view: which edges to follow, which way, how deep, what to hide. Add your own in `.topo/lenses.json`; one with a built-in's name replaces it.
|
|
48
110
|
|
|
49
111
|
```json
|
|
50
112
|
{
|
|
@@ -60,35 +122,11 @@ A lens is a saved view: which edges to follow, which way, how deep, what to hide
|
|
|
60
122
|
}
|
|
61
123
|
```
|
|
62
124
|
|
|
63
|
-
`view` takes `hopKinds` (`calls`, `references`, `imports`, `inherits`, `implements`), `direction` (`out`, `in`, `both`), `globalDepth`, `hiddenTags`, `excludePaths` (globs) and `containerRoots`/`foldNested`.
|
|
64
|
-
|
|
65
|
-
## Agents (MCP)
|
|
66
|
-
|
|
67
|
-
`topo review` and `topo map` also serve the live graph over MCP, so a coding agent can ask the map instead of grepping:
|
|
68
|
-
|
|
69
|
-
```sh
|
|
70
|
-
claude mcp add --transport http topo http://127.0.0.1:4477/mcp
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
Tools: `find` (search blocks by name), `callers`/`callees` (who calls or is called, to a depth), `blast_radius` (everything that depends on a block), `get_block` (kind, file:lines, signature, doc, source), `view` (apply a lens and get a text outline), `shape_view` (propose a lens for the human to see, optionally saving it to `.topo/lenses.json`), `list_territories`/`get_territory`, `request_territory` (ask for one), `report_change` (explain an edit, one sentence).
|
|
74
|
-
|
|
75
|
-
Territories are regions of the map you hand an agent — a label, a note (the task), and the blocks it covers — stored in `.topo/territories.json` and editable from the UI. An agent can read its territory with `get_territory`; edits outside it aren't blocked, just flagged in the map as out-of-territory.
|
|
76
|
-
|
|
77
|
-
## Command bar, agents, and the inbox
|
|
78
|
-
|
|
79
|
-
The command bar (the UI's search box, also `POST /api/command {text, context?}`) is a semantic helper: it's its own headless Claude Code process, restricted to Topo's own MCP tools (`--tools ""`, `--strict-mcp-config`), so it can change the view, focus blocks, make or update territories, launch or stop agents, and decide inbox items — but it never edits code. Without a `claude` CLI on PATH, it falls back to a plain block search.
|
|
80
|
-
|
|
81
|
-
Launching an agent on a territory (the UI's "Launch" button, also `POST /api/territories/<id>/launch`) starts a real headless `claude -p` in your repo, scoped to that territory's task. It gets Topo's MCP tools over `--mcp-config`, and Topo writes it the same PostToolUse hook `topo hook` prints (via `--settings`) so its edits are attributed in the map without you pasting anything — it works the same way in any repo. `GET /api/runs` lists runs; `POST /api/runs/<id>/stop` stops one.
|
|
82
|
-
|
|
83
|
-
The inbox (`GET /api/inbox`, `POST /api/inbox/<id> {decision: "approve"|"deny"|"dismiss"}`) is everything waiting on you: an agent asking for a territory or a permission, a proposed view, or an FYI (it finished, it stepped outside its territory, two agents touched the same block). The UI surfaces it as a queue; deciding an item unblocks the agent that's waiting on it.
|
|
84
|
-
|
|
85
|
-
Agents working in git worktrees (Claude Code subagents in `.claude/worktrees/`, Codex, `git worktree add`) show up too: their hook's file path is mapped onto the served checkout, the edited blocks are found by diffing the worktree's copy, and the agent's label carries the worktree's name.
|
|
86
|
-
|
|
87
|
-
Start the server with `--dangerously-skip-permissions` to have launched agents skip every permission prompt (like Claude Code's flag of the same name); the UI shows a red pill while it's on.
|
|
125
|
+
`view` takes `hopKinds` (`calls`, `references`, `imports`, `inherits`, `implements`), `direction` (`out`, `in`, `both`), `globalDepth`, `hiddenTags`, `excludePaths` (globs) and `containerRoots`/`foldNested`. Block ids look like `path#Qualified.name`; find one with ⌘K, then *Properties* in the Inspector. It's a plain file, so you can ask your agent to write a lens for the task at hand.
|
|
88
126
|
|
|
89
127
|
## Layers and boundary rules
|
|
90
128
|
|
|
91
|
-
`topo layers --suggest` drafts `.topo/layers.json` from your top-level
|
|
129
|
+
`topo layers --suggest` drafts `.topo/layers.json` from your top-level folders, or ask Topo to "sort this code into layers". Rename and merge them, then add rules:
|
|
92
130
|
|
|
93
131
|
```json
|
|
94
132
|
{ "version": 1,
|
|
@@ -96,15 +134,11 @@ Start the server with `--dangerously-skip-permissions` to have launched agents s
|
|
|
96
134
|
"rules": [{ "from": "client", "notTo": "server", "why": "talk through Net remotes" }] }
|
|
97
135
|
```
|
|
98
136
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
## Using Topo from other tools
|
|
102
|
-
|
|
103
|
-
Topo is a layer other tools call, not a platform that competes with them. A running `topo map` serves a versioned HTTP + live-events + MCP API (`GET /api/meta` → `api: 1`); see [docs/api.md](docs/api.md).
|
|
137
|
+
With layers, blocks are colored by layer, *Group by layer* draws each layer as a region, and *Overview* shows the whole program as one box per layer with the calls between them. Reviews flag every *new* call that breaks a rule (existing ones aren't, so an old codebase doesn't light up on day one), and `topo diff <base> --fail-on-violations` exits 1 for CI.
|
|
104
138
|
|
|
105
139
|
## On pull requests (GitHub Action)
|
|
106
140
|
|
|
107
|
-
|
|
141
|
+
The action posts one PR comment, kept up to date, with the riskiest changes and their reasons, shared code touched, signature changes and boundary crossings, and links the full map as a run artifact:
|
|
108
142
|
|
|
109
143
|
```yaml
|
|
110
144
|
on: pull_request
|
|
@@ -123,25 +157,16 @@ jobs:
|
|
|
123
157
|
```
|
|
124
158
|
git repo ──► indexer (TS checker / tree-sitter) ──► graph (base + head)
|
|
125
159
|
│
|
|
126
|
-
git diff ──► hunks ──► identity matching ──► graph diff ──► blast radius + risk ──►
|
|
160
|
+
git diff ──► hunks ──► identity matching ──► graph diff ──► blast radius + risk ──► map
|
|
127
161
|
```
|
|
128
162
|
|
|
129
|
-
The base version is extracted from git into a cache keyed by commit
|
|
130
|
-
|
|
131
|
-
## Accuracy
|
|
132
|
-
|
|
133
|
-
Graph accuracy is measured, not assumed. `node packages/engine/src/eval/run.ts` indexes a hand-labeled fixture repo and reports precision and recall per edge kind; CI fails if call-edge accuracy regresses.
|
|
163
|
+
The base version is extracted from git into a cache keyed by commit, so your working tree is never touched. Graph accuracy is measured against a hand-labeled fixture repo, and CI fails if call-edge accuracy drops.
|
|
134
164
|
|
|
135
|
-
##
|
|
136
|
-
|
|
137
|
-
```sh
|
|
138
|
-
pnpm test # vitest
|
|
139
|
-
pnpm typecheck
|
|
140
|
-
pnpm lint # biome
|
|
141
|
-
pnpm --filter @topo/web dev # UI dev server; open /?mock for sample data
|
|
142
|
-
```
|
|
165
|
+
## Changes
|
|
143
166
|
|
|
144
|
-
|
|
167
|
+
- **0.3.0:** Ask Topo hands code changes to a worker agent itself; Launch runs Gemini CLI and Codex as well as Claude Code; agent permissions (safe commands by default, *Always allow* on a request card); a badge on every block an agent is editing; guided tours of walkthroughs, and *Tour the changes* in a review; repeat "outside its territory" warnings fold into one card; *Viewed* and *Ask for changes* replace Approve and Request changes (saved across restarts, cleared when a block changes again, notes go straight to the agent).
|
|
168
|
+
- **0.2.0:** a new interface: one ⌘K box for search, actions and questions; right-click menus on blocks; views as one list; a single side panel you can fold or resize; agent requests under a bell with Approve/Deny on each card; quieter colors. Runs on Node 24+ (was 26+).
|
|
169
|
+
- **0.1.0:** first preview.
|
|
145
170
|
|
|
146
171
|
## License
|
|
147
172
|
|
|
Binary file
|