VibeVM
Contents
On this page
en
Publisher
org.vibevm.core
Version
1.0.0latest
Audiences
user, author, agent
Reading time
4 min
Rendered
Read aloud
never

The dependency tree on screen

01vibe tree draws the packages a project resolved as a tree, says for each one how its text reaches the agent, and explains why. On a terminal it opens an interactive screen; in a script it prints a plain tree or JSON. This page is that command, its screen, and the way an agent can look at the screen without a terminal.

02
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  .  .  .

What it shows

03The command reads the committed lock file, the manifests and the generated boot files of the project at --path, and writes nothing: it never touches the tree, a manifest, the lock or the generated files. Each package is one row, with the columns in a fixed order. The load column is the lane a package's boot snippet landed in, read from the generated files rather than recomputed, so the screen shows what an agent will read. A package that appears under several parents is drawn under each one and marked (*) after the first, without being expanded again. The status line shows the size of the compiled lane in bytes and lines.

04 vibe tree answers that algorithmically: it renders the resolved package tree annotated with the effective load type and the flags that explain it, and emits the same data as JSON for downstream tools.
05 It operates on the workspace discovered from --path (default .), reading the committed vibe.lock, the node manifests, and the generated boot artifacts.
06 vibe tree is a read-only analyzer over the current project. It mutates nothing (REQ: never writes to the tree, manifests, lockfile, or artifacts).
07 Each package is one row. Columns, left to right (REQ: this order):
08 The load value is the lane a package's boot snippet actually lands in, read from the committed artifacts (REQ):
09 vibe tree renders each package under each parent, marks a re-occurrence with a trailing (*) and does not re-expand it, and cycle-guards the walk on the package's qualified group/name (REQ).
10 The status line shows the size of the statically-compiled lane: the byte count and line count of STATIC.md (REQ).

Three outputs

11On a terminal the default is the interactive screen. When the output is not a terminal, or with --plain, the command prints a static tree. --json emits one object with the same data the screen renders, valid against the shipped schema, for any tool downstream.

12 interactive TUI — the default on a tty (§2.11);
13 plain — a static ASCII tree when not on a tty, or under --plain.
14 --json — the machine surface (§2.7), the same data a GUI consumes;
15 vibe tree --json emits one object, the same data model the TUI renders, valid against the shipped schema (REQ: schema_version = 1).

16Two warnings come with the tree. Root drift means the lock file's list of roots disagrees with the manifest, so the lock is behind. Stale artifacts means the committed boot files disagree with a fresh computation, so the project needs vibe reinstall.

17 root-driftvibe.lock meta.root_dependencies disagrees with the root vibe.toml [requires.packages] (the lock is behind).
18 stale-artifacts — the committed lanes disagree with a fresh EffectiveBoot recompute (the tree needs vibe reinstall).

The screen

19The screen has three display modes, each a configuration of one tree widget and none a flat list, and three shapes of the tree, chosen per mode; the active mode is picked from a menu, shown in the status line and remembered. Primary actions sit on function keys: F1 opens Search Everywhere, F2 the sort menu, F3 the mode menu, F4 the settings screen, F6 copies the current screen and Shift+F6 opens the copy settings. The footer lists the active keys, with Shift written as an arrow to keep the hints short.

20 REQ. vibe tree has three display modes, each a Tree-widget (§3.1) configuration (§3.2) — none is a flat list:
21 REQ. The pipeline offers three shapes, selectable per context on the F2 sort menu (§7.2), default = (a):
22 REQ. The active mode is chosen from the F3 menu (§7.1) — not a bare cycle key. The active mode is shown in the status line and persisted (§9).
23 REQ. Primary actions are on function keys: F1 Search Everywhere (§7.3), F2 sort menu (§7.2), F3 mode menu (§7.1), F4 settings (opens the vibe prefs settings UI — PROP-041), F6 copy / Shift+F6 copy-settings (§10.2). The footer lists the active keys with short labels; Shift is written as (e.g. Shift+F6↑F6) to keep hints short.

24Inside the tree the arrows move and pan, Space folds a node, Enter opens the detail card, and Shift with a horizontal arrow switches tabs anywhere in the application. Search Everywhere works as in an IDE: an «All» tab that searches everything and tabs per category. The sort menu depends on the mode. Controls are grouped, and Tab steps between groups. Modals stack: each new one draws over the last, Esc closes the top one, and at the base screen Esc asks before quitting, because a session may have been slow to load.

