<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">Packages and their kinds</title>
  <status stage="doc" state="work" audience="user,author"/>
  <p p="1">Everything vibe installs is a package: a folder with a small description file and the text or tools it delivers. Packages come in eight kinds, and the kind tells you what a package is for before you open it: a way of working, a feature, a technology, a tool, a language guide, an agent server, documentation, or an application.</p>
  <example id="list" fixture="hello-vibe" p="2">
    <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>
  <section id="a-package" title="What a package is">
    <p p="3">A package is a project made installable. It has the same layout as a project, with its own `vibe.toml` and its own `vibevm/vibespecs/`, and it may carry code beside them. When a project installs it, the package's published tree is copied verbatim into the project's dependency tree; nothing is extracted, rewritten or merged.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-052#PACKAGES-CARRY-THE-LAYOUT-TOO" p="4"/>
    <p p="5">A package is named by a *[coordinate](../glossary/index.xml#coordinate)*: a group, a slash, and a name, as in `org.vibevm.world/wal`. The group looks like a reversed domain name and says who publishes; the name is unique within the group. A version completes the address when one is needed: `org.vibevm.world/wal@1.0.0`. The kind is not part of the name. It may be written as a prefix on the command line, `flow:org.vibevm.world/wal`, and then vibe checks that the package really is of that kind.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#IDENTITY-TUPLE" p="6"/>
    <p p="7">The group is a claim, not a credential: nothing checks that the publisher of `com.google/x` owns that domain, and nothing ever will, because vibe has no central verifier to ask. The name is unique within its group, so the coordinate alone is the identity. On the command line the kind prefix and the group are both optional; in a [manifest](../glossary/index.xml#manifest) the coordinate is always written in full. In a [registry](../glossary/index.xml#registry) the repository is named by joining group and name with a dot, `org.vibevm.world.wal`, which is itself a valid reversed domain name.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#GROUP-IS-A-CLAIM" p="8"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#NAME-UNIQUE-IN-GROUP" p="9"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#PKGREF-GRAMMAR" p="10"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#SHORT-CLI-ONLY" p="11"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-000#IDENTITY-FORM" p="12"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#JOINER-UNDERSCORE" p="13"/>
    <p p="14">Wherever a package is named in a project, the full coordinate stands: `group/name` in a requirement, `group.name` as a repository name, `group/name` as the first segment of a `spec://` address. Short names survive only as what a person types once at the command line.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-029#ADDR-LAW" p="15"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-029#CARRIER-PKGREF-FORM" p="16"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-029#CARRIER-REPO-NAME-FORM" p="17"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-029#CARRIER-SPEC-URI-FORM" p="18"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-029#ADDR-SHORT-NAMES" p="19"/>
  </section>
  <section id="the-kinds" title="The eight kinds">
    <table p="20">
      <tr>
        <td>Kind</td>
        <td>What it delivers</td>
        <td>Example</td>
      </tr>
      <tr>
        <td>`flow`</td>
        <td>a way of working: commit rules, session notes, review conventions; usually a [boot snippet](../glossary/index.xml#boot-snippet) the agent reads every session</td>
        <td>`org.vibevm.world/wal`</td>
      </tr>
      <tr>
        <td>`feat`</td>
        <td>a description of what to build, without saying how</td>
        <td>a welcome page, e-mail sign-in</td>
      </tr>
      <tr>
        <td>`stack`</td>
        <td>a technology context that says how a feature is built with it, or a bundle of a family's members at one version</td>
        <td>`org.vibevm.ai-native/rust-ai-native`</td>
      </tr>
      <tr>
        <td>`tool`</td>
        <td>a script or utility a build step can invoke</td>
        <td>a formatter wrapper</td>
      </tr>
      <tr>
        <td>`lang`</td>
        <td>guidance on how to write in a language or notation</td>
        <td>`org.vibevm.ai-native/rust-ai-native-lang`</td>
      </tr>
      <tr>
        <td>`mcp`</td>
        <td>a server an agent talks to, built from the package's own code</td>
        <td>`org.vibevm.ai-native/rust-ai-native-mcp`</td>
      </tr>
      <tr>
        <td>`doc`</td>
        <td>documentation of other packages: read, never installed</td>
        <td>`org.vibevm.core/vibevm-docs`</td>
      </tr>
      <tr>
        <td>`app`</td>
        <td>a standalone product with its own deployment</td>
        <td>`org.vibevm.doc/web`</td>
      </tr>
    </table>
    <p p="21">The set is closed and grows only by an amendment to the [specification](../glossary/index.xml#specification); a [manifest](../glossary/index.xml#manifest) with an unknown kind is rejected rather than guessed.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-000#KIND-SET" p="22"/>
    <p p="23">The kind is metadata about the package, not part of its identity: it decides where content is placed, what the `--kind` filter of `vibe list` and `vibe search` shows, and whether a kind-prefixed name is accepted. Two packages of different kinds may not share a coordinate, because the coordinate alone is the identity.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#KIND-METADATA" p="24"/>
    <p p="25">An `app` differs from a `tool` mechanically: a tool lives in a project and runs through `vibe bin exec` by the lock file, while an app runs in no consumer project and is built and deployed on its own.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-057#KIND-APP-VS-TOOL" p="26"/>
  </section>
  <section id="families" title="Families and companions">
    <p p="27">Some [capabilities](../glossary/index.xml#capability) arrive as several packages that share a name stem: the language guide, the server that serves its tools, and a small bundle that pins both at one version. This is a *family*. Requiring the bundle installs the family, and a change to any member bumps every member to one shared version, so the pieces can never drift apart.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-028#UNISON-LAW" p="28"/>
    <p p="29">The bundle itself is the smallest package there is: a manifest and a README, no code and no [boot snippet](../glossary/index.xml#boot-snippet). Its one job is to name the family's members at one version.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-028#ROLE-AGGREGATOR" p="30"/>
    <p p="31">Documentation is the exception. A package's manual is its *[companion](../glossary/index.xml#companion)*, named with the suffix `-docs` in the same group, and it keeps its own version line. A fixed typo in the manual does not release the tools, and a new tool version does not demand a new manual. The manual says which versions of its [subject](../glossary/index.xml#subject) it describes, and the site picks the newest manual that fits.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-028#ROLE-DOCS" p="32"/>
  </section>
  <section id="on-disk" title="How a package lands on disk">
    <p p="33">`[package].materialization` says how a package arrives in a consumer's tree. `copy` is the default and all an ordinary package needs; `hardlink` is the same content sharing bytes with the [store](../glossary/index.xml#store). Both are vendored: the folder is committed with the project and restores offline from it. `in-place` keeps a live git checkout with its own `.git`, ignored by git and restored by a fresh clone at the locked commit, so it needs the network and a [git source](../glossary/index.xml#git-source). Anything destructive on such a slot, an uninstall, a forced reinstall or a version switch, asks first, or needs `--force` when nobody can answer.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-022#MODE-FIELD" p="34"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-022#SNAPSHOT-DEFAULT" p="35"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-022#VENDORED-COPY-MODES" p="36"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-022#IN-PLACE-NOT-VENDORED" p="37"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-022#IP-REQUIRES-GIT" p="38"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-022#DESTRUCTIVE-CONFIRM" p="39"/>
  </section>
  <section id="edge-cases" title="Edge cases and rules">
    <p p="40">Changing a package's group or name creates a new package, not a rename: versions do not carry across, and old coordinates are never reused for different content.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#GROUP-CHANGE-NEW-PACKAGE" p="41"/>
    <p p="42">A documentation package cannot be installed into a project. `vibe install` refuses it and names the command that fetches it for reading instead.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-057#KIND-DOC-NOT-INSTALLED" p="43"/>
    <p p="44">A short name without a group, such as `wal`, is accepted on the command line and resolved through the [registry](../glossary/index.xml#registry) [index](../glossary/index.xml#index-registry); it is convenience, and the manifest always records the full coordinate.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#ROW-SHORT-BEHAVIOUR" p="45"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#RESOLVE-ONCE-WRITE-QUALIFIED" p="46"/>
    <p p="47">Resolving a short name needs the index, one lookup per registry; a registry without one offers no short names, and the full coordinate is required. If the lock file already pins a package of that name, the short name means the locked one. When two registries offer different packages under one name, vibe stops with exit code 7 and lists the candidates, and you repeat the command with the group. A kind prefix checks the result and never disambiguates, because two packages of different kinds cannot share a coordinate.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#INDEX-DEPENDENCY" p="48"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#LOCKFILE-AUTHORITATIVE" p="49"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#COLLISION-BEHAVIOR" p="50"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#EXIT-CODE-7" p="51"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#KIND-VALIDATION" p="52"/>
  </section>
</spec>
