<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">Install a package</title>
  <status stage="doc" state="work" audience="user"/>
  <p p="1">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.</p>
  <prompt id="install-a-package" p="2">
    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</needs>
    <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</outcome>
    <assert>grep -q "org.vibevm.world/wal" vibe.lock</assert>
    <assert>vibe check --quiet</assert>
  </prompt>
  <section id="what-happens" title="What happens">
    <p p="3">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.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-011#PHASE-RESOLUTION" p="4"/>
  </section>
  <section id="by-hand" title="By hand">
    <p p="5">1. Install by [coordinate](../glossary/index.xml#coordinate). Add `@` and a constraint to ask for a range or an exact version:</p>
    <example id="install" fixture="hello-vibe-empty" p="6">
      <run>vibe install org.vibevm.world/wal --path hello-vibe --assume-yes</run>
      <expect>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 -&gt; 854 B

Materialised 1 package into vibedeps/; regenerated boot artifacts for 1 node(s).</expect>
    </example>
    <p p="7">2. Confirm the plan when asked. `--assume-yes` answers yes for scripts and agents.</p>
    <p p="8">3. Check what was recorded and what the agent will read:</p>
    <example id="list" fixture="hello-vibe" p="9">
      <run>vibe list --path hello-vibe</run>
      <expect>KIND  NAME  VERSION  ROLE     BOOT SNIPPET
flow  wal  1.0.0    package  —

1 package installed.</expect>
    </example>
    <example id="tree" fixture="hello-vibe" p="10">
      <run>vibe tree --plain --path hello-vibe</run>
      <expect>project: &lt;TMP&gt;/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  .  .  .</expect>
    </example>
  </section>
  <section id="constraints" title="Asking for a version">
    <p p="11">`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.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-000#CF-RANGE" p="12"/>
    <p p="13">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.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#ROW-QUALIFIED-KIND-BEHAVIOUR" p="14"/>
  </section>
  <section id="after-a-clone" title="After cloning a project">
    <p p="15">`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.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-011#LOCKFILE-RESPECTING" p="16"/>
  </section>
  <section id="edge-cases" title="Edge cases and rules">
    <p p="17">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.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-011#HOLD-THE-LOCK" p="18"/>
    <p p="19">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.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-020#INSTALLATION-CONSENT-SUCCESSOR" p="20"/>
    <p p="21">A package that is already installed is not installed twice: vibe says so and points at `vibe update`.</p>
    <p p="22">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.</p>
    <p p="23">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 &lt;name&gt;` 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.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-025#BUILD-TIMING" p="24"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-025#BIN-BUILD" p="25"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-025#BIN-EXEC" p="26"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-025#BUILD-CONSENT" p="27"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-025#OFFLINE-HONESTY" p="28"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-024#PATH-DEP-LAW" p="29"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-024#WORKSPACE-EXCLUDE" p="30"/>
  </section>
</spec>
