Skip to main content
Glama

Mellos Mapping

npm downloads MCP registry CI license LINUX DO

English | 简体中文

A live, terminal-native map of bottom-up development for Claude Code, ChatGPT desktop Codex mode and Codex CLI.

While Claude builds your system, a split pane beside the conversation shows the system's layered dependency map: primitive layers at the bottom, dependency edges that may only point downward, ghost nodes for what is designed, a spinner on what is being built right now, and solid green for what is built and verified.

A real session: Claude Code on the left, the map pane on the right. L0 is verified, L1 just lit up, everything above is still a ghost.

Why

Most progress reporting is a task list — a top-down worldview. A Mellos map grows the other way: an upper node can only stand on nodes below it, and the picture makes the discipline visible:

  • The ghost design appears before any code. Claude declares the whole intended structure as dashed ghost nodes first; you can veto a bad design while it is still only a picture.

  • The spinner is where Claude's attention is. One glance answers "what is it doing right now, and on top of what?"

  • Done means verified. A node turns solid green only with evidence (a passing test run). If later work cracks a foundation, the node turns red — a cracked foundation under a spinning upper floor is the most honest status report there is.

  • The map is a ledger, not a judge. The tools refuse only structural corruption (an edge pointing upward, a duplicate rank). Workflow is Claude's discipline, defined in the bundled skill; violations are made visible, never silently blocked.

Related MCP server: lxDIG MCP

Install

Clone the branch for your host, then run one command. No build is required.

Branch

Audience

Command from the clone

main

Shared source / either host

node install.mjs chatgpt-app or node install.mjs claude

claude

Claude Code

node install.mjs

chatgpt-app

ChatGPT desktop, Codex mode

node install.mjs

Requires Node.js 18.17+ on the 18.x line, or 20.3+, and the corresponding host CLI on PATH. Supported platforms are Windows 10+, macOS 13.0+ and Linux with glibc 2.28+, each on x64 or arm64. The OS must also meet the selected Node.js version's requirements. Native lock bindings ship with the release; no local compilation is needed. The installer checks release integrity and all eight MCP tools, retains the runtime outside the clone, and configures the host. Start a new conversation after installation. See release and branch instructions.

Claude Code's marketplace installation is also available:

Two lines inside any Claude Code conversation:

/plugin marketplace add GuangminJu/mellos-mapping
/plugin install mellos-mapping@mellos-mapping

Or one line in a terminal:

claude plugin marketplace add GuangminJu/mellos-mapping && claude plugin install mellos-mapping@mellos-mapping

