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

Packages and their kinds

01Everything 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.

02
vibe list --path hello-vibe
KIND  NAME  VERSION  ROLE     BOOT SNIPPET
flow  wal  1.0.0    package  —

1 package installed.

What a package is

03A 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.

04 L4 — packages too. Every package root mirrors the same layout (vibevm/vibespecs inside the package instead of spec/); materialisation mirrors package layout into the slots, boot-snippet paths and INDEX targets follow.

05A package is named by a 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.

06 Decision. Package identity becomes (group, name, version, content_hash). kind leaves the identity tuple.

07The 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 the coordinate is always written in full. In a 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.

08 Decision (owner ruling, 2026-08-13). A group is a claim, not a credential. Nothing verifies that the author of com.google/x owns google.com — and nothing ever will: vibevm is decentralised and has no central verifier to delegate to (Maven's central domain verification is the model we deliberately do not inherit). The claim's grammar is domain-shaped (§2.1); its semantics carry no domain-ownership assertion.
09 name becomes unique within a group (was: within a kind, VIBEVM-SPEC.md §7.1). (group, name) is therefore unique on its own — kind is no longer needed to disambiguate.
10 Decision. The pkgref grammar gains an optional group segment and makes the kind prefix optional:
11 The short form is CLI-only sugar. It is never written to a manifest (§2.6).
12 Decision: [<kind>:]<group>/<name>@<version> — identity is qualified since M1.19 (PROP-008 §2.2); the unqualified <kind>:<name>@<version> of VIBEVM-SPEC.md §7.1 is CLI sugar that resolves once, at the human boundary.
13 naming = "fqdn" maps a pkgref to the repository name <group>.<name> (org.vibevm.world/walorg.vibevm.world.wal) — the composite is itself a valid reversed FQDN, and that is the point of the ruling. Owner ruling 2026-08-13 («убери подчёркивания везде, чтобы получились настоящие FQDN с доменными правилами»), superseding the 2026-05 _-joiner decision recorded in this unit's earlier text. The split stays deterministic without a charset-excluded joiner: the name is a single dot-free LDH label (validate_package_name), so the last dot is always the boundary — parse back by taking the last label as name, the rest as group. The old rationale's premises are both gone: _ was then legal inside groups (no longer — §2.1 LDH), and the composite was not required to be a domain (now it is). Considered and rejected: keeping _ (the composite is not even formally a domain; and a _-joined name contradicts the LDH ruling the halves now obey). Migration: live _-joined repositories in vibespecs (M0/M1 scale) rename to the dot form as a follow-up of the 2026-08-13 landing — pre-public and cheap, and GitHub redirects renamed repositories; the §3 history below records the _-era as it happened and is not rewritten. Revisit: a hosting provider that forbids . in repository names appears in the registry set — then that provider's adapter gets its own naming value, never a silent re-join.

14Wherever 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.

15 A package address MUST carry its full coordinate — group and name — in every occurrence across the project:
16 [<kind>:]<group>/<name>
17 <group>.<name>/ is illegal in a repo name; the name is the last label
18 <group>/<name> — the name is the first path segment
19 Short or bare names survive only as a one-time human CLI input, resolved to the qualified form at the boundary (PROP-008 §2.6).

The eight kinds

20
Kind What it delivers Example
flow a way of working: commit rules, session notes, review conventions; usually a boot snippet the agent reads every session org.vibevm.world/wal
feat a description of what to build, without saying how a welcome page, e-mail sign-in
stack a technology context that says how a feature is built with it, or a bundle of a family's members at one version org.vibevm.ai-native/rust-ai-native
tool a script or utility a build step can invoke a formatter wrapper
lang guidance on how to write in a language or notation org.vibevm.ai-native/rust-ai-native-lang
mcp a server an agent talks to, built from the package's own code org.vibevm.ai-native/rust-ai-native-mcp
doc documentation of other packages: read, never installed org.vibevm.core/vibevm-docs
app a standalone product with its own deployment org.vibevm.doc/web

21The set is closed and grows only by an amendment to the specification; a manifest with an unknown kind is rejected rather than guessed.

22 kind ∈ {flow, feat, stack, tool, mcp, lang, doc, app} — eight kinds; mcp shipped with PROP-027; doc and app admitted by PROP-057 through the VIBEVM-SPEC.md §4.1 amendment of 2026-09-12 (pending the owner's ratification at the merge of the docs-2026-09 branch; the code learns the two kinds in that campaign's phase 2). (§Invariants INV-VOCABULARY in this file carries the same list.)

23The 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.

24 Decision. kind (flow / feat / stack / tool) stays a mandatory [package] field but is now a pure attribute — it identifies nothing and names nothing.

25An 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.

26 The boundary with tool is mechanical: a tool lives in a project and runs through vibe bin exec by the lock file; an app runs nowhere in a consumer project and is built and deployed on its own.

Families and companions

27Some capabilities 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.

28 Within a family the members move in unison: a content change to any member bumps EVERY member of that family to one shared version, and the aggregator's version IS that family version.

29The bundle itself is the smallest package there is: a manifest and a README, no code and no boot snippet. Its one job is to name the family's members at one version.

30 <family> — the aggregator. kind = "stack", content-minimal: a vibe.toml and a README.md, and nothing else — no code, no boot snippet, no specmap.toml / conform.toml. Its whole job is to name the family's members at one resolved version set through exact =X.Y.Z pins in [requires]. Requiring the aggregator installs the family.

31Documentation is the exception. A package's manual is its 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 it describes, and the site picks the newest manual that fits.

32 <family>-docs — the documentation companion (kind = "doc", PROP-057 §3): the official-by-default documentation of the family's subject, in the subject's group. Unlike the three code roles it is a companion, not a member: it is never pinned by the aggregator, it does not take part in the family's unison (§2.2), it keeps its own version line, and it states compatibility with its subject through the version constraint of its [[documents]] table. Its translations follow the same companion form, one package per language, named <family>-docs-<lang> with a lower-case BCP-47 tag (rust-ai-native-docs-ru). Amended 2026-09-11.

How a package lands on disk

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. 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. Anything destructive on such a slot, an uninstall, a forced reinstall or a version switch, asks first, or needs --force when nobody can answer.

34 [package].materialization selects how the package lands on disk:
35 copy is the default and the only mode an ordinary package needs. (It was named snapshot until the owner's 2026-08-13 terminology ruling reserved that word for the unfrozen version — PROP-044 §2b; the legacy spelling is refused with the rename recipe, never aliased.)
36 copy / hardlink are vendored — the slot is committed into the project's git and is offline-reproducible from it (a hardlink slot's bytes are materialised into git on git add like any file); a copy slot trivially so.
37 in-place is not vendored — the slot (a nested .git plus possibly millions of files) is .gitignored in the project; restoration is a re-clone at the lockfile's resolved_commit. The honest trade: in-place packages need the network to restore, where snapshot packages do not.
38 Requires a git source. Incremental update and git clean reset both need git; a non-git source has no in-place story (§4).
39 An in-place slot may be a multi-hour download. Any destructive operation on it — uninstall, reinstall --force, a version switch that requires a re-clone, or slot removal — must be confirmed: interactively a y/n, and in a non-interactive run it requires an explicit flag (--force) or it aborts rather than silently deleting an expensive resource.

Edge cases and rules

40Changing 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.

41 Changing a package's group is a new package, not a rename — same discipline as changing name.

42A documentation package cannot be installed into a project. vibe install refuses it and names the command that fetches it for reading instead.

43 vibe install MUST refuse a doc package with a hint naming the warm-up command; documentation is warmed into the machine store with vibe cache add (§11), and the local reader and vibe explain read the store.

44A short name without a group, such as wal, is accepted on the command line and resolved through the registry index; it is convenience, and the manifest always records the full coordinate.

45 resolved via the index (§2.6)
46 vibe install wal resolves the collision once, at the top level, and writes org.vibevm.world/wal into [requires]. Manifests are therefore always qualified — exactly the cargo/npm pattern (cargo add serde on the CLI, serde = "1" in Cargo.toml).

47Resolving 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.

48 Index dependency. Resolving a short name requires enumerating candidates (*, name) across registries. The host cannot list an org cheaply (PROP-005 §1 — GitVerse exposes no org listing, GitHub is rate-limited). Therefore short-name resolution requires PROP-005: one HTTP GET of by-name/<name>.json per registry yields the candidate set. Without an index, a registry's short names are unavailable and the qualified form is required.
49 Lockfile is authoritative. If vibe.lock already pins org.vibevm.world/wal, a later vibe install wal resolves to the locked entry — the short name prefers what is already locked.
50 One candidate → resolve. Multiple candidates with different identity → collision:
51 A new exit code 7 ("ambiguous package") is assigned, distinct from 3 ("package conflict", VIBEVM-SPEC.md §9.4).
52 kind validation. If the kind prefix is present, after resolution the resolver asserts resolved.kind == prefix; mismatch is a KindMismatch error. A kind prefix is validation + a UX signal — it does not disambiguate, because by §2.2 name is unique within a group, so flow:org.vibevm.world/wal and feat:org.vibevm.world/wal cannot co-exist. A short-name collision is always a group collision (§2.7), resolved by group-qualification, never by kind.

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/model/packages-and-kinds

.md.xmlllms.txt