25 REQ. Within a tree: / move selection (+ scroll), / pan horizontally, Space folds/unfolds the selected node, Enter opens the detail card (§8). Shift+/ switches tabs app-wide — the tree's display tabs (in tabs mode) and the Search Everywhere category tabs (§7.3); plain / stay tree-pan (which is why tab-switch takes Shift). These direct keys are exempt from the F-key scheme (they are navigation, not commands).
26 REQ. F1 opens the Search Everywhere window — the vibe-actions Search Everywhere engine (PROP-039 §10), in the IntelliJ IDEA idiom: a hybrid "All" tab that searches everything, plus per-category tabs that narrow it (Tab/Shift+Tab cycle; the "All" tab carries a category checkbox filter). Three providers ship (PROP-039 §10.4):
27 REQ. F2 opens a dialog whose content depends on the active mode:
28 REQ. A screen's controls are partitioned into focus groups — cohesive clusters the user steps between with Tab (and Shift+Tab backwards). Within a group the group's own keys act (arrows move a radio selection, typing edits a field, Enter activates a button). A screen with more than one focus group declares a Tab Order — the explicit sequence Tab cycles — per screen; a single-group screen has no Tab Order (Tab is inert there). Tab never switches display tabs (that is Shift+←/Shift+→, §5.3) and never activates a control (that is Enter).
29 REQ. Modals form a stack: opening a modal pushes it; it draws over everything below (each lower layer still visible as backdrop); input goes only to the top modal; Esc pops the top modal (returning to the one beneath). A feature may push a modal over a modal — e.g. copy-settings (§10.2) → file-path (§10.5) is a depth-2 stack. The base screen is the bottom of the stack; Esc at the bottom triggers quit-confirm (§7.4), it does not pop.
30 REQ. At the base screen, Esc opens a confirm dialog ("Really quit?") with Yes/No buttons; Yes/Enter-on-Yes quits, No/Esc returns. The confirmation exists because loading may be slow and Esc is used pervasively in modals — an accidental single Esc must not discard the session.

31Copy is «what I see is what I copy»: each screen serialises what it shows, as text by default, as Markdown or a file on request; a PNG export is reserved and says so. The interface state, the mode and the sort, shape and order choices, is saved under ~/.vibe/tree/ and restored at the next launch; a missing or broken file falls back to the defaults. The colour tier is detected once from the environment and can be overridden in the settings.

