Versions and updates
01A version is a promise about behaviour, not a snapshot of files. Your project asks for a range, vibe records the one number it chose, and an update moves that number on purpose. vibe itself follows the same rule: one number stands for one contract, however often the binary behind it is rebuilt.
vibe outdated --path hello-vibe
PACKAGE VERSIONS
GROUP NAME INSTALLED LATEST STATUS
org.vibevm.world wal 1.0.0 - unknown
0 of 1 package have updates available
Asking for a version
03Package versions follow semantic versioning: three numbers, where the first changes when a package breaks compatibility. In the manifest you name a constraint, not a version: ^1.0 means any 1.x from 1.0 up, =1.2.0 means exactly that one, and a bare coordinate means the newest stable release. The resolver picks one version per package that satisfies every constraint in the graph, and the lock file records the choice.
04
flow:wal@^0.3 → semver range.
05
flow:wal → latest stable.
06A family of packages that must move together pins its members exactly, so that a language guide and the server that serves its tools always resolve to one version set. You will meet these pins in the manifests of bundles; they are deliberate.
07 The aggregator's exact pins are deliberate, not kind-mandated: a stack may pin its dependencies however it likes, but a family is a tested version set, so the aggregator holds its members equal.
Moving the pin
08vibe outdated reads the lock file and the registry and lists the packages with a newer version available; it changes nothing. vibe update re-resolves and moves the pins, preferring to keep every package you did not name at its current version, so that updating one package does not silently drag the others along.
09
DepSolver trait — minimal additions. The trait gains one method:
10After an update the dependency tree and the boot files are regenerated, and the diff of the lock file is the change log of what your agent will now read.
What a version promises
11A version number is a contract: version 1 does what version 1 is documented to do. Inside a version the files behind it may be rebuilt, corrected or re-published, and a reader of the documentation does not see that kitchen. This is also how vibe treats its own releases. The binary you get from vibe self install latest is whatever the main branch holds today, under one version number. The manual describes the contract of that number rather than the files of one build.
12
A version is a behavioural contract, not a frozen set of files. Inside a version the product changes as often as it likes — amend, rewritten history, vibe self update --force — and this is invisible by design. The only event by which the documentation computes «a difference between versions» is the owner's conscious bump of the version number: no checksums, no file hashes, no history.
13A package version is a snapshot by default, in the sense the word has in Maven: its content may change under the same number, and vibe update brings the fresh content. A frozen version is the exception a publisher declares. Before the first public release, breaking changes ship without migration notes; the switch that ends that regime is the owner's alone.
14 2a. Frozen and snapshot versions (owner rulings, 2026-08-10; terminology fixed 2026-08-13). A version is a snapshot by default — the word carries its Maven sense, mutable: content may change under the same version string,vibe updatebrings the fresh content without regard for hash continuity, and the lockfile pins the delivered capture'scontent_hashplus an opaque provider locator for reproduction. The freeze is the package author's one-way act:frozen = truein the manifest — never a registry's opinion, never part of the version string. The carrier decisions and their reasons: (i) the flag lives inside the hashed content, so a frozen version self-describes even offline and every registry serving those bytes necessarily agrees — in a multi-registry world with no global journal, content is the only carrier that cannot diverge; registries merely observe a freeze in their journals and project it into catalogs; (ii) the version string carries version ordering only — two entities never share one name, which keeps the full matrix expressible: a frozen prerelease (an immutable published beta) and a mutable bare version (being stabilised in place) are both legal; (iii) the transition is one-way and single — unfreezing is forbidden, further work is a new version string; a registry may never accept a frozen coordinate's re-publication with different bytes; (iv) same coordinate + different bytes + any party claiming frozen = loud conflict through the candidate machinery, never a quiet pick. Every surface that shows a version shows its frozen state — machine outputs carry the field by schema; CLI, TUI, GUI and MCP render it always (the Maven lesson: mutability a human cannot see is mutability that will surprise them). Yank remains journal-borne — it is the act frozen content can no longer carry itself.
15 The pre-publication regime, and the switch only the owner can flip (owner ruling, 2026-08-10, near-verbatim: «я пока ничего не публиковал на большую публику… я хочу, чтобы мы не применяли миграции до тех пор, пока я не скажу, что состоялось первое представление публике… технически этот факт нельзя определить никак — только владелец может сказать, что это произошло»). Until that declaration the system is in the pre-publication regime: breaking is free and unmigrated — no codemods run, no bot PRs, no parallel worlds, no sunset calendars; break machinery reports instead of demanding (corpora regenerate freely, break notes are optional records); readers of old shapes are conveniences deletable at will; the standing user recipe is «regenerate / re-init / re-fetch». The fact of the first public presentation is technically undetectable by design and must never be inferred from technical events — not from a push, not from the default registry filling, not from a tag; any earlier «de-facto publication» reading is superseded by this ruling. The switch is one owner-only line (public = trueinformats/EPOCHS.toml), and flipping it is the single moment obligations, migrations, support windows and the handshake vow activate. The wave-0 slots (epoch markers, recipe identity, must-understand, yank) are still built early — not because the window is closing silently, but because they are cheap now, constrain today's breaking not at all, and are what makes the later freeze possible at all.
Versions of vibe itself
16The program manages its own versions with vibe self: self install builds a version from source or installs a verified bundle, self ls lists what the machine holds, self use switches the active one, and self rollback returns to the previous one. The selector latest means the tip of the main branch, stable the newest tagged release, and a plain X.Y.Z that tag.
17latest→ tip of branchmain.
18
stable → highest semantic-version git tag (the newest release).
19Switching versions never overwrites a running binary and never requires a new terminal: the active version is a pointer the shim follows on the next call.
20 Switching must not reload the console and must not overwrite a running file. (v1's "env is truth" violated the first; see §9.1.) The model has four layers:
21The manager looks after the program on the machine, not a project's dependencies, and its launcher folder goes on PATH once. self use repoints the active version; --eval prints a shell line for a one-terminal switch instead. self update follows where the running copy came from: a source checkout rebuilds at the tip, an installed binary moves to the newest published release. The same number is fetched again only when its release was rebuilt underneath it; self reinstall fetches the running version again without changing which one it is. self rollback swaps to the previous version and back again. The active version needs --force to be removed, and the copy that is running cannot be removed at all. Every prompt has a flag, so the whole thing works from a script or an agent, and vibe vars prints the variables the installation reads, without the publish token.
22
VVM manages the vibevm tool itself on the machine — a user-global
prefix, not a project's vibedeps/.
23
The shim dir on PATH (stable; set once).
24self use <selector>— make a version active by repointing the livecurrentfile — no console reload (§2.5).--evalprints the shell line for an integrity-checked shell-local override instead of touching the durable environment.
25self updatefollows the running origin, and moves versions FORWARD (owner ruling 2026-09-14, replacing the v1 rule that a binary execution refreshes its own number and never jumps). A source/worktree execution rebuilds its exact source root atlatest. A binary execution reads the release channel's newest-release aggregate manifest and goes to the newest published release: newer than the running version installs and activates it by the same verified path an explicitX.Y.Ztakes. The SAME version is not a no-op — a release may be rebuilt under its own number, so the manifest's bundle digest decides: changed bytes install a fresh immutable#N, unchanged bytes reuse the instance already held and cost no bundle download at all. A newest release OLDER than the running one (withdrawn on the far side) never walks the machine backwards.--forceinstalls a fresh#Nwhatever the digest says.self install stableenters this same path, sincestableIS the newest release (§2.3).
26self reinstallrefreshes the version that is RUNNING, without changing which version that is: a binary execution refetches its own release's manifest and bundle, a source/worktree execution rebuilds its exact source root — either way landing a fresh immutable#N. It takes no--force, because a fresh instance is the whole verb;--profile/--releasesteer the source lane exactly as onupdate. The pair is deliberate (owner ruling 2026-09-14): refetching the current version and moving to a new release are two acts, so they carry two names.
27self rollbackatomically swaps to the immediatepreviousinstance; repeating it toggles the two pointers without deleting either generation.
28
The active version and the running instance are protected:
removing an active but non-running instance needs --force; the actually
running instance is never removable, even with that flag.
29 It is fully scriptable: every interactive prompt has a non-interactive flag equivalent, so VVM works from a bare terminal, CI, or an agent transcript.
30vibe varsprints the project's env-configurable variables —VIBEVM_INSTALL_ROOT,VIBEVM_HOME(whose actual values are derived fromcurrent_exe, §2.5), plusVIBE_INVOKED_BY,VIBE_UNATTENDED,VIBE_LOG— inNAME=VALUEform. The publish token is deliberately excluded.
Edge cases and rules
31Two packages with the same coordinate and version but different bytes are two different things, and the second is refused. If a maintainer needs to re-publish, the version number changes.
32 Consequence. Fetching the same(kind, name, version)from two different URLs (canonical + mirror, original + fork, upstream + vendored copy) must produce the samecontent_hash. Mismatch is a fatalIntegrityError. The effect is:
33A branch used as a git source is the one exception to pinning by number: its lock entry records the commit that was installed, and an update walks the branch again.