# Install a package {#root}

@status:doc/work @audience:user

[p01] You 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.

[p02]
```prompt
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.
```

- needs: 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

outcome: `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

- assert: `grep -q "org.vibevm.world/wal" vibe.lock`
- assert: `vibe check --quiet`

## What happens {#what-happens}

[p03] The agent runs `vibe install org.vibevm.world/wal`. vibe walks the project's [registries](../glossary/index.xml#registry) 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](../glossary/index.xml#store), and verifies each [fingerprint](../glossary/index.xml#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.

> [p04] **Resolution** — the depsolver: read every node's `[requires]`, pick one version per package. It **must stay unified** (one `vibe.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).
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-011#PHASE-RESOLUTION>

## By hand {#by-hand}

[p05] 1. Install by [coordinate](../glossary/index.xml#coordinate). Add `@` and a constraint to ask for a range or an exact version:

[p06]
```sh
vibe install org.vibevm.world/wal --path hello-vibe --assume-yes
```

```output
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).
```

[p07] 2. Confirm the plan when asked. `--assume-yes` answers yes for scripts and agents.

[p08] 3. Check what was recorded and what the agent will read:

[p09]
```sh
vibe list --path hello-vibe
```

```output
KIND  NAME  VERSION  ROLE     BOOT SNIPPET
flow  wal  1.0.0    package  —

1 package installed.
```

[p10]
```sh
vibe tree --plain --path hello-vibe
```

```output
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 {#constraints}

[p11] `vibe 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](../glossary/index.xml#manifest) instead of a range. The manifest keeps the constraint you asked for; the [lock file](../glossary/index.xml#lock-file) keeps the version you got.

> [p12] `flow:wal@^0.3` → semver range.
>
> <spec://org.vibevm.core/vibevm/common/PROP-000#CF-RANGE>

[p13] A 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.

> [p14] resolved exactly; **kind validated against the manifest**
>
> <spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#ROW-QUALIFIED-KIND-BEHAVIOUR>

## After cloning a project {#after-a-clone}

[p15] `vibe 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.

> [p16] With the freshness check, **`vibe install` becomes lockfile-respecting**: unchanged `[requires]` ⇒ the locked versions are honoured verbatim.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-011#LOCKFILE-RESPECTING>

## Edge cases and rules {#edge-cases}

[p17] Installing 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.

> [p18] 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.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-011#HOLD-THE-LOCK>

[p19] A 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.

> [p20] **Current law.** Installing the package is the consent to run its declared
> hooks. There is no `[hooks].allowed_groups`, first-run prompt, or
> `--allow-hooks` permission 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.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-020#INSTALLATION-CONSENT-SUCCESSOR>

[p21] A package that is already installed is not installed twice: vibe says so and points at `vibe update`.

[p22] A 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.

[p23] A 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.

> [p24] After materialising a slot whose manifest declares `[[binary]]` entries,
>   `vibe install` MAY build them (v1: on `vibe bin sync`, see §4 — the
>   install itself only RECORDS the declarations; an install-time
>   `--build-bins` opt-in flag is v2 surface).
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-025#BUILD-TIMING>

> [p25] `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.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-025#BIN-BUILD>

> [p26] `vibe bin exec <name> [--] <args…>` — resolve `name` through 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.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-025#BIN-EXEC>

> [p27] **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-hooks` analogue; provider identity, artifact records and outcomes supply the audit trail. Existing direct `vibe bin` compatibility remains routed through its declared package rather than silently choosing ambient code.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-025#BUILD-CONSENT>

> [p28] 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.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-025#OFFLINE-HONESTY>

> [p29] A language-native consumer that needs a shipped
>   crate — a proc-macro that compiles *into* the consumer's own code (the
>   `specmark` case), or a binary it invokes (the `conform`/`specmap` case) —
>   references it **by path into the materialised slot**:
>
> <spec://org.vibevm.core/vibevm/common/PROP-024#PATH-DEP-LAW>

> [p30] The consumer **excludes** `vibevm/vibedeps/` (and, for a self-hosting repo, the
>   in-repo `vibevm/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.
>
> <spec://org.vibevm.core/vibevm/common/PROP-024#WORKSPACE-EXCLUDE>

