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 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 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 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 [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 Decision. vibe.lock gains schema_version = 2 and the following record shape per package:
10 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 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 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 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 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 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