Requires the same Node.js and platform versions on PATH (install Node separately when using native Claude Code). No build step: dist/ is committed, so a clone runs as-is — dist/server.mjs (the MCP server), dist/watch.mjs (the pane), dist/mmap.mjs (the mmap toggle), dist/hook-session-start.mjs (the SessionStart hook that hooks/hooks.json registers) and dist/store-paths.mjs (the store's path vocabulary, which the plain-node pane launcher imports instead of restating filenames).

omp (Oh My Pi) reads the same plugin layout the Claude Code edition ships — the same marketplace catalog, .mcp.json, skill and slash command — so one release serves both hosts:

omp plugin marketplace add GuangminJu/mellos-mapping
omp plugin install mellos-mapping@mellos-mapping

That install follows main, where a release is a version bump. To freeze a version instead, add a checkout of one — the Claude Code edition ZIP from the GitHub Release, or a clone at the release tag:

omp plugin marketplace add "<checkout or extracted release directory>"
omp plugin install mellos-mapping@mellos-mapping

omp never reads hooks/hooks.json, so the session paragraph arrives through the plugin's omp host adapter (dist/omp-extension.mjs, declared in package.json#omp.extensions): the same store, the same policy text, and the same mmap shim install as the Claude hook. The pane is the same terminal split beside the session. Install it as a plugin: neither omp plugin link nor the npm package is a plugin, and both would leave the tools behind. See omp installation and limitations.

pi reads none of that layout: it loads an extension and has no MCP of its own, by design. So the plugin speaks MCP to itself — the extension declared in package.json#pi.extensions (dist/pi-extension.mjs) starts the same dist/server.mjs in the session's directory, which makes the eight mmap_* tools the same eight, under the same names, and builds the session paragraph from the same store and the same policy text the Claude hook prints:

pi install npm:mellos-mapping

Add -l to install it for the current project instead of every one, then start a new session: pi discovers packages at session start. The package's skills/ and commands/ travel with it — the same map discipline, and /mmap for the same slash command. See pi installation and behaviour.

The first session after installing asks you one question — how eager mapping should be — and records the answer for every project you will ever open. From then on the hook carries it into each new session by itself; there is no per-project setup step. See Setup: choose when maps open.

The mmap terminal command (the pane's open/close toggle) installs itself on Windows: the same hook notices on session start when the shim is missing or points at an older install, writes mmap.cmd (cmd, PowerShell) and mmap (git-bash) into %LOCALAPPDATA%\mellos-mapping\bin, appends that one directory to your user PATH, and tells you so through the assistant. The PATH change reaches only new processes — and a new tab of a running Windows Terminal inherits the old environment, so close the terminal app entirely and reopen it before the first mmap. The PATH edit keeps the installer's guarantees: nothing happens when the entry is already there, and a PATH that setx would damage (flattened %VARIABLE% references, truncation past its limit) is refused outright.

A refused PATH is not a dead end: the same two shims are then written into %LOCALAPPDATA%\Microsoft\WindowsApps (or ~/.local/bin) — a directory your PATH already names — so mmap is runnable in a new terminal with no PATH change at all. Machines with a long PATH are exactly where that happens, and where it matters most. The command takes the page to open as an argument (mmap omp-host-support), and closes the pane when it is already open.

The step behind it is still a command of its own, for the cases the hook does not cover — --uninstall, or re-adding a PATH entry you removed while the shims stayed put:

node "<plugin dir>/scripts/install-mmap-command.mjs" [--uninstall]

(--json prints the install outcome as one JSON line instead of prose — the mode the hook itself calls it in.) npm i -g mellos-mapping provides the same mmap via bin, no shims involved.

Update

claude plugin marketplace update mellos-mapping && claude plugin update mellos-mapping@mellos-mapping

Two steps because plugin update compares against the locally cached marketplace clone — the first command is what actually pulls this repo. Restart Claude Code to apply. Releases are version bumps on main. (In-app, /plugin opens the same management UI.)

omp updates with its own two steps:

omp plugin marketplace update mellos-mapping && omp plugin upgrade mellos-mapping@mellos-mapping

Close the pane first (q in it): the watcher runs from the plugin copy, and on Windows an open file cannot be renamed away, so an upgrade attempted while a pane is open can fail with EPERM and leave the plugin cache empty — repaired by omp plugin install mellos-mapping@mellos-mapping --force. Then: the first command refreshes the catalog, the second reinstalls from it. omp also refreshes a catalog entry it has not updated for a day at startup, unless marketplace.autoUpdate is off — in the default notify mode that check writes its finding to the debug log only, so marketplace update is the step that makes an update visible. upgrade does not compare versions: it force-reinstalls whatever the catalog names, which is why a release is identified by its version bump rather than gated by it. Restart omp afterwards, and reopen a pane still showing the old bundle (q in it, then mmap_open again).

pi updates the package it installed, with no marketplace in between:

pi update npm:mellos-mapping

That is the npm source; a git source is reconciled to the ref your settings name by pi's own update, and a versioned spec (npm:mellos-mapping@0.27.0) is pinned and skipped. Restart the session afterwards: a session owns the map server process it started, so one still running keeps the copy it began with until it ends.

Upgrading from 0.19

0.20 moved the store out of .claude/ — the map belongs to this tool, not to one client — into .mellos/. The server and the watcher each perform the move once at startup, and print exactly one line on stderr when they do (mellos-mapping: moved the legacy .claude map store to .mellos/ — commit the move.):

0.19 and earlier

0.20 and later

.claude/mellos-mapping.json

.mellos/map.json

.claude/mellos-mapping.pages/

.mellos/pages/

.claude/mellos-mapping.config.json

.mellos/config.json

Nothing is merged and nothing is overwritten: a project that already has a .mellos/ store (map, pages or config) is left untouched, whatever the legacy directory still holds. If you keep your maps in git, commit the move — git add -A .claude .mellos records it as renames rather than as a pile of deletions plus untracked files.

That one move is the only time either process touches .claude/. Afterwards the tools write nowhere but .mellos/, and never outside the project directory they resolved at startup.

ChatGPT App · Codex mode

This is Codex mode in the ChatGPT desktop app (also called Codex App). From the source branch run the following command; on chatgpt-app, omit the host argument. It configures the desktop skill, marketplace and eight MCP tools.

node install.mjs chatgpt-app

Start a new conversation. The desktop skill defaults to web-terminal: mmap_open {surface: "web-terminal", page: "<slug>"} starts a local service, then the AI opens its URL in the current conversation's right browser panel. The mmap terminal starts automatically, with its own font-size selector; no manual paste or Computer Use is needed. Graphical SVG, native terminal and Markdown remain available. With an older MCP schema, run node "<plugin root>/dist/web.mjs" "<project>" --terminal --page <slug>. A queued panel request does not prove that the user can see it. See desktop installation and limitations.

For Codex CLI inside Windows Terminal (not the desktop integrated terminal), run node <plugin root>/scripts/open-pane.mjs <project dir> — it splits the terminal window hosting the session, keeping keyboard focus on the conversation. If that window cannot be identified or focused, it reports failure without opening elsewhere. --window explicitly chooses a separate window. Add --page <slug> to open on a particular page — and with a pane already open, rerunning with --page retargets the pane belonging to this console. A map open in another session or a separate window does not count as this split. The pane auto-follows the page being written — the map the agent is operating on right now; press f to toggle that (a manual page switch also turns it off), or start with --no-follow. Elsewhere run node <plugin root>/dist/watch.mjs from the project directory in a second terminal (or any terminal split). Both take the same flags — see Pane flags.

Desktop Markdown map

When the user chooses the document surface, the skill uses mmap_open {surface: "markdown", page: "<slug>"} and opens the returned file beside the current conversation. The document embeds a colored SVG dependency map plus module details, evidence, and child-page links. It needs no web server, browser rendering process, Mermaid support, or additional runtime dependencies.

Successful MCP map writes regenerate enabled previews in .mellos/previews/; JSON remains the source of truth. Image nodes are static. File visibility and automatic viewer refresh belong to the desktop host. See the desktop map guide for regeneration, cache behavior, and limitations.

Optional interactive web viewer

An additional interactive web viewer is available with mmap_open {surface: "web", page: "<slug>"} or node "<plugin root>/dist/web.mjs" "<project directory>" --page <slug>. Open its returned URL in the host's right browser panel. It provides live updates, pan/zoom, hover and pinned details, search, dependency highlighting, filters, group overview, submaps and themes. Stop it with node "<plugin root>/dist/web.mjs" "<project directory>" --stop. Markdown/SVG and terminal workflows remain available; all surfaces share the same map data. See web viewer details.

Any MCP client

The server ships on npm, so any MCP client (Cursor, Windsurf, Zed, Gemini CLI, …) can run it with a standard stdio entry:

npx -y mellos-mapping

The map file lands in the client session's working directory (.mellos/map.json). Open the live pane from the same project:

npx -y -p mellos-mapping mellos-mapping-watch

The server picks its project directory in this order: MELLOS_MAPPING_CWD (an explicit override, for clients that spawn servers from a fixed directory), then CLAUDE_PROJECT_DIR (what Claude Code sets for plugin MCP servers), then the server process's own working directory. Set MELLOS_MAPPING_CWD when your client would otherwise start the server somewhere other than the project you are working in.

The skill/discipline layer is Claude Code + Codex specific; other clients get the eight mmap_* tools and the pane, and bring their own prompting.

Use

  1. Ask Claude to build something non-trivial. The bundled skill has Claude declare the ghost design and keep the map current as it works.

  2. The pane opens itself. Every write tells Claude whether anybody is actually looking (see Who is watching), and Claude opens or retargets the pane with mmap_open when nobody is — you never have to remember to. Open or close it yourself with mmap in any terminal, or /mellos-mapping:mmap in the conversation (Windows Terminal split on Windows, tmux split inside tmux, or a printed command to run in any second terminal). On Windows the pane opens in the terminal window hosting YOUR session, even with several windows open; pass --window to put the map in its own dedicated window instead. Prefer --ascii if your font lacks box-drawing glyphs.

  3. Watch nodes light up from the bottom. Interrupt when the picture worries you — that is what it is for.

On Linux and macOS, mmap_open and mmap automatically use tmux. The launcher targets the inherited TMUX/TMUX_PANE; if the tool process lost those variables, it discovers the single attached session on the default tmux server. The default is a right split that preserves input focus; --window creates a new tmux window. Repeated opens reuse the watcher bound to that source pane or session window.

For multiple attached sessions or a custom tmux socket, set these variables in the environment of the MCP server (restart it after changing them):

Variable

Meaning

MELLOS_MAPPING_TMUX_TARGET

Explicit tmux session or pane, such as work:2.1 or %7

MELLOS_MAPPING_TMUX_SOCKET

Absolute socket path, for example /tmp/my-tmux/socket

Ambiguous sessions, detached sessions and missing tmux produce a concrete error and a fully quoted watcher command, including the project and requested page, to paste into any visible terminal. Map writes remain available; after an open failure the assistant retries only when the environment changes or you ask.

The pane is mouse-aware (xterm SGR any-event tracking — the same protocol htop and tmux speak):

Input

Action

hover a node

spotlight its wires; preview its details below the map

click a node

pin it — details stay resident after the mouse leaves

click empty space / Esc

unpin; with nothing pinned, Esc climbs out of a dive

wheel / + -

zoom, anchored on the focused node (see the ladder below)

left-drag

grab and pan when the map outgrows the pane

shift+wheel

scroll vertically

wheel tilt (horizontal)

pan sideways

hjkl / arrows

nudge the view

Tab / Shift+Tab / 1-9 / click a tab

switch pages (parallel maps)

wheel on the tab row / click

browse an overflowing tab strip without switching pages

f

toggle auto-follow (see Pages)

x, or click the × on the active tab

ask to delete the page on screen; press again inside the window and its file is removed (see Pages)

double-click a node

dive into its sub-map (a child page)

Backspace / Esc

climb back out of the last dive

drag the divider

resize the detail panel — pull it up to read long design notes in full

0

reset pan and zoom

q / Ctrl+C

quit the pane

Every other key is inert, on purpose: an escape sequence the pane does not know (F-keys, Home/End, PgUp/PgDn, Insert/Delete, modified arrows) is consumed whole and does nothing, rather than having its payload bytes read as hotkeys.

Zooming scales the picture first and switches display mode only at the ends of the ladder, so every level still shows meaningful data:

detail+ ← detail ← 100% ← 85% ← 70% ← 55% ← overview
  • zoom in past 100%detail unfolds evidence and the first three lines of the design notes inside the boxes; detail+ widens them into reading cards (up to twelve note rows);

  • 85–55% — whitespace tightens and labels truncate proportionally, boxes stay boxes;

  • below 55% — labels would stop meaning anything, so the map AGGREGATES: each declared group (a labeled subsystem within a band) becomes one box named foundation subsystem 1/2 with its status derived from the members, edges collapse onto the groups, ungrouped nodes stay themselves. Like a real map, zooming out shows province names — not anonymous dots. (A map with no groups falls back to a pure glyph constellation with per-band counts.) The footer always names the level.

Below the map, between it and the hint line, sits a fixed-height detail panel: a separator you can drag, a status-colored header, the focused node's evidence, both wire directions (uses → … · used by ← …, each neighbour carrying its own status glyph) and its design notes, word-wrapped. With nothing focused it shows the map's dashboard instead. Fixed height — details never float over the map and the layout never jumps.

Glyphs

One status, one glyph, everywhere a map is drawn — the pane's boxes, its tab strip and detail panel, and any other client reading the same store:

Unicode

ASCII

Meaning

·

.

planned — declared, not started

*

in-progress, at rest — a box that can animate spins through the braille frames (⠋⠙⠹…) instead, or a four-bar cycle in ASCII

#

done, with evidence

o

done, with no evidence recorded — same claim, nothing behind it

X

regressed: was done, now broken

+

badge: the node links a sub-map; double-click dives in

The legend under the picture names the four statuses; □ done, no evidence joins it only on a map that actually contains one — the four are the vocabulary, that one is a rule being broken here and now. Documentation diagram kinds replace the status legend with their node-kind glyphs.

Pane flags

Both the pane launcher (scripts/open-pane.mjs <project dir>) and the watcher (dist/watch.mjs) take the same watcher flags; the launcher forwards them verbatim and rejects anything it does not know rather than dropping it.

Flag

Effect

--page <slug>

open on this page; with this console’s pane already running, retarget it instead of opening another

--ascii

pure-ASCII repertoire, for fonts without box-drawing glyphs

--no-color

no ANSI color

--no-mouse

no mouse reporting, if your terminal multiplexer wants the mouse for itself

--no-follow

start with auto-follow off

--interval <ms>

poll interval; default 250, floored at 50

Launcher-only: --window opens the dedicated "mellos-mapping" window instead of splitting the session's window, and --force opens another pane even though one is already running for this project. Watcher-only: --file <path> names the default page's state file (the launcher derives it from the project directory).

Pane ownership is carried by the internal watcher flag --owner <token> and the optional owner field in viewer reports. Launchers derive the token from the source console process and its creation time; manual watchers can omit it. Focus and quit requests to a bound viewer use its PID, so another window of the same project cannot consume them. Bare mmap toggles only the pane bound to the current console; mmap --window toggles the separate project window.

The mmap command

mmap, typed in any terminal, is a toggle: it opens the map pane for the project you are standing in, or closes the one that is already open.

You type

What it does

mmap

nothing watching this project → open the pane; something watching → close it

mmap <page-slug>

open on that page, or retarget an already-open pane to it — never closes

mmap --window

open in the dedicated "mellos-mapping" window instead of splitting this one

mmap --force

open another pane even though one is already running

The project is found the way git finds its root: from the current directory upwards, to the nearest one holding a .mellos/ store. Standing in a project that has no map yet is fine — the pane opens on its standby screen and says so until the first mmap_declare.

Closing goes through the store rather than through a signal: mmap writes a one-shot request beside the map, the pane consumes it on its next poll (250 ms by default) and exits, handing the terminal back exactly as it found it — mouse reporting off, cursor visible. A pane still on the standby screen closes the same way. The request is deleted as it is read, and a leftover from a pane that died is swept when the next one starts, so a stale request can never close a fresh pane.

Every watcher flag above works here too, forwarded verbatim; an unknown one is a usage error, never dropped in silence. mmap needs installing once unless you have the npm package. Inside a Claude Code conversation, /mellos-mapping:mmap opens the same pane.

Pages

A project can keep several maps side by side — one effort = one page. Claude targets a page by passing page to any mmap_* tool; the pane grows a tab bar as soon as a second page exists. The active tab is bold in its map's aggregate status color. Each page remembers its own pan, zoom and pinned node.

By default the pane follows the page being written — the map the agent is operating on right now — so declares and updates bring the audience along by themselves. f toggles that, a manual page switch turns it off, and --no-follow starts it off; with follow off, a background page's change lights its tab in status color instead of stealing your view. An explicit --page outranks follow, and a page requested before it exists is shown the moment it appears.

Deleting a page. An effort ends; its page does not have to stay. In the pane, x — or the × the active tab carries when the mouse is on — asks: the footer says press x again to delete <page>, and a second press within three seconds removes that page's file. Switching page, Esc or simply waiting takes the request back. The × sits on the active tab only, so clicking an inactive one switches to it first and offers its × on the next frame. From a tool call it is mmap_remove {pages: ["slug", …]}, applied after that call's map edits. Either way the file is gone for good — the maps are plain JSON, so committing them is the only undo there is.

State lives in the tool-owned .mellos/ directory at the project root:

Path

What it is

.mellos/map.json

the default page — optional; a project whose work lives on named pages has none

.mellos/pages/<slug>.json

one file per named page

.mellos/config.json

the project's mapping policy (see Setup)

.mellos/focus

one-shot "show this page" request from a launcher to a running pane; the pane consumes it and deletes it within a poll tick

.mellos/quit

one-shot "close yourself" request from the mmap toggle, consumed and deleted the same way

.mellos/viewers/<pid>.json

one report per live pane — the page it is showing, whether auto-follow is on — refreshed every second while it runs (see Who is watching)

<any of the above>.<pid>.<random>.tmp

a save in flight; it is renamed over its target or removed. A leftover means a write failed (and was reported) and even its cleanup could not run

.mellos/.write-lock

permanent regular file for the OS project lock; keep it untracked and never remove, rename or replace it during normal operation

The map files are plain JSON, safe to commit if you want the maps' history in git. Keep focus, quit, viewers/ and .write-lock out of Git. The first three carry runtime messages; the lock file must remain in place, including when no process holds its lock.

Concurrency, stated plainly. Every save is atomic — written to a private sibling temp file and renamed over the target — so a reader polling the store sees the previous complete map or the new one, never a torn write. Every graph writer (MCP, the HTTP viewer, the watcher) uses the same non-blocking OS exclusive lock for the project. The lock has its own fixed file, separate from the map files being replaced; it stays in place after the OS releases the lock on completion or process exit. Contention returns a retryable BUSY.

The lock serializes each operation's read, change and save. To protect an edit computed from an earlier read, pass expectedRevision: it is compared inside the lock, and a stale revision returns CONFLICT. Without it, a later write can still overwrite the same field or a whole value such as context. Pages separate unrelated efforts; sharing a page still requires revision-checked edits. Low-level saveMapFile, hand edits and older running processes do not participate in this contract. Stop all old MCP, viewer and watcher processes for the project before upgrading; an old lock directory needs a one-time migration. See the persistent-map API guide and project locking for the boundary and upgrade steps.

Diagram kinds

The default kind, dev, is the living progress ledger described above. The same layered-DAG machinery also draws documentation diagrams: pass kind in mmap_declare and the page renders neutrally — plain solid boxes, no ghosts, no spinners, no progress counts.

Kind

Reading

Extras

architecture

layered components (also module deps, call graphs)

edge labels for protocols

dataflow

pipeline stages as layers, sources at the bottom

edge labels for the data

behavior-tree

leaves (actions) at the bottom, root on top (also mind maps, WBS)

node kinds selector sequence parallel decorator condition action render as glyphs

sequence

classic call/return: time flows top-down, participants as lane headers; every call and every return is an event in the acting participant's lane

lanes are participants; edge labels are messages

Node kinds and edge labels work on dev maps too. State machines are out of scope on purpose: transitions cycle, and edges here only point downward.

Sub-maps

A node can link a child page with submap: <page-slug> — the pane badges it ; double-click dives into the child map, Backspace climbs back out. A map of maps, built entirely from pages: no new storage, no new invariants. Whether a node deserves a sub-map is the AI's judgment call — most don't.

Sub-maps are interior detail, not siblings: a page some other page dives into never occupies a tab. Two refinements keep the tab strip from erasing itself — a page whose own node names itself hides nobody, and a link cycle keeps its tabs unless a page outside the cycle dives in, because a cycle has no outside to climb back to. Inside a dive the tab row becomes a breadcrumb — ⌫ parent map ▸ node — and clicking it (or Backspace) climbs back out. When a hidden sub-map changes in the background, the footer says so.

MCP tools

Start with mmap_read to resume an existing page; a new conversation is not a new effort. Use stable IDs, filtered reads and revision-checked writes. The persistent-map API guide covers complete CRUD, atomic mixed batches, context checkpoints, source hashes and worktree boundaries.

Tool

Purpose

mmap_declare

Grow the map: title (null removes it), diagram kind, layer bands, lanes, groups (subsystems), nodes — with status, evidence, detail, kind, group, lane, submap — and edges, optionally labeled (all-or-nothing batch)

mmap_update

Record progress and revise: status (planned → in-progress → done +evidence, regressed), relabel a node, move it to another band (layer), join/leave a group or lane, set a node kind or a submap; rename and re-rank bands (layers), relabel groups (groups) and lanes (lanes); null clears any clearable field

mmap_remove

Revise: drop edges, nodes, groups, lanes, empty bands — and, with pages, whole pages, file and all (permanent; applied after this call's map edits)

mmap_view

Render the current map as text inline (optional zoom, -42), ending with a pages: line naming every page the project has and which one you are looking at

mmap_read

Structured page discovery, precise IDs, filtered/paginated reads, context and source changes

mmap_batch

One-page mixed create/update/remove transaction with a revision check

mmap_setup

Get/set the project's mapping policy — when maps open

mmap_open

Put the map on your screen: open the pane, or retarget an open one to a page (window: true for the dedicated window). It answers with whether a pane actually reported in afterwards, not merely that a command ran — and it can never close one

A batch applies bands → groups → lanes → node updates, and within one node update layer moves the node before its other fields, so a node can move and join a group on its new band in one item.

What the boundary refuses, so the ledger never records something it did not mean:

  • an unknown key, naming it — a misspelled evidance is an error, not a silently dropped field, at every nesting depth;

  • control characters in text fields — an ESC sequence stored in a label would let a map repaint the terminal of everyone who opens it. detail is the exception: newlines and tabs are how a note is written, everything else (ESC, BEL, lone CR) is still refused. File loading and library saves apply the same control-character rules, retaining multiline evidence in older files. Terminal rendering also neutralizes controls in maps constructed directly by library callers;

  • an empty string where a field is optional — null is how a field is cleared, never a blank that renders as a box nobody can tell from a real one;

  • a node whose submap names the page the call itself targets — a link with no bottom, not a parent link;

  • a page deletion aimed at the page the same call targets, or at a slug the project does not have — one call must not edit a map it is deleting, and a name matching no page is a typo far more often than a race; the refusal lists the pages that do exist.

A write that does not land answers save failed, nothing changed (retry): the previous file is intact and calling again is the whole recovery.

Who is watching

A map nobody has on screen is a file, not a map — and nothing in the system used to be able to tell the difference. An assistant would declare a design, light nodes up as it built them, and report all of it into a store you had never opened a pane for.

Every pane now publishes a small report while it runs — .mellos/viewers/, one file per pane, refreshed once a second — and every write and every view ends with what those reports say:

The line

What it means

pane: CLOSED

nobody is seeing this map; the assistant opens one with mmap_open instead of asking you to

pane: running on this page

a live process reports this page; its terminal may be hidden

pane: open on <other>, auto-follow on

the pane follows the page last written, so it arrives here by itself

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

The same reports answer "is a pane already open?" for mmap and for the launcher — a question that used to cost a Windows-only process scan and could not say which page was on screen. A report whose pane stopped refreshing it is ignored after five seconds and deleted after a minute, so a killed pane cannot go on claiming an audience.

A heartbeat does not establish screen visibility. An explicit tmux open also selects the existing watcher's window, reveals it if another pane was zoomed, and verifies the attached session's active window before reporting visibility. Focusing that watcher in a shell without TMUX reuses its original owner.

Setup: choose when maps open

How eager mapping should be is a habit, not a property of a repository — so it is chosen once, for you, in the first session after you install:

  • always — map every structured task: workflows, designs, architecture, technical dependencies. The assistant opens the pane on its own initiative; your recorded answer is its standing consent, so it stops asking.

  • complex — the same, but only for medium or complex tasks: several modules, a new subsystem, roughly an hour of work or more.

  • on-request — map only when you explicitly ask. In a project with no map, the plugin then says nothing at all — zero noise is the point.

The answer lands in <your home>/.mellos/config.json and reaches every session through the plugin's SessionStart hook, which reads it and hands the assistant the matching instruction before you have typed anything. Nothing has to be set up per project, ever again.

One project can still differ: mmap_setup {policy, scope: "project"} records a policy in that project's .mellos/config.json, and a project policy overrides the user one. /mmap setup re-runs the question for either scope whenever you want to change your mind. The policy guides the assistant; it never blocks the tools, and asking for a map explicitly always works under any policy.

Hosts without hooks (Codex CLI, a bare MCP client) get the question another way: while no policy exists in either scope, every mmap_declare reply carries a note telling the assistant to ask you. That note goes quiet for good — in every project — the moment you have answered anywhere.

Structural invariants enforced by the tools: layers form a total order by rank (an integer in 0..99, 0 = bottom, unique per map); every node lives in exactly one layer; edges point strictly downward — which makes the graph acyclic by construction; nodes may not depend on same-layer siblings (if A needs sibling B, either B is really a lower concept or A and B are one node); a group clusters nodes within one band; and node ids and group ids share one namespace — an id names a node or a group, never both, because both render as boxes and one id must mean one box.

Development

See contributing and the project structure, branch and recovery guide.

npm ci
npm run verify

Use Node.js 22.12+ for development. verify runs typecheck, test, build (bundles dist/ and emits lib/ with declarations), check:package, check:codex, and check:release. These check npm entrypoints, the Codex package and both installable editions, including their MCP handshake.

The repo is itself layered bottom-up, and each layer has its spec:

Layer

Code

Spec

Owns

0 domain

src/domain/

ops.test.ts

the map value, structural invariants, pure ops

1 format

src/store/format.ts

store.test.ts

the state-file format: replay-validated parse, serialize — I/O-free

1 store

src/store/store.ts

store.test.ts, atomic-save.test.ts

atomic state-file persistence on Node

1 semantics

src/semantics/

semantics.test.ts

medium-neutral view semantics: zoom ladder, group aggregation, page-set rules, sequence flip, the shared glyph vocabulary

2 apply

src/server/apply.ts

apply.test.ts

tool inputs → transactional op sequences

3 server

src/server/server.ts

server.test.ts, save-failure.test.ts

the eight MCP tools over stdio

4 render

src/render/

render.test.ts, routing.test.ts

the ASCII renderer and its wire routing

4 pane

src/watch/

watch.test.ts, pane-state.test.ts, input.test.ts

the polling pane: page set, input parsing, panel and chrome

— launchers

scripts/

open-pane.test.mjs, codex-register.test.mjs

plain-node entry points

— packaging

package.json

tests/lockfile.test.ts, browser-safe.test.ts

what ships, and to whom

dist/ is committed deliberately: plugin installation clones this repo and runs nothing, so entry points ship bundled. CI diffs the committed dist/ against a fresh build, so a source change that forgets the rebuild fails.

Library

The lower layers are also a library (npm run build emits lib/ with type declarations; npm packs it). Subpath exports mirror the source:

Subpath

Contents

Browser-safe

mellos-mapping/domain/types

the map value, ids, ranks, statuses, errors

yes

mellos-mapping/domain/ops

pure operations over a map

yes

mellos-mapping/format

state-file parse / serialize, page ids

yes

mellos-mapping/semantics

zoom ladder, group aggregation, focus and page-set rules, the shared glyph vocabulary

yes

mellos-mapping/render

the terminal renderer

gated the same way (it is pure), but its output is character cells — for terminal hosts

mellos-mapping/store

filesystem persistence, atomic saves, focus file, policy

Node only

mellos-mapping/server

the bundled MCP server entry — a spawn target, not a module to import

Node only

Browser-safe means no Node builtins anywhere in the import closure, gated by a test, so a graphical client (a web panel, an editor view) can parse state files and reuse the exact aggregation, zoom and glyph semantics the terminal pane draws with.

Optional GitHub Star reminder

npm/npx installations may show one small, dismissible reminder after at least 7 days and successful map viewing on 3 different UTC dates. Web viewers show it inline without taking focus; a native interactive terminal shows it only after a successful viewing session exits. It is never added to MCP replies, AI prompts, install logs, CI or piped output. Plugin editions and source checkouts are excluded.

The reminder is claimed once per user, across projects, versions and installs. The Star button opens GitHub in the system's default browser, keeping its existing sign-in session. A failed launch leaves the notice open with a copy-address option. Closing it, following its Star link, or simply leaving the session means it will not appear again. To suppress it before it appears, set MELLOS_MAPPING_NO_STAR=1 in the environment of the viewer/MCP process. Only the first-use time, last UTC day, a capped day count and the one-time flag are stored in ~/.mellos/support/star-reminder.json; nothing is uploaded and GitHub is contacted only when the user follows the link. Unreadable settings or a busy store silently skip the reminder.

Community

This project takes part in and endorses the LINUX DO community.

License

MIT

Available Tools

8 tools
mmap_batchCommit a single-page transactionA

Atomically combine additions, updates and removals on ONE page. Checks the final graph, so a coordinated move or edge replacement needs no intermediate saves. Read IDs and revision with mmap_read first. Cross-page deletion is excluded.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNopage (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort.
operationsYes
expectedRevisionNoRevision from mmap_read; absent requires a new page. A stale revision returns CONFLICT.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It discloses that the tool is atomic, that it validates the final graph before committing, and that it can handle coordinated changes without intermediate saves. The 'Cross-page deletion is excluded' constraint is also useful behavioral context. It could go further by describing persistence, reversibility, or exact return behavior, but what is provided is substantially more than a bare mutation statement.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three compact sentences with no wasted words. The purpose is front-loaded, the key behavioral benefit follows immediately, and the prerequisite and exclusion are stated last. Every sentence earns its place and none merely restates the tool name or title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex tool with a large operation schema, the description covers the critical contextual pieces: atomicity, single-page scope, final-graph validation, the need to read IDs/revision first, and the cross-page deletion exclusion. The extensive schema handles per-operation details. It is not a 5 because there is no output schema and the description does not mention what the tool returns or how conflicts surface beyond the schema's existing `CONFLICT` note.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 67%, with page and expectedRevision already documented in detail. The tool description adds real semantic value beyond the schema by explaining that `operations` combine additions, updates, and removals, and by tying `expectedRevision` to a concrete source ('Read IDs and revision with mmap_read first'). This helps the agent populate both parameters correctly without repeating the verbose schema details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Atomically combine additions, updates and removals on ONE page.' The title 'Commit a single-page transaction' reinforces this. It is clearly distinct from the single-operation sibling tools (mmap_declare, mmap_update, mmap_remove) because it emphasizes atomicity and the final-graph check, and the boundary is further sharpened by 'Cross-page deletion is excluded.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives an explicit precondition: 'Read IDs and revision with mmap_read first,' naming the sibling tool the agent must call beforehand. It also explains when this tool is valuable—coordinated moves or edge replacements become safe without intermediate saves—and states a clear exclusion: cross-page deletion is not supported. It falls just short of a 5 because it never explicitly contrasts this with the single-op sibling tools for simpler one-operation changes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mmap_declareDeclare map structureA

Grow the Mellos map: set the title and diagram kind, add layer bands, lanes and groups (labeled subsystems within ONE band — declare them when a single band grows crowded, roughly five or more nodes in that band; a group must be a strict subset of its band, and a map spread thin across many bands needs none), add nodes, add dependency edges. Declare the missing design after reading existing pages with mmap_read; reuse verified nodes. Edges must point strictly downward (a node may only use nodes on lower layers); the batch is all-or-nothing. Title and kind can also be changed with mmap_update; this legacy form remains supported. Revising what already exists (moving, renaming, relabeling, clearing) is mmap_update.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNodiagram kind. dev (default) = the live progress ledger with status skins. The rest are documentation diagrams rendered neutrally: architecture (layered components; also fits call graphs and module dependencies), dataflow (source→transform→sink, stages as layers), behavior-tree (root on top, leaves at the bottom; also fits mind maps and WBS), sequence (classic call/return: rank = time step with rank 0 = EARLIEST, drawn top-down; declare lanes as participants and make every call AND every return its own event node in the acting participant's lane, edges labeled with the message). State machines are unsupported: cycles cannot enter a Mellos map.
pageNopage (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort.
edgesNo
lanesNovertical columns crossing all bands; declaration order = left-to-right
nodesNo
titleNomap title, e.g. the feature being built; null removes it
groupsNo
layersNo
contextNo
expectedRevisionNoRevision from mmap_read; absent requires a new page. A stale revision returns CONFLICT.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description takes on the behavioral burden and does substantial work: it discloses the strict downward-edge rule, the all-or-nothing batch semantics, and the strict-subset rule for groups. It does not mention response/conflict behavior, but the transaction and constraint disclosures go well beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the purpose and operates at the right level of abstraction; the parenthetical group rule is dense but directly actionable. No sentences repeat schema boilerplate.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter, four-array tool with no annotations and no output schema, this description explains workflow, scope split with mmap_update, and critical constraints, while the schema covers parameter details. The main missing piece is return/conflict behavior, but the rest is unusually complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already describes most parameters well, and the description adds helpful operational semantics: when groups are warranted (five or more nodes in a band), that they must be strict subsets, and that edges must point strictly downward. This adds usable meaning without re-listing every field.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a concrete verb ('Grow') and lists the exact map objects it creates (title, kind, bands, lanes, groups, nodes, edges). It also contrasts with mmap_update, saying revision of existing content is update, so the tool's scope is unambiguous next to siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly tells the agent to read with mmap_read before declaring and to reuse verified nodes. It names mmap_update as the alternative for revising existing content and even notes that title/kind changes are supported here only as a legacy path, giving both a primary and exclusionary usage signal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mmap_openOpen the map paneA

For automatic display beside the current ChatGPT desktop conversation in Codex mode, use surface: "web-terminal", then call open_in_codex with the returned browser hostOpen object. No paste or Computer Use is needed. For the native host terminal, use surface: "codex-terminal": prepare absolute watcher commands for the current project, then ask the host to open its right terminal. This does not launch the watcher or type into that terminal. Agent exec PTYs cannot be attached using their numeric session ids. For a document panel, use surface: "markdown": generate MD + SVG files, enable automatic preview updates after successful map writes, then use the HOST file-opening tool to display the returned absolute Markdown path on the right of the current conversation. Generated does not mean visible: this server cannot open or observe the desktop side panel. For interactive maps, choose surface: "web": start or reuse a project-local web viewer and pass the returned URL to the host browser-opening tool. Markdown and terminal remain available. The default surface is "terminal", preserving the terminal workflow. Put the live map on the user's screen: a terminal pane beside this conversation that redraws on every write. Call it whenever a result says pane: CLOSED — and do NOT ask permission first, because a user who has set a mapping policy has already said they want to see the map. With a pane already open this RETARGETS it to page instead of opening a second one, so it is also how you show the user a particular page when they ask for one. It never closes a pane: taking the map off the screen belongs to the user (the q key in the pane, or typing mmap in a terminal). The reply says whether a pane actually reported itself in afterwards, not merely that a command was run. Automatic terminal opening supports Windows Terminal and tmux on Linux/macOS. omp (Oh My Pi) has no side panel of its own: there the routes are this same terminal pane (a Windows Terminal split, or a tmux split on Linux/macOS) and the web viewer, whose URL the session opens with its own browser tool. If opening fails, relay the reason and copyable command; retry only after the environment changes or the user asks.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNopage to show first — the page THIS effort lives on, the same slug you pass to the other tools. Omit only for the default page: without it a fresh pane opens on whichever page was written last, which after a gap is rarely the one under discussion.
windowNoopen the map in its own "mellos-mapping" window (a new tmux window on Linux/macOS) instead of splitting this conversation's window. Pass it only when the user asked for the map separate (a second monitor, a small screen); the split is the default because the map is meant to sit beside what it describes.
surfaceNoweb-terminal = automatically started mmap terminal in a local browser page; codex-terminal = prepare a command for the desktop host terminal; web = local browser viewer; markdown = MD/SVG; terminal = Windows Terminal or tmux launcher (default)

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so richly. It discloses that opening is not visibility (`Generated does not mean visible: this server cannot open or observe the desktop side panel`), that it never closes a pane, that the reply indicates whether a pane actually reported itself in, that agent exec PTYs cannot be attached by id, and that retry should only happen after environment changes or user request.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but almost every sentence carries operational value—surface routing, retargeting semantics, failure policy, platform support. It is organized by surface then general behavior, though it leads with the web-terminal edge case rather than the default terminal workflow, so it is not perfectly front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with three optional parameters, no output schema, and no annotations, the description covers invocation triggers, parameter semantics, failure handling, retry rules, supported terminal environments, and limitations. It gives enough context for an agent to decide when to call it and what to expect from the reply.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description adds significant meaning beyond the schema: it explains the page slug convention and the pitfall of omitting it (opens last-written page), constrains window to explicit user requests for a separate window, and elaborates each surface enum value into concrete workflows and limits. This materially helps correct invocation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a clear verb and resource: it opens or retargets the map pane beside the conversation and can show a specific page. It distinguishes itself from siblings by detailing surfaces, the `pane: CLOSED` trigger, and retargeting behavior, so an agent can tell it apart from `mmap_view` or `mmap_update` without guessing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use guidance: call whenever a result says `pane: CLOSED`, do not ask permission first, and use it to show a requested page when a pane is already open. It also maps each surface to a specific scenario — web-terminal for Codex desktop, codex-terminal for the native host terminal, markdown for document panels, and web for interactive maps — with clear exclusions like not launching the watcher or typing into the terminal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mmap_readRead and resume saved mapsA

Read existing pages before creating a map. Returns structured IDs, revisions and bounded results. pages lists summaries; map reads page metadata/context; nodes/edges/layers/groups/lanes read editable records; neighborhood reads related nodes; changes compares saved source hashes with local files. New conversations and compacted context should resume the existing effort. mmap_view remains the picture.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoExact ID; missing returns NOT_FOUND. Edge IDs use from->to; default page ID is _default.
idsNo
laneNofilter by lane
pageNopage (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort.
depthNo
groupNofilter by group
layerNofilter by layer
limitNo
queryNo
cursorNoOpaque cursor; reuse the same query. Changes return CONFLICT instead of skipping records.
fieldsNo
statusNo
resourceNo
directionNo
ifRevisionNoRevision from mmap_read; absent requires a new page. A stale revision returns CONFLICT.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral disclosure burden and does substantial work: it says results are bounded, pages return summaries, map returns metadata/context, and changes compares saved hashes with local files. It also communicates resumption behavior. It does not cover error/conflict semantics or pagination mechanics in detail, but the read-only nature and result shape are conveyed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the key directive and uses a compact structured list to explain resource behaviors. There is no filler; the only slightly obscured line is 'mmap_view remains the picture,' but it is short and not bloating.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a 15-parameter tool with no output schema, and the description gives a useful high-level map of resource behaviors and resume guidance. It does not describe output shape, pagination/conflict behavior, or how filters combine, so it is adequate but not complete for fully autonomous invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 47%, and the description compensates mainly for the resource parameter by explaining what each resource returns. It adds little meaning for filter/pagination parameters such as limit, cursor, status, direction, depth, and fields, leaving a significant portion of the 15 parameters semantically under-described.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly frames the tool as the read/resume operation: 'Read existing pages before creating a map' and 'Returns structured IDs, revisions and bounded results.' It also enumerates resource-specific reads (pages, map, nodes/edges/layers, neighborhood, changes), which makes the core purpose concrete. It does not explicitly contrast with siblings beyond a cryptic nod to mmap_view, so it lacks full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear usage context: read before creating a map, and resume existing effort for new conversations or compacted context. It also distinguishes read intent from viewing via 'mmap_view remains the picture.' It stops short of fully explicit when-not-to-use guidance or naming alternatives like mmap_open.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mmap_removeRevise the mapA

Remove edges, nodes, groups and empty layer bands (in that order, all-or-nothing). Removing a node also removes every edge touching it; removing a group merely ungroups its members. Use when the ghost design turns out wrong — the map is a hypothesis, revising it is honest work. pages is the other scale: it DELETES whole page files, so a finished effort can be cleaned up instead of accumulating tabs forever. A bare {pages: ["slug"]} with no other field is the normal form; combined with map edits, the edits are applied first and the pages are deleted after. The deletion is permanent and cannot be undone, so delete only pages whose effort is over — and only ever with the user behind it. An unknown slug is refused with the project's real page list (naming a page that does not exist is a typo, not a request). The default page has no slug and is not deletable here. A node elsewhere still pointing at a deleted page with submap stays legal — a submap reference has no existence invariant — but it has nowhere to dive until the page comes back.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNopage (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort.
edgesNo
lanesNo
nodesNo
pagesNopages to delete entirely, after this call's map edits; permanent
groupsNo
layersNo
deletePageNoDelete the page targeted by page, including the default page; cannot be combined with other edits.
referencesNoFor deletePage: reject inbound submap references by default, or explicitly keep them.
expectedRevisionNoRevision from mmap_read; absent requires a new page. A stale revision returns CONFLICT.

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully carries the behavioral burden and does so impressively. It discloses ordering, all-or-nothing semantics, cascading edge deletion, ungrouping behavior, permanence of page deletion, application order for edits vs page deletion, unknown-slug refusal, and the lack of an existence invariant for submap references.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but almost every sentence carries behavioral or safety-critical information. It is front-loaded with the core action and ordering, then expands to page deletion and edge cases. The phrase "revising it is honest work" is slightly stylistic but not harmful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no annotations and no output schema, the description is remarkably complete. It covers operation order, atomicity, cascades, deletion permanence, user consent, error behavior for unknown slugs, default-page handling, and dangling submap references. An agent has enough context to invoke this tool safely and correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds important meaning beyond the schema, especially for `pages` — permanent deletion, applied after edits, and default-page non-deletability via slug. It also clarifies node/edge/group/layer semantics. Some parameters like `expectedRevision` and `references` are left to the schema, so it is not exhaustive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly names the action and resource: "Remove edges, nodes, groups and empty layer bands" and distinguishes map-level edits from page-file deletion via `pages`. It does not explicitly compare itself to sibling tools like `mmap_update`, so it falls slightly short of full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear when-to-use signal: "Use when the ghost design turns out wrong." It also advises that page deletion should happen "only ever with the user behind it." However, it does not explicitly contrast with `mmap_update` or state when edits should go there instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mmap_setupConfigure when maps openA

Get or set the mapping policy — WHEN the assistant opens a Mellos map. Call with no arguments to read it: the reply names the policy chosen for the USER (every project), the one this PROJECT overrides it with if any, and which of them is in effect. If it reports "not set", ask the USER to choose (never pick for them): always = map every structured task — workflows, designs, architecture, technical dependencies; complex = map only medium or complex tasks — several modules, a new subsystem, roughly an hour or more; on-request = map only when the user explicitly asks. Then call again with their choice to persist it. It defaults to user scope, which is the normal one — the question is about how someone works, so it is asked once ever, not once per repository. Pass scope: "project" only when the user wants THIS project to differ from that habit. The policy guides you; it never blocks the tools, and an explicit user request for a map always wins.

ParametersJSON Schema
NameRequiredDescriptionDefault
scopeNowhere to record the choice: "user" (default) applies to every project this user opens; "project" overrides that for this project alone. Ignored when reading.
policyNothe user's choice to persist; omit to read the current policy

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden: it explains read output, persistence behavior, the user-scope default, and the non-blocking nature of the policy. This is detailed behavioral disclosure for a configuration tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but purposeful; each section maps to a decision the agent must make. It is front-loaded with the core purpose and then expands into needed operational detail, though it could be tightened slightly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has two optional parameters and no output schema, and the description covers reading, writing, defaults, the 'not set' error case, and fallback behavior. Given its simple parameter surface, nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds substantial meaning: it defines each policy value with concrete examples, clarifies the default scope, and reiterates that scope is ignored when reading. This goes well beyond the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Get or set the mapping policy — WHEN the assistant opens a Mellos map,' naming a specific verb pair and resource. It clearly distinguishes this configuration tool from the sibling open/read/declare/remove tools by focusing on policy rather than map content.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit call patterns: no arguments to read, then call again with the chosen policy to persist; scope: 'project' only when the user wants a per-project override. It also says exactly what to do on 'not set' — ask the user, never pick for them — and warns the policy never blocks explicit map requests.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mmap_updateRecord progress and revise the mapA

The revision tool, all-or-nothing. Record progress on nodes: in-progress when starting a node (the pane spins), done with evidence when its verification passes, regressed with evidence when a done node breaks. Revise what the ghost design got wrong: move a node to another band, join or leave a group or lane, rename a band (or re-rank it, which reorders the whole map), relabel a group or a lane. Every clearable field takes null to empty it — that is how a field is cleared, never an empty string. Bands, groups and lanes are applied before the node updates, and within one node update layer moves the node before its other fields. The map is a ledger: report honestly, it never blocks you.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNodiagram kind. dev (default) = the live progress ledger with status skins. The rest are documentation diagrams rendered neutrally: architecture (layered components; also fits call graphs and module dependencies), dataflow (source→transform→sink, stages as layers), behavior-tree (root on top, leaves at the bottom; also fits mind maps and WBS), sequence (classic call/return: rank = time step with rank 0 = EARLIEST, drawn top-down; declare lanes as participants and make every call AND every return its own event node in the acting participant's lane, edges labeled with the message). State machines are unsupported: cycles cannot enter a Mellos map.
pageNopage (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort.
edgesNo
lanesNorelabel existing lanes; order and membership are untouched
titleNoMap title; null clears
groupsNorelabel or move a group; final membership must match its layer
layersNorename and/or re-rank existing bands; an item must carry a name, a rank, or both
contextNo
updatesNo
laneOrderNoEvery lane exactly once, in display order.
expectedRevisionNoRevision from mmap_read; absent requires a new page. A stale revision returns CONFLICT.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden, and it does substantial work: it discloses the all-or-nothing transactional nature, the ordering semantics ('Bands, groups and lanes are applied before the node updates', 'layer moves the node before its other fields'), the null-clears convention, the ledger honesty principle, and the fact that the map never blocks the reporter. It also discloses that unknown kinds are kept and shown in the detail panel. This is rich behavioral context beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well-structured: it front-loads the tool's identity and core purpose, then enumerates operations in a logical order (progress, revision, structural moves, clearing, ordering, ledger principle). Every sentence carries information; there is no filler. It is longer than the ideal, but the tool is genuinely complex with 11 parameters and multiple operation families, so the length is justified.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex 11-parameter mutation tool with no annotations and no output schema, the description covers a great deal: the all-or-nothing behavior, ordering semantics, null-clearing, the ledger principle, and the unsupported state-machine case. It does not explicitly describe return values or error behavior beyond the schema's CONFLICT mention, and it does not enumerate every parameter's purpose, but the schema covers 73% of parameters and the description adds the cross-cutting semantics that matter most.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 73%, so the schema already documents most parameters. The description adds meaningful semantics beyond the schema: the null-clears convention for every clearable field, the ordering of band/group/lane application before node updates, the layer-moves-first rule within a node update, and the 'never an empty string' rule. These are exactly the kind of cross-parameter semantics that the schema's per-field descriptions cannot convey. It does not fully compensate for the 27% undocumented gap, but the added value is substantial.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear verb and resource ('revision tool, all-or-nothing') and enumerates the full scope: recording node progress, revising ghost-design mistakes, moving/renaming bands/groups/lanes, and clearing fields with null. It distinguishes itself from siblings by framing itself as the revision/update counterpart to mmap_declare and mmap_read, and the 'all-or-nothing' transactional note adds a specific behavioral identity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives strong context for when to use this tool: record progress, revise ghost design, move/rename bands/groups/lanes, clear fields. It also gives an explicit exclusion ('State machines are unsupported') and a strong directive ('Read existing pages with mmap_read first; reuse the same page for continued work'). It does not explicitly name sibling alternatives like mmap_declare or mmap_remove, but the usage context is clear enough that an agent can route correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mmap_viewView the current mapA

Render the current Mellos map as monochrome text — the same picture the split-pane watcher shows live. Use it to check the map state or to show it inline in conversation. Every response ends with a pages: line naming the pages this project actually has and which one you are looking at, so this is also how you discover whether a map exists at all and under which slugs — never probe the files.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNopage (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort.
zoomNozoom ladder: 1 = detail (notes unfold), 0 = standard (default), -1..-3 = scaled down, -4 = overview glyphs

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It discloses the output style (monochrome text, same as the live watcher), the guaranteed `pages:` trailing line, and that it can reveal map existence. It stops short of explicitly stating it has no side effects or describing missing-map behavior, but 'view/render' strongly implies read-only.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose, then usage and behavioral notes. The split-pane watcher comparison and the `pages:` detail are informative rather than padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only view tool with no output schema, the description covers the return format (text plus `pages:` line), when to use it, and its discovery role. It could add explicit no-mutation wording or missing-map behavior, but nothing critical is absent for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both `page` and `zoom` have detailed inline descriptions, so the tool description adds no additional parameter semantics. The baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Render'), resource ('current Mellos map'), and output format ('monochrome text'), and clarifies its secondary role in discovering pages and slugs. It doesn't explicitly contrast with sibling mmap_read, but the action is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use it: to check map state, show inline in conversation, and discover whether a map exists and under which slugs. It also provides an exclusion ('never probe the files') and, in the page parameter, directs reading existing pages with mmap_read first.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 8 tool updatesv0.26.0
    • Addedmmap_batch
    • Changedmmap_declare44 fields changed
      • addedInput schema / properties / context
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "next": {
        +      "description": "Next actions for resuming this effort",
        +      "maxLength": 2000,
        +      "minLength": 1,
        +      "pattern": "^[^\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f]*$",
        +      "type": "string"
        +    },
        +    "summary": {
        +      "description": "Concise purpose and confirmed decisions",
        +      "maxLength": 2000,
        +      "minLength": 1,
        +      "pattern": "^[^\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f]*$",
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / edges / items / properties / label / minLength
        Added value: +1
      • addedInput schema / properties / edges / items / properties / label / pattern
        Added value: +"^[^\\u0000-\\u001f\\u007f-\\u009f]*$"
      • addedInput schema / properties / expectedRevision
        Added value: +{
        +  "description": "Revision from mmap_read; absent requires a new page. A stale revision returns CONFLICT.",
        +  "pattern": "^(?:[a-f0-9]{64}|absent)$",
        +  "type": "string"
        +}
      • removedInput schema / properties / groups / items / properties / id / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / groups / items / properties / id / description
        Added value: +"stable kebab-case identifier of the group"
      • addedInput schema / properties / groups / items / properties / id / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / groups / items / properties / id / type
        Added value: +"string"
      • addedInput schema / properties / groups / items / properties / label / pattern
        Added value: +"^[^\\u0000-\\u001f\\u007f-\\u009f]*$"
      • removedInput schema / properties / lanes / items / properties / id / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / lanes / items / properties / id / description
        Added value: +"stable kebab-case identifier of the lane"
      • addedInput schema / properties / lanes / items / properties / id / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / lanes / items / properties / id / type
        Added value: +"string"
      • addedInput schema / properties / lanes / items / properties / label / pattern
        Added value: +"^[^\\u0000-\\u001f\\u007f-\\u009f]*$"
      • removedInput schema / properties / layers / items / properties / id / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / layers / items / properties / id / description
        Added value: +"stable kebab-case identifier of the band"
      • addedInput schema / properties / layers / items / properties / id / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / layers / items / properties / id / type
        Added value: +"string"
      • addedInput schema / properties / layers / items / properties / name / pattern
        Added value: +"^[^\\u0000-\\u001f\\u007f-\\u009f]*$"
      • changedInput schema / properties / layers / items / properties / rank / description
        Previous value: -"0 = bottom / most primitive; must be unique"New value: +"an integer in 0..99, 0 = bottom / most primitive; must be unique among the map's bands"
      • addedInput schema / properties / nodes / items / properties / detail / minLength
        Added value: +1
      • addedInput schema / properties / nodes / items / properties / detail / pattern
        Added value: +"^[^\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f]*$"
      • addedInput schema / properties / nodes / items / properties / evidence
        Added value: +{
        +  "description": "how an already-verified node was verified; for regressed: what broke. Declaring a node straight to done needs it as much as updating one does.",
        +  "maxLength": 200,
        +  "minLength": 1,
        +  "pattern": "^[^\\u0000-\\u001f\\u007f-\\u009f]*$",
        +  "type": "string"
        +}
      • removedInput schema / properties / nodes / items / properties / group / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / nodes / items / properties / group / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / nodes / items / properties / group / type
        Added value: +"string"
      • removedInput schema / properties / nodes / items / properties / id / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / nodes / items / properties / id / description
        Added value: +"stable kebab-case identifier of the node"
      • addedInput schema / properties / nodes / items / properties / id / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / nodes / items / properties / id / type
        Added value: +"string"
      • addedInput schema / properties / nodes / items / properties / label / pattern
        Added value: +"^[^\\u0000-\\u001f\\u007f-\\u009f]*$"
      • removedInput schema / properties / nodes / items / properties / lane / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / nodes / items / properties / lane / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / nodes / items / properties / lane / type
        Added value: +"string"
      • addedInput schema / properties / nodes / items / properties / sources
        Added value: +{
        +  "description": "Optional source files and verified SHA256 baselines. mmap_read changes checks them without rescanning the repository.",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "path": {
        +        "maxLength": 1024,
        +        "type": "string"
        +      },
        +      "sha256": {
        +        "pattern": "^[a-f0-9]{64}$",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "path"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 100,
        +  "type": "array"
        +}
      • changedInput schema / properties / nodes / items / properties / status / description
        Previous value: -"defaults to planned"New value: +"defaults to planned. planned = ghost on the map; in-progress = spinner; done = verified; regressed = was done, now broken"
      • removedInput schema / properties / nodes / items / properties / submap / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / nodes / items / properties / submap / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / nodes / items / properties / submap / type
        Added value: +"string"
      • changedInput schema / properties / page / description
        Previous value: -"page (parallel map) this call targets; omit for the default page. One effort = one page: start a NEW effort on its own page named after the effort, so concurrent sessions never write over each other and the pane can switch between pages."New value: +"page (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort."
      • addedInput schema / properties / title / anyOf
        Added value: +[
        +  {
        +    "description": "map title, e.g. the feature being built; null removes it",
        +    "maxLength": 120,
        +    "minLength": 1,
        +    "pattern": "^[^\\u0000-\\u001f\\u007f-\\u009f]*$",
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / title / description
        Previous value: -"map title, e.g. the feature being built"New value: +"map title, e.g. the feature being built; null removes it"
      • removedInput schema / properties / title / maxLength
        Removed value: -120
      • removedInput schema / properties / title / type
        Removed value: -"string"
    • Addedmmap_open
    • Addedmmap_read
    • Changedmmap_remove24 fields changed
      • addedInput schema / properties / deletePage
        Added value: +{
        +  "description": "Delete the page targeted by page, including the default page; cannot be combined with other edits.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expectedRevision
        Added value: +{
        +  "description": "Revision from mmap_read; absent requires a new page. A stale revision returns CONFLICT.",
        +  "pattern": "^(?:[a-f0-9]{64}|absent)$",
        +  "type": "string"
        +}
      • removedInput schema / properties / groups / description
        Removed value: -"groups to remove; members stay, merely ungrouped"
      • removedInput schema / properties / groups / items / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / groups / items / description
        Added value: +"id of the group to remove; members stay, merely ungrouped"
      • addedInput schema / properties / groups / items / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / groups / items / type
        Added value: +"string"
      • removedInput schema / properties / lanes / description
        Removed value: -"lanes to remove; members stay, merely off-lane"
      • removedInput schema / properties / lanes / items / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / lanes / items / description
        Added value: +"id of the lane to remove; members stay, merely off-lane"
      • addedInput schema / properties / lanes / items / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / lanes / items / type
        Added value: +"string"
      • removedInput schema / properties / layers / description
        Removed value: -"bands to remove; must be empty of nodes and groups"
      • removedInput schema / properties / layers / items / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / layers / items / description
        Added value: +"id of the band to remove; it must hold no nodes and no groups"
      • addedInput schema / properties / layers / items / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / layers / items / type
        Added value: +"string"
      • removedInput schema / properties / nodes / items / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / nodes / items / description
        Added value: +"id of the node to remove, with every edge touching it"
      • addedInput schema / properties / nodes / items / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / nodes / items / type
        Added value: +"string"
      • changedInput schema / properties / page / description
        Previous value: -"page (parallel map) this call targets; omit for the default page. One effort = one page: start a NEW effort on its own page named after the effort, so concurrent sessions never write over each other and the pane can switch between pages."New value: +"page (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort."
      • addedInput schema / properties / pages
        Added value: +{
        +  "description": "pages to delete entirely, after this call's map edits; permanent",
        +  "items": {
        +    "description": "slug of a page whose WHOLE map file is deleted — the page and everything drawn on it. Not the page this same call targets with `page`.",
        +    "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / references
        Added value: +{
        +  "description": "For deletePage: reject inbound submap references by default, or explicitly keep them.",
        +  "enum": [
        +    "reject",
        +    "keep"
        +  ],
        +  "type": "string"
        +}
    • Addedmmap_setup
    • Changedmmap_update33 fields changed
      • addedInput schema / properties / context
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "next": {
        +          "description": "Next actions for resuming this effort",
        +          "maxLength": 2000,
        +          "minLength": 1,
        +          "pattern": "^[^\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f]*$",
        +          "type": "string"
        +        },
        +        "summary": {
        +          "description": "Concise purpose and confirmed decisions",
        +          "maxLength": 2000,
        +          "minLength": 1,
        +          "pattern": "^[^\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f]*$",
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedInput schema / properties / edges
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "from": {
        +        "description": "the node that USES the other (must live on a higher layer)",
        +        "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +        "type": "string"
        +      },
        +      "label": {
        +        "anyOf": [
        +          {
        +            "description": "New edge label; null clears",
        +            "maxLength": 80,
        +            "minLength": 1,
        +            "pattern": "^[^\\u0000-\\u001f\\u007f-\\u009f]*$",
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "description": "New edge label; null clears"
        +      },
        +      "newFrom": {
        +        "description": "replacement consumer",
        +        "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +        "type": "string"
        +      },
        +      "newTo": {
        +        "description": "replacement dependency",
        +        "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +        "type": "string"
        +      },
        +      "to": {
        +        "description": "the node being used (must live on a strictly lower layer)",
        +        "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "from",
        +      "to"
        +    ],
        +    "type": "object"
        +  },
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / expectedRevision
        Added value: +{
        +  "description": "Revision from mmap_read; absent requires a new page. A stale revision returns CONFLICT.",
        +  "pattern": "^(?:[a-f0-9]{64}|absent)$",
        +  "type": "string"
        +}
      • addedInput schema / properties / groups
        Added value: +{
        +  "description": "relabel or move a group; final membership must match its layer",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "description": "id of the group to revise",
        +        "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +        "type": "string"
        +      },
        +      "label": {
        +        "description": "new subsystem name",
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "pattern": "^[^\\u0000-\\u001f\\u007f-\\u009f]*$",
        +        "type": "string"
        +      },
        +      "layer": {
        +        "description": "new layer; move members in the same batch",
        +        "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "id"
        +    ],
        +    "type": "object"
        +  },
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / kind
        Added value: +{
        +  "description": "diagram kind. dev (default) = the live progress ledger with status skins. The rest are documentation diagrams rendered neutrally: architecture (layered components; also fits call graphs and module dependencies), dataflow (source→transform→sink, stages as layers), behavior-tree (root on top, leaves at the bottom; also fits mind maps and WBS), sequence (classic call/return: rank = time step with rank 0 = EARLIEST, drawn top-down; declare lanes as participants and make every call AND every return its own event node in the acting participant's lane, edges labeled with the message). State machines are unsupported: cycles cannot enter a Mellos map.",
        +  "enum": [
        +    "dev",
        +    "architecture",
        +    "dataflow",
        +    "behavior-tree",
        +    "sequence"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / laneOrder
        Added value: +{
        +  "description": "Every lane exactly once, in display order.",
        +  "items": {
        +    "description": "existing lane id",
        +    "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +    "type": "string"
        +  },
        +  "maxItems": 100,
        +  "type": "array"
        +}
      • addedInput schema / properties / lanes
        Added value: +{
        +  "description": "relabel existing lanes; order and membership are untouched",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "description": "id of the lane to relabel",
        +        "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +        "type": "string"
        +      },
        +      "label": {
        +        "description": "new column name",
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "pattern": "^[^\\u0000-\\u001f\\u007f-\\u009f]*$",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "id",
        +      "label"
        +    ],
        +    "type": "object"
        +  },
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / layers
        Added value: +{
        +  "description": "rename and/or re-rank existing bands; an item must carry a name, a rank, or both",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "description": "id of the band to revise",
        +        "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +        "type": "string"
        +      },
        +      "name": {
        +        "description": "new display name of the band",
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "pattern": "^[^\\u0000-\\u001f\\u007f-\\u009f]*$",
        +        "type": "string"
        +      },
        +      "rank": {
        +        "description": "an integer in 0..99, 0 = bottom / most primitive; must be unique among the map's bands",
        +        "maximum": 99,
        +        "minimum": 0,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "id"
        +    ],
        +    "type": "object"
        +  },
        +  "minItems": 1,
        +  "type": "array"
        +}
      • changedInput schema / properties / page / description
        Previous value: -"page (parallel map) this call targets; omit for the default page. One effort = one page: start a NEW effort on its own page named after the effort, so concurrent sessions never write over each other and the pane can switch between pages."New value: +"page (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort."
      • addedInput schema / properties / title
        Added value: +{
        +  "anyOf": [
        +    {
        +      "description": "Map title; null clears",
        +      "maxLength": 120,
        +      "minLength": 1,
        +      "pattern": "^[^\\u0000-\\u001f\\u007f-\\u009f]*$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Map title; null clears"
        +}
      • addedInput schema / properties / updates / items / properties / detail / anyOf
        Added value: +[
        +  {
        +    "description": "design notes shown in the pane detail panel: responsibility, contract, key decisions; null clears them",
        +    "maxLength": 600,
        +    "minLength": 1,
        +    "pattern": "^[^\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f]*$",
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / updates / items / properties / detail / description
        Previous value: -"design notes shown in the pane detail panel: responsibility, contract, key decisions"New value: +"design notes shown in the pane detail panel: responsibility, contract, key decisions; null clears them"
      • removedInput schema / properties / updates / items / properties / detail / maxLength
        Removed value: -600
      • removedInput schema / properties / updates / items / properties / detail / type
        Removed value: -"string"
      • addedInput schema / properties / updates / items / properties / evidence / anyOf
        Added value: +[
        +  {
        +    "description": "for done: how it was verified; for regressed: what broke; null clears it",
        +    "maxLength": 200,
        +    "minLength": 1,
        +    "pattern": "^[^\\u0000-\\u001f\\u007f-\\u009f]*$",
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / updates / items / properties / evidence / description
        Previous value: -"for done: how it was verified; for regressed: what broke"New value: +"for done: how it was verified; for regressed: what broke; null clears it"
      • removedInput schema / properties / updates / items / properties / evidence / maxLength
        Removed value: -200
      • removedInput schema / properties / updates / items / properties / evidence / type
        Removed value: -"string"
      • changedInput schema / properties / updates / items / properties / group / anyOf
        Previous value: -[
        -  {
        -    "$ref": "#/properties/page"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "description": "join this same-band group; null leaves the current group",
        +    "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedInput schema / properties / updates / items / properties / id / $ref
        Removed value: -"#/properties/page"
      • addedInput schema / properties / updates / items / properties / id / description
        Added value: +"id of the node to update"
      • addedInput schema / properties / updates / items / properties / id / pattern
        Added value: +"^[a-z0-9][a-z0-9-]{0,63}$"
      • addedInput schema / properties / updates / items / properties / id / type
        Added value: +"string"
      • changedInput schema / properties / updates / items / properties / kind / description
        Previous value: -"set the node kind; null clears it"New value: +"node kind rendered as a glyph prefix. Known: selector | sequence | parallel | decorator | condition | action (behavior trees); source | transform | sink (dataflow); service | db | queue | ui (architecture). Unknown kinds are kept and shown in the detail panel."
      • addedInput schema / properties / updates / items / properties / label / description
        Added value: +"new display label inside the box"
      • addedInput schema / properties / updates / items / properties / label / pattern
        Added value: +"^[^\\u0000-\\u001f\\u007f-\\u009f]*$"
      • changedInput schema / properties / updates / items / properties / lane / anyOf
        Previous value: -[
        -  {
        -    "$ref": "#/properties/page"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "description": "join this lane; null leaves the current lane",
        +    "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / updates / items / properties / layer
        Added value: +{
        +  "description": "move the node to this band; applied before this item's other fields, so a node can move and join a group on the new band in one item. Every edge touching it must still point strictly downward, and a grouped node may only move to its group's band.",
        +  "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / updates / items / properties / sources
        Added value: +{
        +  "anyOf": [
        +    {
        +      "description": "Optional source files and verified SHA256 baselines. mmap_read changes checks them without rescanning the repository.",
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "path": {
        +            "maxLength": 1024,
        +            "type": "string"
        +          },
        +          "sha256": {
        +            "pattern": "^[a-f0-9]{64}$",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "path"
        +        ],
        +        "type": "object"
        +      },
        +      "maxItems": 100,
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Optional source files and verified SHA256 baselines. mmap_read changes checks them without rescanning the repository."
        +}
      • changedInput schema / properties / updates / items / properties / status / description
        Previous value: -"planned = ghost on the map; in-progress = spinner; done = verified; regressed = was done, now broken"New value: +"the status to record. planned = ghost on the map; in-progress = spinner; done = verified; regressed = was done, now broken"
      • changedInput schema / properties / updates / items / properties / submap / anyOf
        Previous value: -[
        -  {
        -    "$ref": "#/properties/page"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "description": "link a child map page by slug; null unlinks it",
        +    "pattern": "^[a-z0-9][a-z0-9-]{0,63}$",
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / updates / items / properties / submap / description
        Previous value: -"link a child map page; null unlinks it"New value: +"link a child map page by slug; null unlinks it"
      • removedInput schema / required
        Removed value: -[
        -  "updates"
        -]
    • Changedmmap_view2 fields changed
      • changedInput schema / properties / page / description
        Previous value: -"page (parallel map) this call targets; omit for the default page. One effort = one page: start a NEW effort on its own page named after the effort, so concurrent sessions never write over each other and the pane can switch between pages."New value: +"page (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort."
      • changedInput schema / properties / zoom / maximum
        Previous value: -1New value: +2
  2. 4 tool updatesv0.12.0
    • First observedmmap_declare
    • First observedmmap_remove
    • First observedmmap_update
    • First observedmmap_view

TDQS

A4.3/5.0

Scored across 8 tools

Disambiguation4/5

The tools are mostly distinct: declare creates, update revises, read fetches structured data, view renders text, remove deletes, batch combines operations, open displays on screen, and setup configures policy. Minor confusion remains between mmap_read and mmap_view, and between single-operation tools versus mmap_batch, but the detailed descriptions largely resolve these boundaries.

Naming Consistency4/5

All tools share the consistent mmap_ prefix and use short command-style names such as declare, read, update, remove, and view. The pattern is mostly uniform, though mmap_batch and mmap_setup are slightly noun-like rather than clear verb_noun commands.

Tool Count5/5

Eight tools is a well-scoped count for a mapping tool: create, read, update, delete, batch, render, display, and policy configuration each earn a place. There is no obvious bloat or noticeable thinness.

Completeness5/5

The tool surface covers the full lifecycle of map pages and elements: declaring maps, reading existing state, updating and removing entities, atomic multi-operation changes, rendering views, and controlling display. Administrative concerns like cleanup and policy configuration are also addressed, leaving no major dead ends.

Maintenance

ActivityMaintained
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server that enables AI coding agents to communicate, share state, and coordinate work in real time via MCP tools or REST API.
    44 npm
    8
    MIT
  • F
    license
    B
    quality
    C
    maintenance
    MCP server that gives AI coding assistants persistent memory, structural code graph analysis, and safe multi-agent coordination, enabling them to answer architectural questions, track decisions across sessions, and coordinate safely in multi-agent workflows.
    39
    4
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for creating interactive terminal canvases (calendar, document, flight) in AI coding assistants. Supports multiple TUI frameworks and integrates with tmux.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server that analyzes codebases to provide dependency graphs, impact analysis, and file insights across 15+ programming languages, enabling AI assistants to understand project structure and navigate code efficiently.
    MIT