mellos-mapping 0.20.3 → 0.22.1

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.
Files changed (67) hide show
  1. package/README.md +123 -69
  2. package/README.zh-CN.md +120 -65
  3. package/dist/hook-session-start.mjs +25 -19
  4. package/dist/mmap.mjs +302 -170
  5. package/dist/preview.mjs +1418 -0
  6. package/dist/server.mjs +1197 -399
  7. package/dist/store-paths.mjs +40 -21
  8. package/dist/terminal-worker.mjs +3188 -0
  9. package/dist/watch.mjs +522 -279
  10. package/dist/web/TERMINAL-LICENSES.txt +70 -0
  11. package/dist/web/app.css +967 -0
  12. package/dist/web/app.js +1356 -0
  13. package/dist/web/index.html +9 -0
  14. package/dist/web/terminal.css +9 -0
  15. package/dist/web/terminal.html +7 -0
  16. package/dist/web/terminal.js +9293 -0
  17. package/dist/web/xterm.css +285 -0
  18. package/dist/web.mjs +5535 -0
  19. package/docs/codex.md +183 -0
  20. package/lib/domain/text.d.ts +9 -0
  21. package/lib/domain/text.js +43 -0
  22. package/lib/preview/index.d.ts +3 -0
  23. package/lib/preview/index.js +3 -0
  24. package/lib/preview/markdown.d.ts +8 -0
  25. package/lib/preview/markdown.js +54 -0
  26. package/lib/preview/presentation.d.ts +6 -0
  27. package/lib/preview/presentation.js +14 -0
  28. package/lib/preview/publisher.d.ts +23 -0
  29. package/lib/preview/publisher.js +143 -0
  30. package/lib/preview/svg.d.ts +3 -0
  31. package/lib/preview/svg.js +74 -0
  32. package/lib/preview/text.d.ts +4 -0
  33. package/lib/preview/text.js +13 -0
  34. package/lib/render/canvas.d.ts +1 -1
  35. package/lib/render/canvas.js +4 -2
  36. package/lib/render/draw.js +9 -6
  37. package/lib/render/render.d.ts +6 -0
  38. package/lib/render/render.js +50 -18
  39. package/lib/render/width.js +3 -1
  40. package/lib/store/atomic.d.ts +18 -0
  41. package/lib/store/atomic.js +86 -0
  42. package/lib/store/channels.d.ts +40 -0
  43. package/lib/store/channels.js +135 -0
  44. package/lib/store/format.js +3 -1
  45. package/lib/store/json-text.d.ts +9 -0
  46. package/lib/store/json-text.js +16 -0
  47. package/lib/store/maps.d.ts +12 -0
  48. package/lib/store/maps.js +42 -0
  49. package/lib/store/migration.d.ts +12 -0
  50. package/lib/store/migration.js +46 -0
  51. package/lib/store/pages.d.ts +46 -0
  52. package/lib/store/pages.js +89 -0
  53. package/lib/store/policy.d.ts +74 -0
  54. package/lib/store/policy.js +144 -0
  55. package/lib/store/store.d.ts +9 -256
  56. package/lib/store/store.js +10 -694
  57. package/lib/store/viewers.d.ts +81 -0
  58. package/lib/store/viewers.js +186 -0
  59. package/package.json +25 -5
  60. package/scripts/codex-cli.mjs +42 -0
  61. package/scripts/codex-register.mjs +27 -94
  62. package/scripts/mmap.mjs +26 -16
  63. package/scripts/open-pane.mjs +37 -18
  64. package/scripts/pane-core.mjs +57 -220
  65. package/scripts/terminal-session.mjs +137 -0
  66. package/scripts/tmux-session.mjs +90 -0
  67. package/scripts/watcher-command.mjs +16 -0
package/README.md CHANGED
@@ -1,16 +1,20 @@
1
1
  # Mellos Mapping
2
2
 
