claude-code-plugins / atlas
AGENTS.md6 starsChanged 11 days agoMITView on GitHub
An interactive architecture map, served by Bun to the browser: a tree of nodes, drawn one container's view at a time, at any depth. A view shows the children of the open container, a container child as a box naming its own children, a leaf child as a card, the neighbours outside the container as ghosts at the edge, and one arrow per pair lifted to what it shows. ELK lays each view out in the page, libavoid routes the…
- Reads credentials
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository9 other files it gives its agents.
- AGENTS.mdAGENTS.md
- vellum/AGENTS.mdAGENTS.md
- atlas/CLAUDE.mdCLAUDE.md
- CLAUDE.mdCLAUDE.md
- vellum/CLAUDE.mdCLAUDE.md
- field-testSkill
- landSkill
- leads-gateSkill
- leads-scanSkill
The file
We split this AGENTS.md into the rules it gives an agent
2 rules. About 0 are common, 2 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 258
Every command runs from the repository root.
- Distinctive: line 423
Every view is laid out again when the drawing area's aspect moves, with the Config's ratio "screen" (a packed view aims at it and a layered …
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Atlas
An interactive architecture map, served by Bun to the browser: a tree of nodes, drawn one
container's view at a time, at any depth. A view shows the children of the open container, a
container child as a box naming its own children, a leaf child as a card, the neighbours outside
the container as ghosts at the edge, and one arrow per pair lifted to what it shows. ELK lays each
view out in the page, libavoid routes the arrows of a view with a container child from
WebAssembly, and nothing in the data has a position or a size. Open points carry threads between
the human and the agent. A mod (hooks/) serves a map folder's page on /atlas:board, hands the
human's selection in the page to the agent, and gives the agent its tools on the map.
Files
Content lives only in a map folder; the engine's modules change only for behaviour. A map folder
holds map.ts (its AtlasMap, the default export), atlas.config.ts (its Config, the default
export), threads.json (the thread of each open point, by open id), a .gitignore that lists
drafts/ and the lock and scratch files a reply killed in its write leaves beside threads.json
(a committed lock would refuse every reply on every clone), and the two files sync writes and
check compares byte for byte: atlas.d.ts, a
copy of atlas.ts its data imports its types from, and tsconfig.json, a copy of the
template's. It needs no package.json: its data imports types only. Its data files are its .ts
files but atlas.d.ts, in sub-folders too: a large map keeps each branch in parts/<branch>.ts,
which exports its node and its links with types from ../atlas.d.ts, and map.ts assembles
them (parts.integration.spec.ts holds check, fmt and the page's bundle to it). map.ts writes
its map const map = { … } as const satisfies AtlasMap; and exports it
export default map satisfies Filled<typeof map>;: from the literal types as const keeps,
Filled (atlas.ts) makes tsgo refuse an empty section label, or an empty trigger, carries
or when on a step, which check refuses too; a part
writes its node and its links as const satisfies their types. The template, the sample and
the fixtures written as literals do so. Its drafts sit in
drafts/<name>/, which its check leaves out; each holds a copy of the map's own files, a map folder
of its own.
The plugin's root holds what Claude Code loads (.claude-plugin/, hooks/, skills/), what
cli.ts copies or runs on a map folder (template/, lint/, child.bunfig.toml), the specs'
fixtures/, and src/, where every module of the engine lives. A new module goes in the folder
of its layer, never at a root, its spec beside it. platform/ is a leaf: a copy of
tools/platform/ that bun ./scripts/gates/sync-platform.ts --write writes, never edited here, and
that imports nothing of the plugin. model/ imports nothing outside itself but platform/;
inventory/ imports nothing outside itself but platform/; page/ and commands/ import
model/; the mod imports platform/pure.ts alone of it, since the other modules need Node and Bun;
server/wire.ts is the one module the page, serve.ts, cli.ts and the mod all import.
src/cli.ts the one command line of agents and skills, and of the mod's tools: new, sync,
check, fmt, reply, draft, query (one node as JSON, read from tree.ts),
inventory (cli.integration.spec.ts, on copies in temporary folders)
src/serve.ts serves one map folder's page, rebuilt and reloaded on save, answers
libavoid.wasm, threads.json and the lines a citation names
(server/source.ts), takes the panel's replies, prints the page's
selections, and with --heartbeat leaves with its parent process or a minute
after the last beat carrying its secret (serve.integration.spec.ts)
src/standalone.integration.spec.ts serves the sample from a copy of the plugin outside any repository, as an
install does
src/parts.integration.spec.ts a map assembled from parts/*.ts through check, fmt and the page's bundle
src/model/ the map and what is read from it, pure or Node-only, no browser
atlas.ts the format of a map, types only: Node (a tree, `children`), Link, Journey (a
path of the root's, in sections of steps, a step per link), AtlasMap (the
root and every link), Filled (a map written as const, its journeys' texts
that check holds named refused empty),
Config (title, language, palette, pins, packing ratio, reading direction,
tags, legend labels, panel headings, step words, sources root, work
phases); the source of a map's atlas.d.ts
folder.ts the map folder's files (loadFolder), and its labels by id, the ids a selection
may name (labelsOf, folder.spec.ts); its sources root, a draft's from the
map it drafts (sourcesRootOf); run, it prints them with the paths the map
cites (FolderLine), or refuses a folder the engine cannot draw, which
serve.ts asks before each build
settings.ts the Config with its defaults filled in, refusing what the engine cannot use,
and the palette as the page's CSS custom properties (settings.spec.ts)
drawable.ts the tree and the settings a map folder makes, or why no view can show it:
treeOf's and settingsOf's refusals, a colour outside the palette, markup a
panel would not keep
markup.ts the markup a panel keeps from a map's text (code, cite, b, i, em, strong, br,
no attribute), the rest shown as text, and the faults check and the server
refuse, by node and field (markup.spec.ts)
citations.ts a <cite>path:lines</cite> read as a citation, pure, and every citation of a
map by node and field, and every <cite> that looks like one but reads as
none (citations.spec.ts)
sources.ts the file a citation's path names under the Config's sources root, Node-only:
no absolute path, no `..`, no link out of the root; and its lines, for a
file with no NUL byte under a cap (SOURCE_CAP_BYTES for the page), bytes not
UTF-8 read as U+FFFD, read through one descriptor opened without following a
link or waiting on a FIFO, every filesystem error a refusal (sources.integration.spec.ts)
words.ts the page's own words in each language a Config picks: the dictionary
tree.ts the tree indexed for views at any depth: each node's chain from the root,
open points counted down each subtree, couplings both ways, and what stands
for a node in a container's view (a child, or a ghost); refuses what no view
can show (tree.spec.ts)
view.ts the view of any container: its children as boxes, a container child's
children as its chips; its links lifted to one arrow per pair; its outer
neighbours as ghosts in side columns; the couplings a selection outlines and
the arrows it lights; the legend lines it uses (view.spec.ts; scale.spec.ts
bounds the time of the index and a view on a map of 5,000 nodes)
cards.ts a container's leaf children side by side: a column per leaf, a row for the
leads unless none has one, then one per first element of their `io` pairs;
none for fewer than two leaves, or when no leaf has `io` (cards.spec.ts)
phases.ts what a picked work phase dims: the nodes and links of the phases after it,
a container by its own phase or, without one, once all its descendants
are, a link without a phase once an end is, an arrow once every link it
stands for is; the label of an arrow that stays, from its lit links;
whether a view draws something dimmed (phases.spec.ts)
journeys.ts a journey's steps: numbered across its sections (stepsOf), an entry
(isEntry), the nodes a section has reached (reachedBefore), the data's form
before and after a step (formBefore, formAfter), the link a step follows
(joins); what a view draws, a child, a chip or a ghost (drawnIn), and what
stands for a node there (representativeIn); the journey's host view, the
deepest that draws every end (hostView), the view a step plays in, the
host, else the deepest that draws both ends, else their lowest common
container's (playView, stepView), the steps of a section a view traces
(tracedIn), and a box's index, the steps whose two ends it holds, written
in ranges of one mark (indexOf, rangesOf) (journeys.spec.ts)
navigation.ts where the reader stands at any depth: the path to the open container and the
selection, their events, the breadcrumb and its fold to one line, the URL
fragment that carries both and the parameters of the reading state (its
grammar on `Params`, read against the tree and the Config's phases,
`Scope`), the view a journey's step plays in, shown in place of the place
(shownPlace), and the page's state window.atlas shows agents
(navigation.spec.ts)
threads.ts open points and threads: who a point waits for (threads.spec.ts)
src/commands/ what cli.ts does to a map folder
check.ts validates a map folder: what drawable.ts refuses, then a brief on a leaf, a
rank on an outside node, the root's tour, see/seams/traps ids on every panel,
a <cite> that reads as no citation, tags and phases against the Config's,
journeys' ids, sections, entries, reach and steps against the links, open
points against its step words, and threads, and reports the open points;
with the Config's sources,
each cited file, read once as serve.ts reads it but for the size cap, and its
lines, or the missing root in one line (check.spec.ts)
reply.ts adds an entry to a thread of a map folder, holding a lock beside threads.json
that serve.ts's watch ignores, as it ignores the scratch file the write
renames into place (reply.spec.ts; reply.integration.spec.ts, replies at once
from several processes)
drafts.ts a map folder's data files, and its drafts: made, adopted, dropped
src/inventory/ what a repository holds, as JSON, model-free, for /atlas:init
inventory.ts the summary and the one pass that keeps no text: the files listing.ts lists
(git, or a walk honouring the root's .gitignore, every path it cannot read
set aside with its code); directories of the top two levels; the manifests
(manifests.ts, their boundary parsers); the imports between those
directories and the environment variables read, by pattern (scan.ts)
(inventory.integration.spec.ts, on repositories it writes in temporary folders;
scan.spec.ts bounds every pattern on crafted files)
src/page/ what runs in the browser
atlas.html the page: its styles and its markup, which hold no word and no colour of a map
aliases.d.ts the types of atlas:map and atlas:config, the page's imports of a map folder
engine.ts the page's entry: draws the view of the open container the first time the
reader reaches it and keeps it, paints the camera, takes input, dims what
the phase picked dims in every view it keeps, plays a journey's steps,
posts the reader's selection to serve.ts
stage.ts the stage, pure: the views held, the one being laid out, those wanted now or
later, and what a relayout keeps or lays out again (stage.spec.ts)
draw.ts the renderer of one view: packed (ELK rectpacking or bands by rank, the sides,
libavoid) when the view has a container child, layered (ELK layered, labels
and tags) when it has leaves alone
placement.ts the pure parts of placing a view: the middle items in bands by rank, the side
columns, or bands under DOWN, the chips wrapped in a box, the spot of each
arrow's label, the copies of an item drawn twice (placement.spec.ts)
camera.ts the camera, pure: the view shown and the one it cross-fades with, aligned
through the boxes along their path, any number of levels at once
(camera.spec.ts)
zoom.ts the free look inside a view, pure: the camera's rect zoomed around a point,
panned, or pushed toward an edge the mouse rests at, kept within the rect
that fits the view, whether it strayed from the rest frame, and the
captions a scale leaves readable (zoom.spec.ts)
trace.ts a journey's trace, pure: a step's curve between the copies of its ends'
representatives, its head, the travelling pill's way along it, and the
camera's frame of a mode (trace.spec.ts)
layout.ts runs ELK's layered layout, flat, in the map's direction, its rows wrapped to an
aspect or its layers partitioned by rank, a ghost held to the first or the last
layer (layout.spec.ts, which runs ELK under Bun)
avoid.ts runs libavoid (avoid.integration.spec.ts)
legend.ts the legend's lines, one per arrow kind or node mark a view uses, and one for
what the phase picked dims in it
(legend.spec.ts)
panel.ts the panel, the breadcrumb and the open points' list; fieldHtml, the one way
an HTML field reaches the page, its citations as markers; the viewer of a
citation's lines; the cards' table; a journey's step and the journeys' menu
(panel.spec.ts)
ribbon.ts the ribbon of a journey played: a column per section, a cell per step and
its marks, the data's forms in a row under the cells (ribbon.spec.ts)
measure.ts sizes text: one scale for every view
geometry.ts rects, points and similarities
svg.ts SVG building blocks
src/server/ what crosses processes
wire.ts what crosses between the page, serve.ts and the mod: routes, a selection,
the lines a citation names, the server's JSON line; bunFlags, which every
bun atlas starts takes
source.ts the route of a citation's lines and its refusals, the plugin's one route
that reads a file of the user's (source.integration.spec.ts)
coalesce.ts one run at a time, with at most one waiting: serve.ts's rebuilds
(coalesce.spec.ts)
open.ts hands an address to the desktop's browser, detached, for the mod (open.spec.ts)
src/platform/ the repository's file, path and process helpers, a leaf: a copy of
tools/platform/, never edited here, its tests kept at the source
pure.ts quoting, errno, messages, lexical paths; no Node, no Bun: the mod may import it
fs.ts writes, renames
lock.ts the lock
process.ts processes
git.ts git
child.bunfig.toml the empty Bun configuration bunFlags names
template/ the map folder `new` copies; its tsconfig.json is the one `sync` writes
lint/ the oxlint and oxfmt configs `check` and `fmt` run on a map's data files
fixtures/sample/ the sample map folder
fixtures/deep/ a map folder five levels deep, the specs' DEEP, to look at in the browser;
fixtures/large/ a seeded random map, wide and deep, to time a view on;
fixtures/bands/ a map read DOWN, its views in bands by rank, to look at;
fixtures/citations/ a map whose panels end each claim with a citation of
its repo/, its sources root;
fixtures/phases/ a shop built in three work phases, its header's stepper,
to look at;
fixtures/journeys/ a bookshop with three journeys, its header's menu, to
play, one in two sections with entries, a return, a condition and the
data's forms, Data's cards to start one from, and a step after the phase
MVP;
the six import the plugin's own types and carry no generated files
fixtures/trees.ts a map five levels deep, and seeded random maps, for the specs
hooks/ the mod: register.ts spells `$`, server.ts the server's start, beat and the
command lines the tools run, parse.ts the boundary, register.test.ts the kit's
tests over fixtures.ts
skills/board, stop /atlas:board [map folder] [draft name] and /atlas:stop, the person's alone
skills/init /atlas:init [map folder], the person's alone: a first map, inventory to verified
parts; branch-brief.md and verify-brief.md are its subagents' promptsThe mod keeps one server per map folder, whichever session asks. Its store keeps, under
map:<folder>, that folder's live server, its port and the session that started it, or the claim
of a session starting one, under session:<id> the folders a session shows (a reload attaches
them again), and under selection:<folder> the page's last selection, which every session showing
that map adds to its next prompt's context once. A session claims the folder before it starts a
server and starts it only if its claim still stands CLAIM_SETTLE_MS later. Before it claims, it
probes both its own last port and the one the store names, and reads the record again, as a probe
may wait long on a port: what another session wrote meanwhile is looked at anew. Another session's
claim younger than CLAIM_MS, and not dated ahead of the clock, is waited out, and a server is
forgotten only while the store still names it. $.store.set and $.store.delete take a lock and
rewrite the store's file, and get reads it afresh, so each write lands whole and the next read
sees it (docs/plugin-testing/hook-runtime.md); a read and the write after it are not one step,
which the settle covers. A start that a failing store or clock breaks drops the board and its
claim, and says why. The first session to
ask spawns serve.ts --heartbeat with a secret of its own in $ATLAS_HEARTBEAT, reads its
stdout, and beats it with that secret; another session joins it and only probes it, so the server
never outlives the session that reads it: it leaves once its parent process changes (a claude
killed hard) or a minute after the last beat, and a joined session then starts its own on the
same port. A server that crashes comes back on its port, three ends within a minute leave the
board lost; a SIGTERM from outside, as Claude Code ends its children on exit, revives nothing.
package.json pins the libraries, elkjs (EPL-2.0) and libavoid-js (LGPL-2.1-or-later,
github.com/Aksem/libavoid-js), and the checkers tsgo, oxlint and oxfmt, as runtime dependencies.
Commands
Every command runs from the repository root.
bun install --cwd atlas --frozen-lockfile # once; Claude Code does it at the plugin's cache
bun atlas/src/cli.ts new <dir> # scaffold a map folder in an empty or new folder
bun atlas/src/cli.ts sync <map folder> # write atlas.d.ts and tsconfig.json from the plugin, and drafts/ and threads.json's lock and scratch files into .gitignore
bun atlas/src/cli.ts check <map folder> # the map and its citations, tsgo, oxlint, oxfmt, the two copies; exit 1 on any failure
bun atlas/src/cli.ts check <map folder> --open # list the open points and whom each waits for
bun atlas/src/cli.ts fmt <map folder> # format in place the files check format-checks
bun atlas/src/cli.ts reply <map folder> <open id> --as agent "<text>" # answer an open point; an agent always writes as agent
bun atlas/src/cli.ts draft <map folder> <name> # copy the map's own files into drafts/<name> and print its path
bun atlas/src/cli.ts draft <map folder> <name> --adopt # its data files and threads.json replace the map's, then it is deleted; --drop deletes it
bun atlas/src/cli.ts query <map folder> <node id> # one node as JSON: path, children, links, couplings, fields, sources
bun atlas/src/cli.ts inventory <repo> [--summary] # what a repository holds, as JSON; --summary for a first read
bun test atlas # the engine's suites, *.spec.ts
bun atlas/src/serve.ts <map folder> [port] # serve the page; it prints its address and reloads on save
claude plugin validate atlas # what the mod hooks and calls
claude plugin test atlas # the mod's kit tests, hooks/*.test.ts
claude --plugin-dir atlas # a live session with the mod from source; it writes .claude-plugin/types/, whose claude-code/ and claude-code-tools/ atlas's own tsconfig.json types hooks/ with, not claude-code-mcp/, the developer's own serversThe sample map folder is atlas/fixtures/sample; atlas/fixtures/deep goes five levels down.
The page
- The URL's fragment is the place (
hashOfinnavigation.ts): a bare#idopens a container's view, or a leaf's parent's view with the leaf selected;#<open>/<selected>carries a selection no bare id lands on, a ghost or a container among them. After a?come the parameters of the reading state,key=valuejoined by&, each written only away from its default, such as#app?mode=cards&phase=MVP; their grammar, the rules every new one follows and what survives a move are onParams. Withjourney=<id>&step=<n>, the page shows the view that step plays in, and the place and the mode written are where the journey started (shownPlace). A fragment typed into the address bar is followed. window.atlasis what an agent reads of the page without a screenshot (pageStateOfinnavigation.ts): the open path, the step's on a journey, the selected id, the ids the open view draws (boxes, chips, ghosts), each parameter of the fragment (mode,phase,journey,step) and the fragment, frozen and replaced at each move, with the view'szoom, 1 at its fit (zoomOfinengine.ts), thecamera's mode,sourcesInFull, and thecitationwhose lines the panel shows, or null; a getter, so a page script cannot assign it.- A
<cite>whose text is a citation (citationOfincitations.ts) shows as a small mono marker of its lines, the whole citation as its tooltip; a<cite>of other text, akicker, and alabel, plain text even as the heading of a node withouttitle, show as written. The header's Sources toggle, shown when the map has a citation, shows every citation in full, remembered per browser underatlas.sources(sourcesInFull). - With the Config's
sources, a marker is a button: a click shows each cited stretch and eight lines around it in the panel, a…row between stretches apart, long lines wrapped, read from serve.ts, under the path and a close button, until the close button, Escape or a move; a file over the route's cap shows as too large to show. serve.ts knows the paths the map cites only from folder.ts's line. - A view whose container has two leaf children or more, one of them with
io(cardsOfincards.ts), the root's included, gets a Map | Cards switch in the stage's controls. Cards (mode=cards) lays the container's leaves over the drawing as a table (cardsHtmlinpanel.ts): a column per leaf, in data order, its header in its colour selecting it; a row of leads, unless no leaf has one, then one periokey, each cell throughfieldHtml, the column of a leaf the phase picked dims faded and dotted as the drawing shows it, a marker opening its lines in the panel, shown if it was hidden; a click elsewhere on the cards does nothing. The header row and the keys' column stay in sight as it scrolls, below the controls, which wrap within the stage. The drawing stays laid out beneath, inert, keeping its zoom, which Escape leaves alone, the fit and legend buttons disabled; the legend and the hint hide. Another container opens on its drawing. - With the Config's
phases, the header shows a stepper: every phase, then each in order, scrolling within its own box when the header is narrower. A phase picked (phase=) fades and dots, in every view, what the phases after it bring, by the ruledimmedByinphases.tsstates. The dots are a pattern of their own, apart from the dashes ofkind: "off", of outside nodes and of couplings, and the legend explains them in a view that draws some (dimsIn). An arrow that stays names only the links that do not fade (labelAt), in the spot its whole label took, shortened as a placed label is when it does not fit. The panel shows a node's phase under its own heading. The phase stays as the reader moves. A map without phases has no stepper. - With the root's
journeys, the header shows a menu, a row per journey and its count of steps, numbered across its sections. Picking one plays it from its first step, nothing selected, in its host view, the deepest that draws every end of every step as a box, a card, a chip or a ghost (hostViewinjourneys.ts); a step whose ends the host does not both draw plays in the deepest view that does, else, no view drawing both, in the view of their lowest common container (playView,stepView). The panel shows the journey's label, the step's section and its place in the journey, the step'scarriesor the label of the link it follows over its ends, for an entry the icon of its nature beside its trigger and the word of its nature, the step's direction, the data's form once it is done (formAfter) and its condition, and its note, with ← → buttons, which the arrow keys press too, and under them a button that leaves the journey for the place it started from (renderJourneyinpanel.ts). The mode switch hides on a journey, which shows each step as a drawing, the camera's modes in its place; one started from the cards keepsmode=cardsin the fragment and shows the cards again once left for where it started. A phase picked stays, and leaves the trace undimmed. A map without journeys has no menu. - The view a step plays in traces each step of its section over every item, between the
representatives of its ends, what draws each end or else the box or ghost that holds it
(
representativeIn,tracedIn), a step whose ends share one, or with an end without one, untraced: a quadratic curve from border to border, bowed to the right of its way, further for each step before it on the same pair (curveOf,coursesOfintrace.ts); an item drawn twice, a ghost or an outside leaf on both sides, is left by its "in" copy and reached at its "out" one going forward, as its links' arrows are (Sideinatlas.ts), the other way back (copiesOfinplacement.ts, thecopiesofDrawnindraw.ts). Forward in--accent, back in--back, dashed under a condition, a band of--sheetunder each, a head at its end; the steps played lighter, those to come lighter still, the step shown thicker, in--inkforward; each with its number at its middle, but the step shown when it has a data's form, which a pill shows over its middle, its condition in a pill under it. A pill travels along the step shown, the data's form before the step for the first half of its way, the dot alone when the section gave the data no form yet, then the form after it (travelled,formAt,formBefore); over an entry's start, a pill of its nature and trigger, and the start pulses twice. The items the section touches are outlined, the step's two ends darker, the view's other chips, cards and ghosts faded, never a box; the view's own arrows stay, dimmed, no arrow hot. Numbers, pills, the travelling dot, the strokes and their dashes keep their size on screen at any zoom, each head the size the view's arrows' markers give its stroke, never longer than its curve on screen (placeTraceinengine.ts,headPx); a cell of the ribbon under the pointer brings its step's trace out, its number shown, the step shown's too; the legend has a line for each kind of step traced, forward, back, under a condition. Underprefers-reduced-motion, the pill sits at its end, the camera jumps and nothing pulses. - On a journey, each box of the view a step is played in carries its index on its top edge, when
it has one: the numbers of the steps of every section whose two ends lie below it (
indexOf), in ranges, two numbers or more one after another written6–8(rangesOf); those of the section shown in--accent, its returns in--back, the others in--ink-3, a range holding numbers of one of them only. Its tooltip names the box, then each step over its ends' labels. In the view's units as the open points' badge, left of that badge when the box has one, it is drawn in the box's group, so that a click on it enters the box and leaves the journey; it is drawn anew at a new journey, section, view or layout, and lays nothing out. - On a journey the stage's controls choose what the camera frames, remembered per browser under
atlas.camera,sectionfor any other value:plan, the view's fit;section, every step of the section traced there, the pills of its entries and 60 px on screen around, moving only at a new section or view;step, the step shown and its entry's pill, at each step (frameOfintrace.ts), never closer thanMAX_ZOOM, within the fit, above the ribbon. That frame is the journey's rest frame (restOfinengine.ts) where the fit is off a journey: where a move ends, where a resize or a new layout lands, what the fit button, Escape and a click on the empty sheet bring back, the edge push sliding only once the reader looked away from it. A move to the step's view, or a mode picked, heads straight for that frame: inDURwithin a view or between a view and one of its ancestors, at once between two views neither of which holds the other. - On a journey, a ribbon over the foot of the stage shows it whole (
ribbon.ts): a column per section with a step, as wide as its count of steps; a cell per step, at least 22 px wide, marked as an entry, a return, a condition, played or shown, which a click plays; under the cells, each form of the data (formAfter) over the steps it holds. Past the cells' minimum it scrolls sideways, the step shown's cell kept in sight. Written once per journey and marked in place at each step, it keeps the focus. It floats, leaving the drawing area's size alone: the rest frame aims above it and the legend rises above it, again each time its height moves (itsResizeObserver). Its play button, which Space presses too unless the focus is on a text field, a button or a.hit, plays a step every 2 s up to the last, from the first when pressed there; a step the reader plays (← →, a cell, the menu), a fragment typed or leaving stops it, a phase or a camera mode picked does not. - Escape closes the lines viewer, then deselects, then goes up one level; so does a click on the empty sheet. On a journey, both bring the camera's frame back first when the reader looked away from it, then leave it for the place it started from; a click on an arrow or its label, or on a number or a pill of the trace, does nothing, and any other move leaves it from the step's view.
- The header's lists, the journeys' and the open points', each open under their own button; a click outside an open list only closes it. A box enters its container, a card or a ghost is selected where it stands, a chip jumps to its node.
- Inside a view, the wheel zooms around the pointer, a drag pans and two fingers pinch, within
the rect that fits the view (
zoom.ts); a mouse that rests near an edge of a view looked into slides it that way, faster the closer to the edge, after a short dwell so that a pass toward the panel moves nothing (edgePushandpushedinzoom.ts), the place and the panel as they were, the bottom edge at the ribbon's top on a journey; the fit button, Escape and a click on the empty sheet bring the rest frame back before they do anything else, but over the cards, and a move to another view starts at its own: the fit, or the camera's frame on a journey. - A caption (an arrow's label, a box's tag, a line of a card's sub-title) under 10 px on screen
hides, keeping its spot, unless its arrow is lit by a hover or a keyboard focus or hot from the
selection, or its own box or card is hovered, focused or selected (
captionShowninzoom.ts). An invisible band 8 px wide on screen along each arrow carries its whole label as a tooltip; the bands lie under the boxes, so a click on a box's edge where an arrow lands enters the box. - The breadcrumb stays on one line: from five crumbs on, the levels between the root and the
last two fold into
…, their names in its tooltip (foldedCrumbsinnavigation.ts). - A ghost drawn on both sides carries a
›mark at the edge its arrows cross and a tooltip naming the copy; hovering one copy lights both. - A move between a view and one of its ancestors cross-fades the two, the deeper one aligned on its box; a move between two views neither of which holds the other lands at once.
- A view is laid out the first time the reader reaches it, then kept; its parent and its
container children are laid out while the reader looks, a navigated view before any of them.
Every view is laid out again when the drawing area's aspect moves, with the Config's ratio
"screen" (a packed view aims at it and a layered view wraps its rows to it, but for a view in
bands by rank), and when the fonts settle late.
performance.measure("atlas:draw <view>")times each layout.
Traps
Each module explains its own where it bites.
- The text classes
measure.tsmeasures (CARD,CHIP,BOX,GHOSTandLABELthere) keep the font sizesatlas.htmlgives them, or text overflows its box. svg text { text-rendering: geometricPrecision }stays inatlas.html: without it, Chrome rounds font sizes per zoom and drawn text drifts from the widthmeasure.tsmeasured.- The order of a node's
childrenis the order in which its view packs them: reordering them moves boxes. atlas/fixtures/sampleandatlas/templateeach commit anatlas.d.ts, a copy ofatlas.ts: after a change toatlas.ts,bun atlas/src/cli.ts syncboth, orcli.integration.spec.tsfails on them.- A process that imported a map folder keeps that first evaluation: importing it again answers
the old data, and a
?queryon the specifier refreshes the file named but not what it imports.serve.tstherefore loads the folder in a fresh process (bun atlas/src/model/folder.ts <map folder>) on every build. libavoid.wasmis the installed libavoid-js package's own: its exports list only the entry point, soserve.tsresolves the file beside that entry and answers it beside the page. No copy is committed. A page that cannot load it draws a packed view without arrows and says so in the panel (arrowsMissinginwords.ts).dressPage(engine.ts) writes the Config's title, subtitle and words into the page before the first layout: the header's height sets the drawing area's aspect, which a "screen" packing aims at. Written later, the views pack for another aspect.- The legend shows a line only for the arrow kinds and node marks the open view draws, and for
what the phase picked dims in it (
legendKeysinlegend.ts): a kind the view never uses has no line. - ELK's bundle does not start under Bun, where
selfexists: its worker module takes the web worker's branch and exports nothing.layout.spec.tsbuilds the layouter it handselkLayeredfromelk-api.jsand that branch; a script that lays a view out outside a browser (a check, a benchmark) does the same, or runs under Node. - A map folder's files are code: its
map.tsandatlas.config.tsrun in every command on it, and abunfig.tomlor a.envin the folder a bun starts in preloads more. Every bun atlas starts, from the mod,serve.tsorcli.ts, takesbunFlags(wire.ts) before its script, and the mod's tools run a map outside the session's folder, that no board of the session shows, only once the person allows it. claude plugin test atlasruns every*.test.tsunderatlas/in the engine's environment, where abun:testsuite fails: the engine's suites are*.spec.ts, and the rootbunfig.tomlkeepsbun testoffatlas/**/*.test.ts.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

