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

The lock file: vibe.lock

01vibe.lock is the file vibe writes and you commit: the exact versions the project got. This page explains every field so you can read a diff of it in a pull request and know what changed.

Where it lives and who writes it

02There is one vibe.lock per workspace, at the absolute root, beside the root manifest; members never have their own. vibe install and vibe update write it; vibe clean keeps it; nothing edits it by hand. It is the recorded decision; the dependency tree on disk is only its consequence and can always be rebuilt from it.

03 spec: Nesting is hierarchical grouping, not independent…
Nesting is hierarchical grouping, not independent resolution domains. The lockfile and unified resolution always live at the absolute root of the workspace tree. A nested [workspace] provides (a) the [workspace.versions] matryoshka (§2.6) and (b) logical grouping of members — never its own lockfile, never its own resolution pass.
04 spec: Never touched — vibe.lock
Never touched — vibe.lock. The lock is the recorded resolution, not derived state: keeping it is what makes vibe clean install --offline reproduce the exact world from the machine cache with zero network — the mvn analogy is target/ vs the dependency resolution, and the lock sits on the resolution side.

[meta]

05
Field Meaning
generated_by, generated_at the vibe version and the time of the last write; informational
schema_version the lock schema; an older vibe refuses a newer schema rather than misreading it
solver the resolver that produced the graph
root_dependencies the coordinates the manifests asked for directly; the baseline of the freshness check
language_chain the resolved language preference and its fallbacks, so a re-install on another machine materialises the same files
06 spec: The freshness check itself adds no…
The freshness check itself adds no vibe.lock field: the lockfile is the baseline, and the check is a cargo-style satisfiability test of the locked versions against the current [requires] — see §5.1.
07 spec: [meta].language_chain (§2.7.5) — shipped as one…
[meta].language_chain (§2.7.5) — shipped as one ordered field merging the preference and its fallback, not the language + language_fallback pair this section drafted.

08root_dependencies copies the manifest's [requires.packages], so the lock file is a self-contained snapshot that needs no manifest to read. Removing a root with vibe uninstall drops it from both files; removing a package that is only a transitive dependency is refused with an explanation.

09 spec: Decision: vibe.lock gains schema_version = 2…
Decision. vibe.lock gains schema_version = 2 and the following record shape per package:
10 spec: root_dependencies is a mirror of vibe.toml…
root_dependencies is a mirror of vibe.toml [requires].packages — the lockfile keeps the user's declared roots inline so it remains a self-contained snapshot of the solve state (nothing inside vibe.lock requires reading vibe.toml to interpret). The source of truth for what the user asked for is the manifest's [requires] section; the lockfile carries a copy plus the resolved transitive closure. vibe uninstall of a root drops the entry from both files; vibe uninstall of a pure transitive is rejected with an explanation.

[[package]]

11
Field Meaning
group, name, version the coordinate that was resolved
kind the package's kind, for placement and filters
content_hash the fingerprint of the package's shippable tree; the identity; verified on every fetch
registry the name of the registry that answered, from the manifest's list
source_url, source_ref, resolved_commit where and at what git ref the bytes were fetched this time; informational, always the canonical address even when a mirror served
source_kind registry, git, override or path: which resolution path produced the entry; for path the URL field holds the member's folder relative to the root
dependencies the resolved dependencies of this package, as exact coordinates
overridden true when an [[override]] supplied the package
features, subskills the active features and subskills recorded for the package
files_written the project files this package's install wrote outside its own folder, so that uninstall can remove exactly them
via_redirect the address of the registry stub that delegated the package elsewhere, when one was followed; absent otherwise
12 spec: Decision: A package's identity…
Decision. A package's identity is the tuple (kind, name, version, content_hash). The content_hash is a digest over the deterministically-ordered concatenation of (rel_path_bytes || 0x00 || file_bytes || 0x00) for every file in the package directory, and the value names the recipe that produced it (PROP-044 §4.7): sha256-tree/1:<hex> is recipe 1, whose exclusion list, path normalisation and traversal order are carried as data in formats/hash_recipes/1.toml; the bare sha256:<hex> is recipe 0, the pre-recipe form, frozen verbatim in code — not configurable, because a frozen recipe that can be edited is not frozen — so that values written before recipes were named stay readable. Two hashes are comparable only at the same recipe; comparing across recipes answers a question nobody asked, and is never done silently. PROP-024 §2.2 re-scopes this to the package's shippable tree — its source, minus build output (.git/, .vibe/, target/, node_modules/, .vibeignore globs) — so a code-bearing package's identity is its source, not its build state; that exclusion lands with the code that implements it. The URL used to fetch the content is informational — recorded in the lockfile for debuggability, not for identity.
13 spec: source_kind is "registry" for the M1.13…
source_kind is "registry" for the M1.13 default, "git" for git-source declarations, "override" for [[override]]-resolved (existing overridden = true is preserved as redundant marker for back-compat). Lockfile schema bumps to v3; v2 lockfiles read transparently and migrate to v3 on next install (everything that was overridden = true becomes source_kind = "override"; everything else "registry").
14 spec: The canonical URL is always recorded…
The canonical URL is always recorded as the source_url in the lockfile when the fetch produces a new pin. Mirror URLs do not appear there.

Reading a diff

15A changed version with a changed content_hash is an update. A changed content_hash with the same version is impossible in a healthy world: vibe refuses it at fetch time, so if you see it in a diff someone edited the file. A changed source_url alone is a mirror or a host migration and means nothing for the project. A new entry with source_kind = "override" is a patch someone applied on purpose and should carry a reason in the commit message.

16 quote from the specification
mirror-switching, host-migration, and vendoring never change the lockfile;

Edge cases and rules

17An unchanged manifest against an unchanged lock file makes vibe install skip the resolver entirely: the lock is the answer.

18 spec: With the freshness check, vibe install…
With the freshness check, vibe install becomes lockfile-respecting: unchanged [requires] ⇒ the locked versions are honoured verbatim.

19The lock file records no registry index and no mirror: reproducing it needs only the coordinates, the fingerprints and a source that can serve them.

20vibe why <coordinate> explains from the lock file and the manifests why a package is in the project, or what blocked it.

21The file is read strictly: a field vibe does not know is an error, not a warning, so a hand edit or a field from a newer vibe is caught at once.

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/reference/lock-file

.md.xmlllms.txt