@zhn2605/topo 0.1.0 → 0.2.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 +80 -76
- package/dist/grammars/tree-sitter-cpp.wasm +0 -0
- package/dist/topo.js +1061 -289
- package/dist/web/assets/answer-CbyA0kan.js +2 -0
- package/dist/web/assets/{elk.bundled-DHL5Qd5-.js → elk.bundled-BUXl0iSx.js} +1 -1
- package/dist/web/assets/index-51XzhJVO.css +1 -0
- package/dist/web/assets/index-IpMwIh-N.js +22 -0
- package/dist/web/index.html +2 -2
- package/dist/web/snapshot.html +43 -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,92 @@
|
|
|
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`:
|
|
24
22
|
|
|
25
23
|
```sh
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# in any git repo with TypeScript code:
|
|
30
|
-
pnpm topo diff main --repo /path/to/repo # change list in the terminal
|
|
31
|
-
pnpm topo review main --repo /path/to/repo # opens the map in your browser
|
|
32
|
-
pnpm topo graph /path/to/repo # graph summary (--json for the full graph)
|
|
33
|
-
pnpm topo map /path/to/repo # explore how a program works, no diff needed
|
|
24
|
+
npm i -g @zhn2605/topo
|
|
25
|
+
topo map .
|
|
34
26
|
```
|
|
35
27
|
|
|
36
|
-
|
|
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
|
|
48
|
+
|
|
49
|
+
```sh
|
|
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
|
|
57
|
+
```
|
|
58
|
+
|
|
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 short walkthrough: just the blocks that matter, numbered in the order they run. Without `claude`, the box falls back to plain search.
|
|
72
|
+
|
|
73
|
+
**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 a headless `claude -p` 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.
|
|
74
|
+
|
|
75
|
+
`--dangerously-skip-permissions` lets launched agents run without asking, like Claude Code's flag of the same name. The UI shows a red pill while it's on.
|
|
76
|
+
|
|
77
|
+
### Connect your own agent (MCP)
|
|
78
|
+
|
|
79
|
+
A running `topo map` or `topo review` serves the same map over MCP, so your agent can ask it instead of grepping:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
claude mcp add --transport http topo http://127.0.0.1:4477/mcp
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
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
86
|
|
|
45
87
|
## Lenses
|
|
46
88
|
|
|
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
|
|
89
|
+
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
90
|
|
|
49
91
|
```json
|
|
50
92
|
{
|
|
@@ -60,35 +102,11 @@ A lens is a saved view: which edges to follow, which way, how deep, what to hide
|
|
|
60
102
|
}
|
|
61
103
|
```
|
|
62
104
|
|
|
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.
|
|
105
|
+
`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
106
|
|
|
89
107
|
## Layers and boundary rules
|
|
90
108
|
|
|
91
|
-
`topo layers --suggest` drafts `.topo/layers.json` from your top-level
|
|
109
|
+
`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
110
|
|
|
93
111
|
```json
|
|
94
112
|
{ "version": 1,
|
|
@@ -96,15 +114,11 @@ Start the server with `--dangerously-skip-permissions` to have launched agents s
|
|
|
96
114
|
"rules": [{ "from": "client", "notTo": "server", "why": "talk through Net remotes" }] }
|
|
97
115
|
```
|
|
98
116
|
|
|
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).
|
|
117
|
+
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
118
|
|
|
105
119
|
## On pull requests (GitHub Action)
|
|
106
120
|
|
|
107
|
-
|
|
121
|
+
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
122
|
|
|
109
123
|
```yaml
|
|
110
124
|
on: pull_request
|
|
@@ -123,25 +137,15 @@ jobs:
|
|
|
123
137
|
```
|
|
124
138
|
git repo ──► indexer (TS checker / tree-sitter) ──► graph (base + head)
|
|
125
139
|
│
|
|
126
|
-
git diff ──► hunks ──► identity matching ──► graph diff ──► blast radius + risk ──►
|
|
140
|
+
git diff ──► hunks ──► identity matching ──► graph diff ──► blast radius + risk ──► map
|
|
127
141
|
```
|
|
128
142
|
|
|
129
|
-
The base version is extracted from git into a cache keyed by commit
|
|
143
|
+
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.
|
|
130
144
|
|
|
131
|
-
##
|
|
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.
|
|
134
|
-
|
|
135
|
-
## Development
|
|
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
|
-
```
|
|
145
|
+
## Changes
|
|
143
146
|
|
|
144
|
-
|
|
147
|
+
- **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+).
|
|
148
|
+
- **0.1.0:** first preview.
|
|
145
149
|
|
|
146
150
|
## License
|
|
147
151
|
|
|
Binary file
|