agentleFS
bengousbengous/claude-code-plugins/atlas/AGENTS.md

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.

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
  1. Distinctive:

    Every command runs from the repository root.

    line 258
  2. Distinctive:

    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 …

    line 423

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

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' prompts

The 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 servers

The sample map folder is atlas/fixtures/sample; atlas/fixtures/deep goes five levels down.

The page

  • The URL's fragment is the place (hashOf in navigation.ts): a bare #id opens 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=value joined 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 on Params. With journey=<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.atlas is what an agent reads of the page without a screenshot (pageStateOf in navigation.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's zoom, 1 at its fit (zoomOf in engine.ts), the camera's mode, sourcesInFull, and the citation whose lines the panel shows, or null; a getter, so a page script cannot assign it.
  • A <cite> whose text is a citation (citationOf in citations.ts) shows as a small mono marker of its lines, the whole citation as its tooltip; a <cite> of other text, a kicker, and a label, plain text even as the heading of a node without title, show as written. The header's Sources toggle, shown when the map has a citation, shows every citation in full, remembered per browser under atlas.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 (cardsOf in cards.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 (cardsHtml in panel.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 per io key, each cell through fieldHtml, 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 rule dimmedBy in phases.ts states. The dots are a pattern of their own, apart from the dashes of kind: "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 (hostView in journeys.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's carries or 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 (renderJourney in panel.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 keeps mode=cards in 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, coursesOf in trace.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 (Side in atlas.ts), the other way back (copiesOf in placement.ts, the copies of Drawn in draw.ts). Forward in --accent, back in --back, dashed under a condition, a band of --sheet under each, a head at its end; the steps played lighter, those to come lighter still, the step shown thicker, in --ink forward; 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 (placeTrace in engine.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. Under prefers-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 written 6–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, section for 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 (frameOf in trace.ts), never closer than MAX_ZOOM, within the fit, above the ribbon. That frame is the journey's rest frame (restOf in engine.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: in DUR within 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 (its ResizeObserver). 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 (edgePush and pushed in zoom.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 (captionShown in zoom.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 (foldedCrumbs in navigation.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.ts measures (CARD, CHIP, BOX, GHOST and LABEL there) keep the font sizes atlas.html gives them, or text overflows its box.
  • svg text { text-rendering: geometricPrecision } stays in atlas.html: without it, Chrome rounds font sizes per zoom and drawn text drifts from the width measure.ts measured.
  • The order of a node's children is the order in which its view packs them: reordering them moves boxes.
  • atlas/fixtures/sample and atlas/template each commit an atlas.d.ts, a copy of atlas.ts: after a change to atlas.ts, bun atlas/src/cli.ts sync both, or cli.integration.spec.ts fails on them.
  • A process that imported a map folder keeps that first evaluation: importing it again answers the old data, and a ?query on the specifier refreshes the file named but not what it imports. serve.ts therefore loads the folder in a fresh process (bun atlas/src/model/folder.ts <map folder>) on every build.
  • libavoid.wasm is the installed libavoid-js package's own: its exports list only the entry point, so serve.ts resolves 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 (arrowsMissing in words.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 (legendKeys in legend.ts): a kind the view never uses has no line.
  • ELK's bundle does not start under Bun, where self exists: its worker module takes the web worker's branch and exports nothing. layout.spec.ts builds the layouter it hands elkLayered from elk-api.js and 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.ts and atlas.config.ts run in every command on it, and a bunfig.toml or a .env in the folder a bun starts in preloads more. Every bun atlas starts, from the mod, serve.ts or cli.ts, takes bunFlags (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 atlas runs every *.test.ts under atlas/ in the engine's environment, where a bun:test suite fails: the engine's suites are *.spec.ts, and the root bunfig.toml keeps bun test off atlas/**/*.test.ts.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.