3
- [![CI](https://github.com/GuangminJu/mellos-mapping/actions/workflows/ci.yml/badge.svg)](https://github.com/GuangminJu/mellos-mapping/actions/workflows/ci.yml)
3
+ [![npm](https://img.shields.io/npm/v/mellos-mapping?logo=npm&logoColor=white&label=npm&color=cb3837)](https://www.npmjs.com/package/mellos-mapping)
4
+ [![downloads](https://img.shields.io/npm/dm/mellos-mapping?label=downloads&color=cb3837)](https://www.npmjs.com/package/mellos-mapping)
5
+ [![MCP registry](https://img.shields.io/badge/MCP_registry-listed-2f6feb)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.GuangminJu/mellos-mapping)
6
+ [![CI](https://img.shields.io/github/actions/workflow/status/GuangminJu/mellos-mapping/ci.yml?branch=main&label=CI)](https://github.com/GuangminJu/mellos-mapping/actions/workflows/ci.yml)
7
+ [![license](https://img.shields.io/badge/license-MIT-444)](LICENSE)
4
8
 
5
9
  English | [简体中文](README.zh-CN.md)
6
10
 
7
11
  A live, terminal-native map of bottom-up development for
8
- [Claude Code](https://claude.com/claude-code) and Codex CLI.
12
+ [Claude Code](https://claude.com/claude-code), ChatGPT desktop Codex mode and Codex CLI.
9
13
 
10
14
  <p align="center">
11
15
  <picture>
12
16
  <source media="(prefers-color-scheme: light)" srcset="docs/demo-light.svg">
13
- <img alt="A Mellos map building itself: ghost design first, spinners climbing the layers, a cracked foundation spreading upward, honest recovery" src="docs/demo.svg" width="620">
17
+ <img alt="One declare puts the whole ghost design on screen, then the nodes light up from the bottom a foundation cracks, the damage spreads upward, and green is earned back" src="docs/demo.svg" width="620">
14
18
  </picture>
15
19
  </p>
16
20
 
@@ -20,42 +24,12 @@ dependency edges that may only point downward, ghost nodes for what is
20
24
  designed, a spinner on what is being built right now, and solid green for
21
25
  what is built *and verified*.
22
26
 
23
- ```
24
- Mellos Mapping · the plugin itself
25
-
26
- ━━━━━━━━━━━━━━━━━━━━━━━━━━ orchestration
27
-
28
- ╭╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮
29
- ╎ · MCP Server ╎
30
- ╰╌╌╌╌┬╌┬╌╌┬╌╌╌╌╯
31
- │ │ │
32
- └─┼──┼─────────────┐
33
- │ └──────┐ │
34
- │ │ │
35
- ━━━━━━━━━┿━━━━━━━━━┿━━━━━━┿━━━ contracts
36
- │ │ │
37
- ┏━━━━━━┷━━━━━━━━┓│ ╭╌╌╌╌┴╌╌╌╌╌╌╮
38
- ┃ ■ State Store ┃│ ╎ · Watcher ╎
39
- ┗━━━━━┯━━━━━━━━━┛│ ╰╌╌╌╌╌┬╌╌╌╌╌╯
40
- │ │ │
41
- │ ┌────────┘ │
42
- │ │ │
43
- ━━━━━━━━┿━┿━━━━━━━━━━━━━━━━┿━ primitives
44
- │ │ │
45
- ┏━━━━━┷━┷━━━━━━┓ ╭──────┴───────────╮
46
- ┃ ■ Map Domain ┃ │ ⠋ ASCII Renderer │
47
- ┗━━━━━━━━━━━━━━┛ ╰──────────────────╯
48
-
49
- · planned ⠋ in-progress ■ done ✗ regressed
50
- ```
51
-
52
- In a real terminal the wiring and band bars render FAINT while node boxes
53
- glow in their status colors with bold labels — a dark circuit board where
54
- the components are the bright things. Skip-level edges thread through gaps
55
- between boxes (watch the line dive between State Store and Watcher above);
56
- non-overlapping wire segments share track rows to keep the bands close.
27
+ <p align="center">
28
+ <img alt="A Claude Code session with the Mellos map pane beside it: a six-layer game engine design, L0 and L1 nodes solid green, the upper layers still dashed ghost nodes" src="docs/session-claude-code.png">
29
+ </p>
57
30
 
58
- *(This is the plugin's own map, mid-development. The spinner really spins.)*
31
+ *A real session: Claude Code on the left, the map pane on the right. L0 is
32
+ verified, L1 just lit up, everything above is still a ghost.*
59
33
 
60
34
  ## Why
61
35
 
@@ -79,6 +53,21 @@ picture makes the discipline visible:
79
53
 
80
54
  ## Install
81
55
 
56
+ Clone the branch for your host, then run one command. No build is required.
57
+
58
+ | Branch | Audience | Command from the clone |
59
+ | --- | --- | --- |
60
+ | `main` | Shared source / either host | `node install.mjs chatgpt-app` or `node install.mjs claude` |
61
+ | `claude` | Claude Code | `node install.mjs` |
62
+ | `chatgpt-app` | ChatGPT desktop, Codex mode | `node install.mjs` |
63
+
64
+ Requires Node.js 18+ and the corresponding host CLI on PATH. The installer checks
65
+ release integrity and all six MCP tools, retains the runtime outside the clone,
66
+ and configures the host. Start a new conversation after installation.
67
+ See [release and branch instructions](docs/releasing.md).
68
+
69
+ Claude Code's marketplace installation is also available:
70
+
82
71
  Two lines inside any Claude Code conversation:
83
72
 
84
73
  ```
@@ -92,8 +81,7 @@ Or one line in a terminal:
92
81
  claude plugin marketplace add GuangminJu/mellos-mapping && claude plugin install mellos-mapping@mellos-mapping
93
82
  ```
94
83
 
95
- Requires Node.js 18+ on PATH (Claude Code itself requires Node, so you
96
- already have it). No build step: `dist/` is committed, so a clone runs as-is —
84
+ Requires Node.js 18+ on PATH (install Node separately when using native Claude Code). No build step: `dist/` is committed, so a clone runs as-is —
97
85
  `dist/server.mjs` (the MCP server), `dist/watch.mjs` (the pane),
98
86
  `dist/mmap.mjs` (the `mmap` toggle), `dist/hook-session-start.mjs` (the
99
87
  `SessionStart` hook that `hooks/hooks.json` registers) and
@@ -139,7 +127,7 @@ claude plugin marketplace update mellos-mapping && claude plugin update mellos-m
139
127
 
140
128
  Two steps because `plugin update` compares against the locally cached
141
129
  marketplace clone — the first command is what actually pulls this repo.
142
- Restart Claude Code to apply. Releases are version bumps on `master`.
130
+ Restart Claude Code to apply. Releases are version bumps on `main`.
143
131
  (In-app, `/plugin` opens the same management UI.)
144
132
 
145
133
  ### Upgrading from 0.19
@@ -166,31 +154,34 @@ That one move is the only time either process touches `.claude/`. Afterwards
166
154
  the tools write nowhere but `.mellos/`, and never outside the project
167
155
  directory they resolved at startup.
168
156
 
169
- ## Codex CLI
157
+ ## ChatGPT App · Codex mode
170
158
 
171
- The same repo doubles as a Codex plugin (codex-cli 0.147+). Three lines:
159
+ This is Codex mode in the ChatGPT desktop app (also called Codex App).
160
+ From the source branch run the following command; on `chatgpt-app`, omit the
161
+ host argument. It configures the desktop skill, marketplace and six MCP tools.
172
162
 
173
163
  ```
174
- codex plugin marketplace add GuangminJu/mellos-mapping
175
- codex plugin add mellos-mapping@mellos-mapping
176
- node ~/.codex/plugins/cache/mellos-mapping/mellos-mapping/<version>/scripts/codex-register.mjs
164
+ node install.mjs chatgpt-app
177
165
  ```
178
166
 
179
- The first two install the skill (the map discipline) as a Codex plugin. The
180
- third registers the MCP server at user level — needed because Codex spawns
181
- plugin-bundled MCP servers inside the plugin cache with no way to see your
182
- workspace, so a bundled server would write the map into the cache. A
183
- user-level `codex mcp add` entry (which the script writes) inherits each
184
- session's working directory instead: the state file lands in your project,
185
- same as under Claude Code. The registered path is version-specific — re-run
186
- the script after updating the plugin.
187
-
188
- To watch the live pane beside a Codex session on Windows, run
167
+ Start a new conversation. The desktop skill defaults to **web-terminal**:
168
+ `mmap_open {surface: "web-terminal", page: "<slug>"}` starts a local service,
169
+ then the AI opens its URL in the current conversation's right browser panel.
170
+ The mmap terminal starts automatically, with its own font-size selector;
171
+ no manual paste or Computer Use is needed. Graphical SVG, native terminal and
172
+ Markdown remain available. With an older MCP schema, run
173
+ `node "<plugin root>/dist/web.mjs" "<project>" --terminal --page <slug>`.
174
+ A queued panel request does not prove that the user can see it.
175
+ See [desktop installation and limitations](docs/codex.md).
176
+
177
+ For Codex CLI inside Windows Terminal (not the desktop integrated terminal), run
189
178
  `node <plugin root>/scripts/open-pane.mjs <project dir>` — it splits the
190
- terminal window hosting the session (or falls back to a dedicated
191
- "mellos-mapping" window; `--window` picks that on purpose). Add
179
+ terminal window hosting the session, keeping keyboard focus on the conversation.
180
+ If that window cannot be identified or focused, it reports failure without
181
+ opening elsewhere. `--window` explicitly chooses a separate window. Add
192
182
  `--page <slug>` to open on a particular page — and with a pane already open,
193
- rerunning with `--page` retargets it instead of opening another. The pane
183
+ rerunning with `--page` retargets the pane belonging to this console. A map
184
+ open in another session or a separate window does not count as this split. The pane
194
185
  auto-follows the page being written — the map the agent is operating on
195
186
  right now; press `f` to toggle that (a manual page switch also turns it
196
187
  off), or start with `--no-follow`. Elsewhere run
@@ -198,6 +189,32 @@ off), or start with `--no-follow`. Elsewhere run
198
189
  terminal (or any terminal split). Both take the same flags — see
199
190
  [Pane flags](#pane-flags).
200
191
 
192
+ ### Desktop Markdown map
193
+
194
+ When the user chooses the document surface, the skill uses
195
+ `mmap_open {surface: "markdown", page: "<slug>"}` and opens the returned file
196
+ beside the current conversation. The document embeds a colored SVG dependency
197
+ map plus module details, evidence, and child-page links. It needs no web server,
198
+ browser rendering process, Mermaid support, or additional runtime dependencies.
199
+
200
+ Successful MCP map writes regenerate enabled previews in `.mellos/previews/`;
201
+ JSON remains the source of truth. Image nodes are static. File visibility and
202
+ automatic viewer refresh belong to the desktop host. See the
203
+ [desktop map guide](docs/codex.md#desktop-right-side-map) for regeneration,
204
+ cache behavior, and limitations.
205
+
206
+ ### Optional interactive web viewer
207
+
208
+ An additional interactive web viewer is available with
209
+ `mmap_open {surface: "web", page: "<slug>"}` or
210
+ `node "<plugin root>/dist/web.mjs" "<project directory>" --page <slug>`.
211
+ Open its returned URL in the host's right browser panel. It provides live
212
+ updates, pan/zoom, hover and pinned details, search, dependency highlighting,
213
+ filters, group overview, submaps and themes. Stop it with
214
+ `node "<plugin root>/dist/web.mjs" "<project directory>" --stop`.
215
+ Markdown/SVG and terminal workflows remain available; all surfaces share the
216
+ same map data. See [web viewer details](docs/codex.md#optional-interactive-web-viewer).
217
+
201
218
  ## Any MCP client
202
219
 
203
220
  The server ships on npm, so any MCP client (Cursor, Windsurf, Zed,
@@ -222,7 +239,7 @@ servers), then the server process's own working directory. Set
222
239
  somewhere other than the project you are working in.
223
240
 
224
241
  The skill/discipline layer is Claude Code + Codex specific; other clients
225
- get the five `mmap_*` tools and the pane, and bring their own prompting.
242
+ get the six `mmap_*` tools and the pane, and bring their own prompting.
226
243
 
227
244
  ## Use
228
245
 
@@ -241,6 +258,25 @@ get the five `mmap_*` tools and the pane, and bring their own prompting.
241
258
  3. Watch nodes light up from the bottom. Interrupt when the picture worries
242
259
  you — that is what it is for.
243
260
 
261
+ On Linux and macOS, `mmap_open` and `mmap` automatically use tmux. The launcher
262
+ targets the inherited `TMUX`/`TMUX_PANE`; if the tool process lost those variables,
263
+ it discovers the single attached session on the default tmux server. The default
264
+ is a right split that preserves input focus; `--window` creates a new tmux window.
265
+ Repeated opens reuse the watcher bound to that source pane or session window.
266
+
267
+ For multiple attached sessions or a custom tmux socket, set these variables in
268
+ the environment of the MCP server (restart it after changing them):
269
+
270
+ | Variable | Meaning |
271
+ | --- | --- |
272
+ | `MELLOS_MAPPING_TMUX_TARGET` | Explicit tmux session or pane, such as `work:2.1` or `%7` |
273
+ | `MELLOS_MAPPING_TMUX_SOCKET` | Absolute socket path, for example `/tmp/my-tmux/socket` |
274
+
275
+ Ambiguous sessions, detached sessions and missing tmux produce a concrete error
276
+ and a fully quoted watcher command, including the project and requested page,
277
+ to paste into any visible terminal. Map writes remain available; after an open
278
+ failure the assistant retries only when the environment changes or you ask.
279
+
244
280
  The pane is mouse-aware (xterm SGR any-event tracking — the same protocol
245
281
  htop and tmux speak):
246
282
 
@@ -323,7 +359,7 @@ them verbatim and rejects anything it does not know rather than dropping it.
323
359
 
324
360
  | Flag | Effect |
325
361
  | --- | --- |
326
- | `--page <slug>` | open on this page; with a pane already running, retarget that pane instead of opening another |
362
+ | `--page <slug>` | open on this page; with this console’s pane already running, retarget it instead of opening another |
327
363
  | `--ascii` | pure-ASCII repertoire, for fonts without box-drawing glyphs |
328
364
  | `--no-color` | no ANSI color |
329
365
  | `--no-mouse` | no mouse reporting, if your terminal multiplexer wants the mouse for itself |
@@ -336,6 +372,13 @@ though one is already running for this project. Watcher-only: `--file <path>`
336
372
  names the default page's state file (the launcher derives it from the project
337
373
  directory).
338
374
 
375
+ Pane ownership is carried by the internal watcher flag `--owner <token>` and
376
+ the optional `owner` field in viewer reports. Launchers derive the token from
377
+ the source console process and its creation time; manual watchers can omit it.
378
+ Focus and quit requests to a bound viewer use its PID, so another window of
379
+ the same project cannot consume them. Bare `mmap` toggles only the pane bound
380
+ to the current console; `mmap --window` toggles the separate project window.
381
+
339
382
  ### The mmap command
340
383
 
341
384
  `mmap`, typed in any terminal, is a **toggle**: it opens the map pane for the
@@ -472,7 +515,10 @@ mean:
472
515
  - **control characters** in text fields — an ESC sequence stored in a label
473
516
  would let a map repaint the terminal of everyone who opens it. `detail` is
474
517
  the exception: newlines and tabs are how a note is written, everything else
475
- (ESC, BEL, lone CR) is still refused;
518
+ (ESC, BEL, lone CR) is still refused. File loading and library saves apply
519
+ the same control-character rules, retaining multiline evidence in older
520
+ files. Terminal rendering also neutralizes controls in maps constructed
521
+ directly by library callers;
476
522
  - **an empty string** where a field is optional — `null` is how a field is
477
523
  cleared, never a blank that renders as a box nobody can tell from a real
478
524
  one;
@@ -500,7 +546,7 @@ ends with what those reports say:
500
546
  | The line | What it means |
501
547
  | --- | --- |
502
548
  | `pane: CLOSED` | nobody is seeing this map; the assistant opens one with `mmap_open` instead of asking you to |
503
- | `pane: open on this page` | you are watching this land |
549
+ | `pane: running on this page` | a live process reports this page; its terminal may be hidden |
504
550
  | `pane: open on <other>, auto-follow on` | the pane follows the page last written, so it arrives here by itself |
505
551
  | `pane: open on <other>, auto-follow OFF` | you pinned that page by hand: the change is real and NOT on your screen. The assistant is told to say so rather than move your view |
506
552
 
@@ -510,6 +556,11 @@ not say which page was on screen. A report whose pane stopped refreshing it is
510
556
  ignored after five seconds and deleted after a minute, so a killed pane cannot
511
557
  go on claiming an audience.
512
558
 
559
+ A heartbeat does not establish screen visibility. An explicit tmux open also
560
+ selects the existing watcher's window, reveals it if another pane was zoomed,
561
+ and verifies the attached session's active window before reporting visibility.
562
+ Focusing that watcher in a shell without `TMUX` reuses its original owner.
563
+
513
564
  ### Setup: choose when maps open
514
565
 
515
566
  How eager mapping should be is a habit, not a property of a repository — so it
@@ -551,15 +602,18 @@ render as boxes and one id must mean one box.
551
602
 
552
603
  ## Development
553
604
 
605
+ See [contributing](CONTRIBUTING.md) and the
606
+ [project structure, branch and recovery guide](docs/project-maintenance.md).
607
+
554
608
  ```
555
- npm install
609
+ npm ci
556
610
  npm run verify
557
611
  ```
558
612
 
559
- `verify` is four steps, in this order: `typecheck`, `test`, `build` (bundles
560
- `dist/`, emits `lib/` with declarations, cleaning both first), and
561
- `check:package` which packs the tarball through the real `prepack`
562
- lifecycle and fails if any `exports` or `bin` target is missing from it.
613
+ Use Node.js 22.12+ for development. `verify` runs `typecheck`, `test`, `build`
614
+ (bundles `dist/` and emits `lib/` with declarations), `check:package`,
615
+ `check:codex`, and `check:release`. These check npm entrypoints, the Codex
616
+ package and both installable editions, including their MCP handshake.
563
617
 
564
618
  The repo is itself layered bottom-up, and each layer has its spec:
565
619
 
@@ -570,7 +624,7 @@ The repo is itself layered bottom-up, and each layer has its spec:
570
624
  | 1 store | `src/store/store.ts` | `store.test.ts`, `atomic-save.test.ts` | atomic state-file persistence on Node |
571
625
  | 1 semantics | `src/semantics/` | `semantics.test.ts` | medium-neutral view semantics: zoom ladder, group aggregation, page-set rules, sequence flip, the shared glyph vocabulary |
572
626
  | 2 apply | `src/server/apply.ts` | `apply.test.ts` | tool inputs → transactional op sequences |
573
- | 3 server | `src/server/server.ts` | `server.test.ts`, `save-failure.test.ts` | the five MCP tools over stdio |
627
+ | 3 server | `src/server/server.ts` | `server.test.ts`, `save-failure.test.ts` | the six MCP tools over stdio |
574
628
  | 4 render | `src/render/` | `render.test.ts`, `routing.test.ts` | the ASCII renderer and its wire routing |
575
629
  | 4 pane | `src/watch/` | `watch.test.ts`, `pane-state.test.ts`, `input.test.ts` | the polling pane: page set, input parsing, panel and chrome |
576
630
  | — launchers | `scripts/` | `open-pane.test.mjs`, `codex-register.test.mjs` | plain-node entry points |
package/README.zh-CN.md CHANGED
@@ -1,16 +1,20 @@
1
1
  # Mellos Mapping · 梅勒斯地图
2
2
 
3
- [![CI](https://github.com/GuangminJu/mellos-mapping/actions/workflows/ci.yml/badge.svg)](https://github.com/GuangminJu/mellos-mapping/actions/workflows/ci.yml)
3
+ [![npm](https://img.shields.io/npm/v/mellos-mapping?logo=npm&logoColor=white&label=npm&color=cb3837)](https://www.npmjs.com/package/mellos-mapping)
4
+ [![downloads](https://img.shields.io/npm/dm/mellos-mapping?label=downloads&color=cb3837)](https://www.npmjs.com/package/mellos-mapping)
5
+ [![MCP registry](https://img.shields.io/badge/MCP_registry-listed-2f6feb)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.GuangminJu/mellos-mapping)
6
+ [![CI](https://img.shields.io/github/actions/workflow/status/GuangminJu/mellos-mapping/ci.yml?branch=main&label=CI)](https://github.com/GuangminJu/mellos-mapping/actions/workflows/ci.yml)
7
+ [![license](https://img.shields.io/badge/license-MIT-444)](LICENSE)
4
8
 
5
9
  [English](README.md) | 简体中文
6
10
 
7
- 给 [Claude Code](https://claude.com/claude-code) Codex CLI 的自下而上
11
+ 给 [Claude Code](https://claude.com/claude-code) 、ChatGPT 桌面 Codex 模式与 Codex CLI 的自下而上
8
12
  开发实况地图,原生运行在终端里。
9
13
 
10
14
  <p align="center">
11
15
  <picture>
12
16
  <source media="(prefers-color-scheme: light)" srcset="docs/demo-light.svg">
13
- <img alt="一张梅勒斯地图的自我构建:幽灵设计先行,spinner 逐层攀升,地基开裂向上传染,诚实修复" src="docs/demo.svg" width="620">
17
+ <img alt="一次 declare 铺开整张幽灵设计,节点自下而上逐个点亮 —— 地基开裂向上传染,绿色再被挣回来" src="docs/demo.svg" width="620">
14
18
  </picture>
15
19
  </p>
16
20
 
@@ -18,41 +22,11 @@ Claude 为你构建系统时,对话旁边的分屏实时显示这个系统的*
18
22
  最底层是原语,依赖边只允许向下指;虚线幽灵节点是已设计未实现的部分,
19
23
  转圈的是此刻正在构建的模块,实心绿色代表已构建**且已验证**。
20
24
 
21
- ```
22
- 梅勒斯地图 · mellos-mapping 插件
23
-
24
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 编排层
25
-
26
- ╭╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮
27
- ╎ · MCP Server ╎
28
- ╰╌╌╌┬┬╌╌╌╌┬╌╌╌╌╯
29
- ││ │
30
- └┼────┼───────────┐
31
- │ └───┐ │
32
- │ │ │
33
- ━━━━━━━┿━━━━━━━━┿━━━━━━━┿━━━ 契约层
34
- │ │ │
35
- ┏━━━━┷━━━━━━━┓│ ╭╌╌╌╌╌┴╌╌╌╌╌╮
36
- ┃ ■ 状态存储 ┃│ ╎ · Watcher ╎
37
- ┗━━━━━┯━━━━━━┛│ ╰╌╌╌╌╌╌┬╌╌╌╌╯
38
- │ │ │
39
- │ ┌─────┘ │
40
- │ │ │
41
- ━━━━━━━━┿━┿━━━━━━━━━━━━━━┿━━ 原语层
42
- │ │ │
43
- ┏━━━━━┷━┷━━━━━━┓ ╭────┴────────╮
44
- ┃ ■ 图领域模型 ┃ │ ⠋ ASCII渲染 │
45
- ┗━━━━━━━━━━━━━━┛ ╰─────────────╯
46
-
47
- · planned ⠋ in-progress ■ done ✗ regressed
48
- ```
49
-
50
- 在真实终端里,连线和层级横条以暗色渲染,节点盒子按状态发光、标签加粗——
51
- 像一块黑色电路板,元件是亮的。跨层的边会从中间层的盒子缝隙里穿过去
52
- (看上图 状态存储 和 Watcher 之间下潜的那根线);互不重叠的走线段共享
53
- 轨道行,让层与层贴得更近。
25
+ <p align="center">
26
+ <img alt="Claude Code 会话旁边的梅勒斯地图面板:六层游戏引擎设计,L0 与 L1 节点实心绿色,上面几层仍是虚线幽灵节点" src="docs/session-claude-code.png">
27
+ </p>
54
28
 
55
- *(这就是本插件自己的地图,开发中途的样子。转圈的 spinner 是真的在转。)*
29
+ *真实会话:左边 Claude Code,右边地图面板。L0 已验证,L1 刚点亮,上面还是幽灵节点。*
56
30
 
57
31
  ## 为什么
58
32
 
@@ -72,6 +46,20 @@ Claude 为你构建系统时,对话旁边的分屏实时显示这个系统的*
72
46
 
73
47
  ## 安装
74
48
 
49
+ 克隆适合自己宿主的分支,运行一个安装命令即可;无需构建。
50
+
51
+ | 分支 | 使用对象 | 在克隆目录运行 |
52
+ | --- | --- | --- |
53
+ | `main` | 共用源码/任一宿主 | `node install.mjs chatgpt-app` 或 `node install.mjs claude` |
54
+ | `claude` | Claude Code | `node install.mjs` |
55
+ | `chatgpt-app` | ChatGPT 桌面 App 的 Codex 模式 | `node install.mjs` |
56
+
57
+ 前置要求为 Node.js 18+ 和对应宿主的 CLI,并确保命令在 PATH 中。安装器检查
58
+ 发行文件和六个 MCP 工具,将运行时保留到克隆目录之外,完成宿主配置。
59
+ 安装后开启新对话。详见[发布与分支说明](docs/releasing.md)。
60
+
61
+ Claude Code 也可以通过插件市场安装:
62
+
75
63
  在 Claude Code 对话里输入两行:
76
64
 
77
65
  ```
@@ -125,7 +113,7 @@ claude plugin marketplace update mellos-mapping && claude plugin update mellos-m
125
113
  ```
126
114
 
127
115
  要两步是因为 `plugin update` 只对比本地缓存的 marketplace 克隆——真正
128
- 拉取本仓库的是第一条命令。重启 Claude Code 生效。发布即 `master` 分支
116
+ 拉取本仓库的是第一条命令。重启 Claude Code 生效。发布即 `main` 分支
129
117
  上的版本号提升。(在对话里输入 `/plugin` 也能打开同一个管理界面。)
130
118
 
131
119
  ### 从 0.19 升级
@@ -149,34 +137,71 @@ the move.`):
149
137
  这一次搬迁是两个进程唯一会碰 `.claude/` 的时刻。此后工具只往 `.mellos/`
150
138
  里写,也绝不会写到启动时解析出的项目目录之外。
151
139
 
152
- ## Codex CLI
140
+ ## ChatGPT App · Codex 模式
153
141
 
154
- 同一个仓库也是 Codex 插件(codex-cli 0.147+)。三行装完:
142
+ 本版用于 ChatGPT 桌面 App 的 Codex 模式(也称 Codex App)。在源码分支运行
143
+ 以下命令;在 `chatgpt-app` 分支运行时省略宿主参数。它会一次配置桌面专用技能、
144
+ 插件市场与六个 MCP 工具。
155
145
 
156
146
  ```
157
- codex plugin marketplace add GuangminJu/mellos-mapping
158
- codex plugin add mellos-mapping@mellos-mapping
159
- node ~/.codex/plugins/cache/mellos-mapping/mellos-mapping/<版本>/scripts/codex-register.mjs
147
+ node install.mjs chatgpt-app
160
148
  ```
161
149
 
162
- 前两行把技能(地图纪律)装成 Codex 插件。第三行在用户级注册 MCP
163
- 服务器——必须这么做,因为 Codex 把插件自带的 MCP 服务器拉起在插件缓存里,
164
- 且不给它任何感知工作区的途径,捆绑的服务器会把地图写进缓存。脚本写入的
165
- 用户级 `codex mcp add` 条目会继承每个会话的工作目录:状态文件落在你的
166
- 项目里,与 Claude Code 下行为一致。注册的是版本相关的绝对路径——插件
167
- 更新后重跑一次脚本即可。
150
+ 安装完成后开启新对话。技能默认使用 **web-terminal 网页终端**:
151
+ `mmap_open {surface: "web-terminal", page: "<slug>"}` 启动本地服务后,
152
+ AI 自动把 URL 打开到当前对话右侧浏览器,直接显示 mmap 终端地图。
153
+ 不需要粘贴命令或 Computer Use;网页有独立字号调节。
154
+ 图形 SVG 网页、原生终端和 Markdown 仍然保留。旧 MCP 对话可使用
155
+ `node "<插件根>/dist/web.mjs" "<项目>" --terminal --page <slug>`。
156
+ 面板排队打开不等于地图已经可见。
157
+ 详见[桌面安装与限制](docs/codex.md)。
168
158
 
169
- 要在 Codex 会话旁边看实况面板,Windows 上运行
159
+ Windows Terminal 使用 Codex CLI 时(不指桌面 App 内置终端),运行
170
160
  `node <插件根>/scripts/open-pane.mjs <项目目录>`——它会在承载本会话的
171
- 终端窗口里分屏(识别不到就确定性地开到专属的 "mellos-mapping" 窗口;
172
- `--window` 则是主动选择专属窗口)。加 `--page <slug>` 指定打开哪一页;
173
- 面板已经开着时,带 `--page` 重跑一次不会再开新面板,而是让现有面板
174
- 切到那一页。面板默认**自动跟随**正在被写入的页——AI 此刻操作哪张图,
161
+ 终端窗口右侧分屏,并保留左侧对话的键盘焦点。识别或聚焦失败时会明确报错,
162
+ 不会改开其他窗口;`--window` 用于明确选择独立窗口。加 `--page <slug>` 指定打开哪一页;
163
+ 当前会话的面板已经开着时,带 `--page` 重跑会让它切到那一页。其他会话
164
+ 或独立窗口中的面板不算当前会话已分屏。面板默认**自动跟随**正在被写入的页——AI 此刻操作哪张图,
175
165
  就看哪张图;按 `f` 开关(手动切页也会关掉),或用 `--no-follow` 启动。
176
166
  其他环境在项目目录下的第二个终端(或任意分屏)运行
177
167
  `node <插件根>/dist/watch.mjs`。两者接受同一套参数,见
178
168
  [面板参数](#面板参数)。
179
169
 
170
+ ### 桌面对话右侧:Markdown 地图
171
+
172
+ 用户选择文档方式时,技能会使用 `mmap_open` 的
173
+ `surface: "markdown"`,生成地图文档后交给宿主在当前对话右侧打开。
174
+ 文档包含彩色 SVG 分层依赖图、模块状态、设计说明、验证记录和子图链接。
175
+ 不需要网页服务或 Mermaid 支持,图像放大仍保持清晰。
176
+
177
+ 首次打开后,本项目中成功的地图工具写入会自动重新生成预览。JSON 仍是
178
+ 唯一数据源,`.mellos/previews/` 是可重新生成的输出。图片里的节点没有
179
+ 拖拽、悬停、双击下潜和动画;用文档链接打开子图。侧栏是否自动刷新由
180
+ 桌面应用决定,生成成功不代表已显示。手动刷新或旧会话可以运行:
181
+
182
+ ```sh
183
+ node "<插件根>/dist/preview.mjs" "<项目目录>" --page <页名>
184
+ ```
185
+
186
+ 完整说明见 [Codex 桌面地图](docs/codex.md#desktop-right-side-map)。
187
+
188
+ ### 可选:交互网页版
189
+
190
+ 现有 Markdown/SVG 用法继续保留。需要缩放拖动、悬停/固定节点详情、依赖
191
+ 高亮、搜索、状态筛选、分组概览、页面和子地图切换时,使用新增的
192
+ `mmap_open {surface: "web", page: "<页名>"}`,将返回的网址交给宿主在右侧
193
+ 浏览器打开。网页直接读取项目地图并自动更新,也支持明暗主题和确认后删页。
194
+
195
+ ```sh
196
+ node "<插件根>/dist/web.mjs" "<项目目录>" --page <页名>
197
+ # 关闭该项目的网页服务:
198
+ node "<插件根>/dist/web.mjs" "<项目目录>" --stop
199
+ ```
200
+
201
+ 服务仅在本机运行,不需要部署或下载网页依赖。Markdown 和网页共用原来的
202
+ JSON 数据,能够同时使用;手动切页会固定当前页面。详见
203
+ [网页版功能与运行方式](docs/codex.md#optional-interactive-web-viewer)。
204
+
180
205
  ## 任意 MCP 客户端
181
206
 
182
207
  服务器已发布到 npm,任何 MCP 客户端(Cursor、Windsurf、Zed、Gemini
@@ -198,7 +223,7 @@ npx -y -p mellos-mapping mellos-mapping-watch
198
223
  插件 MCP 服务器设置的约定),最后才是服务器进程自己的工作目录。如果你的
199
224
  客户端会在你实际工作的项目之外启动服务器,就设 `MELLOS_MAPPING_CWD`。
200
225
 
201
- 技能/纪律层是 Claude Code 与 Codex 专属的;其他客户端获得五个 `mmap_*`
226
+ 技能/纪律层是 Claude Code 与 Codex 专属的;其他客户端获得六个 `mmap_*`
202
227
  工具和面板,提示词自备。
203
228
 
204
229
  ## 使用
@@ -216,6 +241,23 @@ npx -y -p mellos-mapping mellos-mapping-watch
216
241
  3. 看着节点从底部一路亮起。图让你不安的时候就打断它——这正是它存在的
217
242
  意义。
218
243
 
244
+ 在 Linux 和 macOS 上,`mmap_open` 与 `mmap` 会自动使用 tmux。启动器优先
245
+ 定位继承的 `TMUX`/`TMUX_PANE`;工具进程丢失这些变量时,会自动发现默认
246
+ tmux 服务中唯一已连接的会话。默认在右侧分屏并保留输入焦点;`--window`
247
+ 创建一个新的 tmux 窗口。再次打开会复用属于该源面板或会话窗口的 watcher。
248
+
249
+ 如果有多个已连接的会话,或使用自定义 tmux socket,在 MCP 服务进程的
250
+ 环境中设置以下变量(修改后重启该进程):
251
+
252
+ | 环境变量 | 含义 |
253
+ | --- | --- |
254
+ | `MELLOS_MAPPING_TMUX_TARGET` | 指定 tmux 会话或面板,例如 `work:2.1` 或 `%7` |
255
+ | `MELLOS_MAPPING_TMUX_SOCKET` | socket 的绝对路径,例如 `/tmp/my-tmux/socket` |
256
+
257
+ 目标不明确、会话未连接或没有安装 tmux 时,启动器会返回具体原因,以及
258
+ 包含项目、页面和正确引号的一条完整 watcher 命令,可以粘贴到可见终端。
259
+ 地图仍可正常写入;打开失败后,助手只在环境变化或你要求重试时再次打开。
260
+
219
261
  分屏支持鼠标(xterm SGR any-event 协议——htop 和 tmux 说的同一种话):
220
262
 
221
263
  | 输入 | 动作 |
@@ -301,14 +343,19 @@ used by ← …`,每个邻居各带自己的状态字形),以及自动折
301
343
  watcher 的:`--file <path>` 指定默认页的状态文件(启动脚本会从项目目录
302
344
  自己推导出来)。
303
345
 
346
+ 内部 watcher 参数 `--owner <token>` 和面板报告的可选 `owner` 字段承载会话绑定。
347
+ 启动器用源控制台进程及创建时间生成身份;手动运行 watcher 可省略。切页和关闭
348
+ 请求按面板 PID 定向投递,同项目其他窗口不会抢走请求。普通 `mmap` 只切换当前
349
+ 会话的面板;`mmap --window` 切换本项目的独立窗口。
350
+
304
351
  ### mmap 命令
305
352
 
306
- 在任何终端里敲 `mmap`,它是一个**开关**:本项目还没有面板就开一个,已经
307
- 有面板就把它关掉。
353
+ 在终端里敲 `mmap`,它是当前会话地图的**开关**:本会话还没有面板就开一个,
354
+ 已经有面板就把它关掉。
308
355
 
309
356
  | 你敲的 | 发生什么 |
310
357
  | --- | --- |
311
- | `mmap` | 本项目没有面板在跑 → 开一个;有 → 关掉它 |
358
+ | `mmap` | 当前会话没有面板在跑 → 开一个;有 → 关掉它 |
312
359
  | `mmap <页 slug>` | 打开时定位到这一页,或者让已开的面板切过去——永远不关 |
313
360
  | `mmap --window` | 开到专属的 "mellos-mapping" 窗口,而不是把当前窗口分屏 |
314
361
  | `mmap --force` | 即使已经有面板在跑也再开一个 |
@@ -420,7 +467,9 @@ Claude 会话的正确姿势。
420
467
  丢掉的字段;任何嵌套深度都一样;
421
468
  - 文本字段里的**控制字符**——藏在标签里的 ESC 序列,会让这张图重绘每一个
422
469
  打开它的人的终端。`detail` 是例外:换行和制表符本来就是写笔记的方式,
423
- 其余(ESC、BEL、单独的 CR)照样拒绝;
470
+ 其余(ESC、BEL、单独的 CR)照样拒绝。文件加载和公共库保存也校验控制字符,
471
+ 同时兼容旧文件中的多行证据。直接通过公共库构造地图时,终端渲染仍会消除
472
+ 控制字符的执行效果;
424
473
  - 可选字段上的**空字符串**——清空字段用 `null`,而不是一个渲染出来跟真盒子
425
474
  分不清的空白;
426
475
  - **`submap` 指向本次调用所针对的那一页的节点**——那是个没有底的环,不是
@@ -445,7 +494,7 @@ Claude 会话的正确姿势。
445
494
  | 这一行 | 意思 |
446
495
  | --- | --- |
447
496
  | `pane: CLOSED` | 没人在看这张图;助手会用 `mmap_open` 自己开,而不是回过头来要求你开 |
448
- | `pane: open on this page` | 你正看着它落地 |
497
+ | `pane: running on this page` | 活跃进程报告正在显示这一页,但终端可能被隐藏 |
449
498
  | `pane: open on <其他页>, auto-follow on` | 面板跟随最后被写入的那一页,它自己会过来 |
450
499
  | `pane: open on <其他页>, auto-follow OFF` | 那一页是你亲手钉住的:这次改动是真的,但**不在**你屏幕上。助手被要求把这件事说出来,而不是把你的视图搬走 |
451
500
 
@@ -454,6 +503,10 @@ Claude 会话的正确姿势。
454
503
  超过五秒没被刷新的报告不再算数,超过一分钟就被读到它的人删掉,所以被强杀
455
504
  的面板不会一直冒领观众。
456
505
 
506
+ 心跳不等于屏幕可见。显式调用 tmux 打开操作时,启动器还会切回已有地图所在的
507
+ 窗口,解除遮挡地图的面板缩放,并检查已连接会话的活动窗口后再报告可见。
508
+ 缺少 `TMUX` 环境变量、焦点又落在地图面板上时,会沿用原来的归属,避免重复打开。
509
+
457
510
  ### Setup:选择什么时候建图
458
511
 
459
512
  建图要多积极,是一个人的工作习惯,不是某个仓库的属性——所以它**只为你选
@@ -488,14 +541,16 @@ AI。从此再也不需要按项目设置什么。
488
541
 
489
542
  ## 开发
490
543
 
544
+ 先阅读[贡献说明](CONTRIBUTING.md)和[项目结构、分支与恢复指南](docs/project-maintenance.md)。
545
+
491
546
  ```
492
- npm install
547
+ npm ci
493
548
  npm run verify
494
549
  ```
495
550
 
496
- `verify` 是按顺序的四步:`typecheck`、`test`、`build`(打包 `dist/`、产出带声明的 `lib/`,两个
497
- 目录都先清空),以及 `check:package`——它按真实的 `prepack` 生命周期打出
498
- tarball,只要 `exports` `bin` 里有任何目标没被打进去就失败。
551
+ 开发环境使用 Node.js 22.12+。`verify` 依次运行 `typecheck`、`test`、`build`
552
+ (打包 `dist/`、产出带声明的 `lib/`)、`check:package`、`check:codex`
553
+ `check:release`,检查 npm 入口、Codex 包和两个可安装发行包,包括 MCP 握手。
499
554
 
500
555
  这个仓库本身就是自下而上分层的,每一层都有自己的规格测试:
501
556
 
@@ -506,7 +561,7 @@ tarball,只要 `exports` 或 `bin` 里有任何目标没被打进去就失败
506
561
  | 1 store | `src/store/store.ts` | `store.test.ts`、`atomic-save.test.ts` | Node 上的原子化状态文件持久化 |
507
562
  | 1 semantics | `src/semantics/` | `semantics.test.ts` | 媒介无关的视图语义:缩放阶梯、分组聚合、页集规则、时序翻转、共享字形词汇表 |
508
563
  | 2 apply | `src/server/apply.ts` | `apply.test.ts` | 工具输入 → 事务性操作序列 |
509
- | 3 server | `src/server/server.ts` | `server.test.ts`、`save-failure.test.ts` | stdio 上的五个 MCP 工具 |
564
+ | 3 server | `src/server/server.ts` | `server.test.ts`、`save-failure.test.ts` | stdio 上的六个 MCP 工具 |
510
565
  | 4 render | `src/render/` | `render.test.ts`、`routing.test.ts` | ASCII 渲染器与它的走线 |
511
566
  | 4 pane | `src/watch/` | `watch.test.ts`、`pane-state.test.ts`、`input.test.ts` | 轮询面板:页集、输入解析、详情面板与外框 |
512
567
  | — 启动脚本 | `scripts/` | `open-pane.test.mjs`、`codex-register.test.mjs` | 纯 node 的入口 |