@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 CHANGED
@@ -1,50 +1,92 @@
1
1
  # Topo
2
2
 
3
- **AI speed, human reasoning.** Topo maps your codebase as a graph of blocks (files, classes, functions, methods). Use it to understand an area before you change it, and to review an AI agent's change on the same map: what changed, what depends on it, and what's risky, instead of scrolling a flat diff.
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
- It works with any agent and any editor: it only reads git. Clicking a block opens it in your own editor at the right line.
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
- > Status: early. TypeScript/JavaScript, Luau (Roblox), Python and Rust.
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
- ## What you get
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
- Requires Node 26+ and pnpm.
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
- pnpm install
27
- pnpm --filter @topo/web build
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
- `--head <ref>` compares against a branch or commit instead of the working tree. `--repo` may point at a subfolder of a git repo (one game in a monorepo, say). `--lens <name>` opens with a lens. Set the editor with `--editor "nvim +{line} {file}"` or `TOPO_EDITOR` (default `code -g {file}:{line}`).
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. One project per `tsconfig.json`, so monorepo path aliases resolve.
41
- - **Luau / Lua (Roblox):** tree-sitter finds functions and call sites. Requires are resolved by [`luau-lsp`](https://github.com/JohnnyMorganz/luau-lsp) with your Rojo project (`@game/...` aliases included) when it's installed (e.g. via rokit), else relative requires only. `*.server.luau` / `*.client.luau` scripts are the entry points.
42
- - **Python:** tree-sitter finds functions, classes and methods; calls resolve through scope, `self.`, and `import` / `from … import` (src layouts and monorepo packages found from `__init__.py`). Untyped `obj.method()` calls are left out rather than guessed.
43
- - **Rust:** tree-sitter plus the module tree: `mod`, `use` trees (re-exports and globs), `crate::`/`super::`, `Type::f`, `Self::`/`self.` in impls, `impl Trait for Type`. In a Tauri app, the frontend's `invoke("name")` links to the `#[tauri::command] fn name`.
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` at the repo root. A lens with a built-in's name replaces it:
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`. Node ids are `path#Qualified.name` (use search, then *Properties*, to find one). Because it's a plain file, you can ask your coding agent to write a lens for the task at hand.
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 source folders (one level into `packages/`, `apps/` and so on). Rename and merge them, then add rules by hand:
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
- Reviews then flag every *new* call or import that crosses a rule: a risk reason on the block, a "Boundary crossings" section in the PR comment, and `topo diff <base> --fail-on-violations` exits 1 for CI. Existing crossings aren't flagged, so an old codebase doesn't light up on day one.
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
- `topo diff <base> --markdown` prints a PR comment: the riskiest changed blocks with their reasons, shared hubs touched, and signature changes. `topo export <base>` writes the review map as one HTML file that opens from disk. The action at this repo's root runs both on each PR, keeps one comment up to date, and links the map from it (as a run artifact):
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 ──► review UI
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 SHA, so your working tree is never touched. Everything runs locally; the server binds to 127.0.0.1.
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
- ## 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.
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
- Layout: `packages/engine` (indexer, diff, identity, graph diff, core views, analysis, eval), `packages/cli` (the `topo` command and local server), `apps/web` (React UI).
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