The boot lane: how an agent reads a project
01When an agent starts, it reads a short ordered list of files that vibe computed from everything the project depends on. The list has a fixed first file, read in full, and a list of the rest. Some entries are read always, some only when a condition holds, and nothing in the list is written by hand.
vibe tree --plain --path hello-vibe
project: <TMP>/work/hello-vibe
STATIC.md: (none)
packages: 1 roots: 1
columns: load T=transitive C=condition S=in STATIC.md
org.vibevm.world/wal dynamic . . .
The order of reading
03An agent session begins with the instruction file its vendor reads, CLAUDE.md, AGENTS.md or GEMINI.md. At the end of that file sits a short block vibe maintains, and the block says: read vibevm/vibespecs/boot/STATIC.md first and in full, then open vibevm/vibespecs/boot/INDEX.md and read every file it names, in order. That is the whole boot: three steps, all of them reading.
04 Session-start order: theCLAUDE.md/AGENTS.md/GEMINI.mdredirect →vibevm/vibespecs/boot/STATIC.xml(if present) →vibevm/vibespecs/boot/INDEX.mdand the entries it names, in order.
05STATIC.md is the priority lane. It holds the text that must be in front of the agent before anything else, assembled from the packages that asked to be read that way, each package's text exactly once. The file exists only when some package asked for it; a project whose packages are all read on demand has no priority lane, and vibe tree prints STATIC.md: (none), as above. A project that keeps its own boot files in the XML dialect gets STATIC.xml instead, with the same content. It changes only when the set of packages or their versions change, which is what makes it cheap: an agent host can keep it cached across sessions.
06 What STATIC is (the owner's definition, refined): the generated static boot lane is a CACHE-STABLE PREFIX in LLM-economy terms. It is loaded into an agent or subagent once, at the head of its context, and from then on stays byte-for-byte identical across sessions and spawns — so the provider's prompt cache serves it as a hit and the user never pays full price for the prefix twice. It is compiled, anchor-qualified, self-contained (resolution rules ride inside it), and deliberately front-loaded: the highest priority content reads first precisely because first is where cache stability lives.
07INDEX.md is a manifest, not a payload. Each entry names a file and says whether it is static, to be read directly, or dynamic, an include the agent resolves as it goes. An entry can carry a condition; then the agent reads it only when the condition holds for the current session, for example one operating system.
08INDEX.md— a generated TOML manifest of the rest of the sequence: aschemaversion, astaticpointer (the path ofSTATIC.md, when one exists), and an ordered list of[[entry]]tables. Each entry carriespath,kind("static"— a resolved file the agent reads directly;"dynamic"— an INCLUDE the agent resolves at boot, §2.4), and, for dynamic entries,when(the activation condition, §2.4). The manifest is flat and machine-precise —vibeperformed the graph walk once at generation time; the agent parses one TOML document and reads the listed files, with no recursion, discovery, or cycle-detection.
Where the list comes from
09Every package may contribute one boot snippet: a short text meant to be read at every session start. The package declares it in its manifest with a category, and the project's manifest decides how the snippet is linked: compiled into the priority lane, or listed in INDEX.md and read on demand. The project's choice wins over the package's suggestion.
10 Decision. Each dependency declares an inclusion type, set by the consumer in itsvibe.tomlon the[requires.packages]entry:
11link = "dynamic" is the default: the contribution becomes a path in INDEX.md, read on demand, and gated by a when condition if the snippet declares one. link = "static" compiles the text into the priority lane, read first and whole; it is used sparingly, because it duplicates the text on disk.
12link = "dynamic"— the default.viberesolves the contribution to a concrete path inINDEX.md; the agent reads it dynamically, on demand. An optionalwhencondition gates the read: with awhenit is a conditional INCLUDE (loaded only when the condition holds) — mechanically the subskilllazy-pulldelivery mode; without one it is read unconditionally. Thewhendraws on the subskill[activation]probe vocabulary (PROP-003 §2.5) — one probe grammar across both mechanisms. v1 implements theos:probe end-to-end —when = "os:windows"matches the session's operating system (windows/macos/linux); the remaining probes are reserved until PROP-003's activation engine is built.
13link = "static"— the contribution's boot text is compiled intoSTATIC.mdahead of time (whole, anchor-qualified — §2.3). Read first, one read, maximum attention weight. The emergency priority lane — for top-level skills and critical disciplines whose priority must be guaranteed by position, not by trusting agent-side resolution. Used sparingly; it duplicates the text on disk.
14The link type belongs to the edge, declared by the consumer, never baked into the package. A bare static is static-soft: a package linked statically by several consumers is compiled once into a shared place and referenced from each. static-hard compiles it into every consumer's own lane. static-transitive forces a package and its whole subtree static, overriding dynamic edges inside. Every package in the dependency tree carries its own boot files, what was compiled into it and what it references dynamically; the project root is one such package among many.
15 Decision.linkis a property of the edge (consumer-side, declared in the parent's manifest), never baked into the pulled package (as PROP-034 §2.1 already states). A unitPis compiled by walking its own direct edgesP→X:
16static-soft— the default, the meaning of a barelink = "static". Hoisting dedup at compile time: a package statically linked by more than one consumer is hoisted to a shared location (§2.4) and linked once; each consumer references it. Deterministic; does not depend on read-time behaviour.
17static-hard— explicit opt-in (link = "static-hard"). Pure local compilation: every consumer compiles the package into its ownSTATIC.mdindependently, with no hoisting. Duplication is deduplicated at read time by the read-set (§2.9).
18static-transitive—Xand its entire subtree are forcedstatic, ignoring anydynamicedges inside — "rewrite the whole tree underX". This is the one mode that overrides nested breaks.
19 Decision. Every package materialised undervibedeps/carries its own boot artifacts —vibedeps/<slot>/spec/boot/STATIC.xml(what is compiled into this unit, verbatim) and.../INDEX.md(this unit's external dynamic references, resolved when the unit loads) — not only entry-point workspace nodes.
20vibe computes the sequence for each project from the resolved dependency graph: the foundation the project itself declares, then its own boot text, then the snippets of its dependencies, a dependency before whatever depends on it. Authors do not number their snippets, and two packages cannot fight over a position, because the order is derived, not declared.
21 Within the computed sequence the order is:foundation→ the node's own → dependency boot (topologically — a dependency before its dependents) →user-override.staticcontributions are concatenated intoSTATIC.mdin the same relative order.
Why it is short
22Every word in the lane is paid for on every session start, by every agent that opens the project. So the lane holds instructions, not explanations: what to do, where the rules are, which addresses to cite. Anything an agent needs only sometimes, including this manual, stays out of the lane and is fetched by address when a question arises. The text of a boot snippet is written to that budget on purpose.
23 Everything is layered by mutation frequency — the whole loaded context is one monotone gradient (owner, 2026-08-23, near-verbatim: «всё в приложении устроено слоями; на самой вершине — динамическая загрузка быстрых изменений»). Reading order equals stability order: the rarest-changing text reads first, because a change at depth N re-prices every byte after it — the earlier a layer sits, the more cache its mutation burns. The concrete gradient: (0) the instruction files (CLAUDE.md/AGENTS.md/GEMINI.md) — read first, so an edit there resets the ENTIRE cache; they carry only what must hit every session (the four rules, the standing directives) and change only for large causes, everything else living in specs loaded later; (1) the generated STATIC lane — structural-events-only (§3), and INTERNALLY sorted by the same law: contributions of rarer-changing packages belong earlier in the tape; (2) the INDEX manifest and the conditional dynamic lane — per-boot variability; (3) the live session tail — task text, tool results, fast state, which lives in context and is never compiled into any lane. This is a GLOBAL architectural idea for all of VibeVM, not a spec of any one mechanism (owner, 2026-08-23): whenever a new system is designed or an existing one changed, the design review checks it against this layering — where does each byte it adds sit on the gradient, and does anything fast-changing sneak ahead of anything slow.
24The same prefix serves every agent: when a boss and its workers load one byte-identical lane, the cache one of them warms serves all the others. That is why nothing per session or per agent, no names, ids or timestamps, may enter it.
25 The multiplier: one prefix, every agent. When the boss and all its workers load the SAME byte-identical prefix, the cache warmed by any one of them serves every later spawn — each subagent starts cheap. This makes the stability requirement STRICTER than per-session determinism: nothing per-session and nothing per-agent may enter the prefix — no agent names, no session ids, no roles, no timestamps. Per-agent material belongs after the prefix, in the variable tail.
Edge cases and rules
26A snippet that declares a condition is always a dynamic entry, whatever link type the project asked for: a condition cannot be evaluated ahead of time, so the text cannot be compiled into the priority lane.
27 A[boot_snippet]that declares awhencondition (§2.6) stays a conditionaldynamicentry, irrespective oflink: a condition cannot be honoured by the ahead-of-timestaticlane, so awhenforces the gated INDEX form. It is a correctness constraint, not a preference — OS-specific content must never reach a session on the wrong OS.
28A cycle among requirements is a hard error when the lane is generated, reported with the offending path; the lane is never written half linked.
29
Reject cycles. requires is expected acyclic; a cycle is a hard error at generate time, reported with the offending cycle path. The boot is never emitted half-linked. (This is the one place cycle detection lives; the agent-side read is a flat, recursion-free parse per PROP-009 §2.)
30The generated lane is never a citation target. Rules are cited by the address of their source document, never by their position in STATIC.md, because the lane is compiler output and changes whenever the dependency set changes.
31 A generatedSTATIC.mdis not a citation target — authored text never citesspec://…/boot/STATIC#…; the lane is compiler output, and source-of-truth is the package source undervibedeps/(PROP-035 §11's lint, B-011 §6.1).
32Documentation never enters the lane. A documentation package has no boot snippet by definition; an agent reaches this manual through a skill or by address, when it needs it.
33 No documentation page entersSTATIC.xml,INDEX.mdor a boot snippet. Adocpackage has no[boot_snippet]; agent-audience text is never in a boot prefix.