Install a package
01You found a package your project should follow. This page adds it to the project, records the exact version, and shows how to check that your agent will now read it.
Install the package org.vibevm.world/wal into the VibeVM project in the current folder, accept the plan, and tell me which version was recorded and what the agent will read from it at session start.
the vibevm skill installed for your agent; a project with vibe.toml in the current folder; network access to the project's registries, or the package already in the machine store
vibe.toml lists the package under its requirements, vibe.lock pins one version with its content fingerprint, the package's tree sits under vibevm/vibedeps/, and vibe tree shows its boot snippet in the reading list
grep -q "org.vibevm.world/wal" vibe.lockvibe check --quiet
What happens
03The agent runs vibe install org.vibevm.world/wal. vibe walks the project's registries in order and asks the first one that knows the package for its versions; with no constraint given, it picks the newest stable release. It resolves the package's own dependencies with the rest of the project's graph, fetches everything that is not yet in the machine store, and verifies each fingerprint. Then it prints a plan: which packages will be added at which versions, and which files will change. Nothing is written until you confirm. On confirmation vibe copies the packages into vibevm/vibedeps/, records the requirement in vibe.toml and the pins in vibe.lock, and regenerates the boot files. Then the agent runs vibe tree to show you the new reading list.
04 Resolution — the depsolver: read every node's[requires], pick one version per package. It must stay unified (onevibe.lock, one version per package across the workspace — the diamond problem; PROP-007 §2.4). It cannot be computed per-subtree. But it can be skipped entirely when its inputs are unchanged (§2.2).
By hand
051. Install by coordinate. Add @ and a constraint to ask for a range or an exact version:
vibe install org.vibevm.world/wal --path hello-vibe --assume-yes
Resolving 1 root package…
Materialising 1 package into vibedeps/:
org.vibevm.world/wal@1.0.0
closure diff:
→ + org.vibevm.world/wal@1.0.0 (root-edge)
→ lane vibevm/vibespecs/boot/INDEX.md: 737 -> 854 B
Materialised 1 package into vibedeps/; regenerated boot artifacts for 1 node(s).
072. Confirm the plan when asked. --assume-yes answers yes for scripts and agents.
083. Check what was recorded and what the agent will read:
vibe list --path hello-vibe
KIND NAME VERSION ROLE BOOT SNIPPET
flow wal 1.0.0 package —
1 package installed.
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 . . .
Asking for a version
11vibe install org.vibevm.world/wal@^1.0 accepts any 1.x; @=1.0.0 accepts exactly one; --exact writes the resolved version as an exact pin into the manifest instead of a range. The manifest keeps the constraint you asked for; the lock file keeps the version you got.
12
flow:wal@^0.3 → semver range.
13A kind prefix, as in flow:org.vibevm.world/wal, is optional; when present, vibe checks it: if the package turns out to be of another kind, the install stops.
14 resolved exactly; kind validated against the manifest
After cloning a project
15vibe install with no package names installs what the manifest already requires, at the versions the lock file pins. When neither the manifest nor the lock changed since the last install, vibe does not even run the resolver: the lock file is the answer, and the command only checks that the tree matches it.
16 With the freshness check,vibe installbecomes lockfile-respecting: unchanged[requires]⇒ the locked versions are honoured verbatim.
Edge cases and rules
17Installing a package by name re-resolves the whole graph, but every dependency the change does not touch keeps its pinned version; only a real conflict triggers a full re-resolution.
18
When [requires] has changed, resolution runs, but holds the lock for every dependency the change did not touch (§5.3): each registry-resolved root the lock still satisfies is pinned to its locked version, so the re-resolve never drifts an untouched dependency — only the changed one and its subtree move.
19A package may declare a script to run after it is installed. Installing the package is the consent to run it; the script runs inside the package's own folder and its effects are not tracked. Read the manifest of a package you do not trust before installing it.
20 Current law. Installing the package is the consent to run its declared hooks. There is no[hooks].allowed_groups, first-run prompt, or--allow-hookspermission layer. Safety is the PROP-054 observability model: the manifest is statically inspectable, selected contributions are narrated, and durable run evidence identifies what ran and which package supplied it.
21A package that is already installed is not installed twice: vibe says so and points at vibe update.
22A public registry that answers with an authentication error for a missing package is walked past, not treated as a failure; add --auth-required in a script that must notice a private registry being down.
23A package that delivers tools is recorded at install and built on demand: vibe bin build compiles the named tools, or all of them, from the exact installed package, and vibe bin exec <name> resolves the tool through the project's lock file to its folder and runs it, building first if needed. Installing the package is the consent to build, and vibe narrates what it is about to compile. Offline, a build that needs crates from the network fails the way Cargo fails, with the manual recipe as a hint. When your own code needs a shipped crate, reference it by path into the package's folder, and keep vibevm/vibedeps/ out of your Cargo workspace, because a folder cannot belong to two workspaces.
24 After materialising a slot whose manifest declares[[binary]]entries,vibe installMAY build them (v1: onvibe bin sync, see §4 — the install itself only RECORDS the declarations; an install-time--build-binsopt-in flag is v2 surface).
25
vibe bin build [<name>…] — release build of the named tools (default: all declared) through their exact installed package and Cargo declaration; installation is the consent and the selected work is narrated.
26vibe bin exec <name> [--] <args…>— resolvenamethrough the CURRENT project's lockfile → its slot → the slot-resident artifact (building the declared package target if absent), then execute with the exit code passed through. This is the rustup dispatch model: the project's pinned version is what runs, always.
27 Successor to the historical first-build prompt. Building executes package build scripts and proc-macros, so installation plus explicit target/route selection is the authorisation and the engine narrates the exact provider and target before execution. Lifecycle build does not add an allow-list, first-run prompt or--allow-hooksanalogue; provider identity, artifact records and outcomes supply the audit trail. Existing directvibe bincompatibility remains routed through its declared package rather than silently choosing ambient code.
28
Cargo needs crates.io for third-party deps unless the
local cargo cache is warm: offline boxes get the same honest failure
cargo gives, plus the hint that cargo install --path <slot>/crates/…
(the documented degraded path, which stays valid indefinitely) has the
same network shape — there is no offline shortcut to a first build.
29 A language-native consumer that needs a shipped crate — a proc-macro that compiles into the consumer's own code (thespecmarkcase), or a binary it invokes (theconform/specmapcase) — references it by path into the materialised slot:
30 The consumer excludesvibevm/vibedeps/(and, for a self-hosting repo, the in-repovibevm/vibepacks/source) from its[workspace], so the slot's crates belong to the package's workspace, not the consumer's — Cargo forbids a directory living in two workspaces, and this is the standard resolution for a repo that contains a sub-project with its own workspace.