32 REQ. F6 copies the current screen straight to the clipboard as text (the provider's default format). Shift+F6 opens the copy-settings modal: a RadioGroup for format (Markdown / PNG — and later PlantUML / Mermaid) and a RadioGroup for destination (clipboard / file). Confirming with destination = file pushes the file-path modal (§10.5) over it (§6 stack).
33 REQ. Each screen (tree/sub-tables/tabs; the card) supplies a copy provider — an object that knows how to serialize what is currently shown into a copy format. A tree provider serializes the tree with its current display options; the card provider serializes the card's fields. Copy is "what I see is what I copy": in tabs mode only the active tab is serialized.
34 REQ. PNG export (a rasterized tree image; a designed package info-card image) is reserved — selecting PNG opens the ComingSoon modal (§2.10) until the rasterization (font + image crates) is built. Named non-goal-for-now (§12).
35 REQ. UI state persists under ~/.vibe/tree/ as one or more JSON files. Saved: the active mode (§4.4), the per-context sort + shape + block-order choices (§7.2, §3.3). On TUI launch the settings are loaded and the UI restored to them; a missing/corrupt file falls back to defaults (never a hard error). Writing is atomic; the directory is created if absent. (This is the machine-global ~/.vibe/ config root, distinct from the project's .vibe/.)
36 REQ. Tier detection is a pure function over the environment — detect_tier(colorterm: Option<&str>, term: Option<&str>) -> Tier ($COLORTERM first, then $TERM; crossterm exposes no colour-count API). The TUI reads the env once at launch in a sanctioned spot and feeds the values in; the detected tier is overridable through the settings system (§9). The default is Tier 3: anything not explicitly dumb (an unset or empty TERM/COLORTERM, or a generic TERM=xterm) is assumed truecolor, because every incumbent terminal renders truecolor and several (notably on Windows) do not advertise the capability via env at all — defaulting to Tier 3 keeps a modern terminal colourful instead of degrading it to mono. The lower tiers are the fallback (the degradation path), reached only when the environment explicitly advertises a lower capability (a 256-colour TERM, or an explicitly dumb TERM=linux/dumb); Tier 0 is never reached from an unset env. A genuinely limited terminal is otherwise overridden via vibe.tree.tier.

A terminal of its own

37vibe term launches vibeterm, a terminal application hosting a shell, so the screen can be used and inspected on its own. A vibe tree started inside vibeterm does not open a second window: it takes over the current terminal for the session.

38 REQ. vibe term launches the vibeterm terminal app hosting an interactive shell, so the terminal can be used and eyeball-debugged standalone.
39 A vibe tree launched inside vibeterm (this env present) does not spawn a second window — it upgrades the current terminal in place: the -t / vibeterm launch resolves to the in-terminal console TUI here, so a plain shell becomes a "VibeTree terminal" for the session (PROP-036 §2.13). Outside vibeterm, -t still opens the desktop app.

Looking at the screen from an agent

40An agent has no terminal, so the vibe aiui commands render the screen for it. The render verb builds the same model vibe tree builds at --path, drives a key script at a given size, 80x24 by default, and prints a snapshot in one of two formats: plain text, or cells, a run-length encoding of every cell with its glyph, colours and modifiers, for assertions about style. A key script is a space-separated list of key names, function keys, arrows, Enter, Esc, Tab and the rest, with a Shift+ prefix where needed. Keys that would leave the process or change the world, F4 and the copy keys, are refused rather than executed. The model verb projects the state without rendering at all, and the terminal verbs drive a live vibeterm session.

41 REQ. vibe aiui is the agent-facing command family. Its render-plane verb:
42 builds the vibe tree model at --path (the same resolver vibe tree uses), drives --send (§3) at --size (default 80x24), and prints the --format snapshot (§2, default text) to stdout.
43 REQ. A rendered Buffer projects to one of two snapshot formats, the same schema every observation plane emits:
44 cells — JSON: {cols, rows, rows:[[run,…],…]} where each run is {n, ch, fg?, bg?, mods?}n cells of glyph ch sharing a style, run-length encoded per row; fg/bg are #rrggbb (or an ANSI role name), mods the set of bold/dim/italic/underlined/reversed present. Enables style/colour assertions (e.g. "the active group's border run is the accent colour").
45 REQ. A key script is a space-separated list of key names driving the TUI before the snapshot. The grammar: function keys F1F12; navigation Up, Down, Left, Right; Enter, Esc, Tab, BackTab, Space, Backspace; a Shift+ prefix on any of them (e.g. Shift+Left, Shift+TabBackTab). Names are case-insensitive.
46 REQ. A scripted key that would escape the process or mutate the world is refused, not executed: F4 (spawns the settings subprocess) and F6/Shift+F6 (write the clipboard) are rejected by the key-script parser (§3).
47 REQ. The model-plane verb projects the TUI state — no rendering at all:
48 REQ. The terminal-plane verbs drive a live vibeterm control session:

49Underneath, every action of the interface has an address, action://<group>/<name>, and the observable state is one serialisable snapshot with the focus, the open modals, the visible rows and the enabled actions with their reasons, carrying no rendering types. A headless surface lists the actions, invokes one by address, returns the snapshot and runs the search, which is how an agent drives the screen without seeing it.

50 REQ. An action is named by an ActionAddr with the textual form action://<group>/<name>[?<params>], where <group> is a dotted namespace (e.g. vibe.tree, core), <name> is a dotted/kebab identifier (e.g. copy.markdown, search.everywhere), and the optional <params> is a &-separated key=value query carrying invocation parameters (§5). (group, name) is the identity; the query is not part of identity. Examples: action://vibe.tree/copy.markdown, action://vibe.tree/sort?by=name&dir=asc, action://core/search.everywhere.
51 REQ. The observable UI state is a serialisable ModelView snapshot (focus, open modals, visible rows, current tree/selection, the active tab, the set of enabled actions with their addresses + reasons). It is a pure projection of the Model and carries no rendering types — so an AI reads structured state, never pixels.
52 REQ (built; the in-process form ships). The core offers a headless AIUI surface: list_actions(filter?) (enumerate the registry with live enablement + reasons + params), invoke(addr, args) (the same invoke as §7.1), state() -> ModelView (§11.2), and search(query, tab?) (drive §10 programmatically). vibe-actions/src/aiui.rs implements list_actions + invoke, and vibe aiui state projects the §11.2 ModelView live, citing this section in its own --help. Because enablement is pure + introspectable, the model is serialisable, and invocation is address-based, this surface is a thin adapter with a no-op present. The architecture must keep it a thin adapter — it was prototyped on the TUI, and the remaining JSON-RPC / MCP bindings are further adapters over the same surface. This is the founding AIUI goal (DO18): the headless surface is the reference; visual surfaces are projections.

Edge cases and rules

53English is the complete locale of the interface and the last fallback; another locale may lag and falls back silently. A package may ship its own locale file, and a language pack may replace one.

54 REQ. English is the default, mandatory-complete locale and the terminating fallback. Other locales may lag and fall back silently. Locale switch is atomic (ArcSwap<Catalogue>); a package may ship locales/<lang>.ftl, and a dedicated language-pack package may override, merged by explicit priority (language-pack > package locale > inline English).

For an agent

This page has a machine mirror. The citation carries the version rather than latest, so what an agent quotes does not move under it.

spec://org.vibevm.core/vibevm-docs@1.0.0/reference/tree

.md.xmlllms.txt