<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">Registries and the index</title>
  <status stage="doc" state="work" audience="user"/>
  <p p="1">Packages are published to a place vibe knows how to read: by default a public organisation on GitHub, one repository per package. A project lists such places in the order it trusts them. A catalogue beside each one answers searches without cloning anything.</p>
  <example id="registry-list" fixture="hello-vibe" p="2">
    <run>vibe registry list --path hello-vibe</run>
    <expect>No `[[registry]]` entries in `vibe.toml`. Use `--registry &lt;path&gt;` on `vibe install` for a local-directory source, or add a `[[registry]]` block.</expect>
  </example>
  <section id="what-a-registry-is" title="What a registry is">
    <p p="3">A [registry](../glossary/index.xml#registry) is not a server vibe runs. It is a hosting organisation, such as `https://github.com/vibespecs`, where every package is its own git repository named after the package's [coordinate](../glossary/index.xml#coordinate). Publishing means pushing a repository and tagging a version; installing means cloning at a tag. Who may publish is decided by the hosting service's own permissions, so vibe carries no accounts of its own.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#SHAPE-OWN-REPO" p="4"/>
    <p p="5">A project declares its registries in the [manifest](../glossary/index.xml#manifest) as an ordered list. Each entry has a local name, the organisation's root address, and a naming convention that maps a coordinate to a repository name. When a package is requested, vibe walks the list in order and the first registry that has a matching version wins.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#REGISTRY-WALK-ORDER" p="6"/>
    <p p="7">The list is an array in priority order; beside it a [mirror](../glossary/index.xml#mirror) is a second address for the same registry, and an [override](../glossary/index.xml#override) bypasses the walk for one coordinate. An entry's `url` is the organisation's root, never a package repository, and it is a plain git address, `https://`, `ssh://`, `git@host:` or `file://`, with no shorthand for any particular host. Its `naming` says how a coordinate becomes a repository name; the default joins the group and the name with a dot.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#SHAPE-REGISTRY-ARRAY" p="8"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#REG-FIELD-URL" p="9"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#SHAPE-PLAIN-GIT-URL" p="10"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#REG-FIELD-NAMING" p="11"/>
    <p p="12">The walk moves on to the next registry only when one answers that it does not have the package. A connection failure, a server error or a malformed manifest stops the install with that error, because an outage or a typo is something you want to know about. On a registry declared public, a demand for credentials counts as «not here» and the walk continues; on a registry that declares an authentication regime, it is a real failure.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#REGISTRY-WALK-SEMANTICS" p="13"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#AUTH-AWARE-401" p="14"/>
    <p p="15">An entry can be switched off without being deleted: `enabled = false` makes every command skip that registry until you flip it back.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#ENABLED-FLAG" p="16"/>
    <p p="17">A machine may add registries of its own in `~/.vibe/registry.toml`, merged after the project's; a project's list always wins over the machine's. This is how a company points every project on a laptop at its private registry without editing each project. The file carries the same `[[registry]]`, `[[mirror]]` and `[[override]]` sections as a project manifest, for any registry, remote or local; a name declared in both places is the project's.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#PROJECT-OVERRIDES" p="18"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#GLOBAL-REGISTRY-FILE" p="19"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#MERGE-PROJECT-FIRST" p="20"/>
    <p p="21">The default trust set the [specification](../glossary/index.xml#specification) names is exactly two roots, `https://github.com/vibespecs` and `https://gitverse.ru/vibespecs`. A project `vibe init` creates today carries no registry block at all, so before the first install add one with `vibe registry add`, or let the machine-wide file supply it. Every other registry is trusted only because you added it.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-008#DEFAULT-TRUSTED-REGISTRIES" p="22"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-000#INIT-DEFAULT-REGISTRY" p="23"/>
  </section>
  <section id="the-index" title="The index">
    <p p="24">Cloning a repository to learn what is in it is slow, and listing an organisation to search it is impossible without an account. So a registry may keep an *[index](../glossary/index.xml#index-registry)*: a separate repository beside the packages that records, for every published version, the manifest's summary and the content [fingerprint](../glossary/index.xml#fingerprint). `vibe search` reads the index; a fresh install reads it to skip a round of clones.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-index/PROP-005#INDEX-OPTIONAL" p="25"/>
    <p p="26">The index is a cache, never the truth. If it disagrees with a package repository, the repository wins, and a package resolved through the index is still verified against its content fingerprint when it arrives. A registry without an index works exactly as before, only slower; a missing index is not an error.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-index/PROP-005#REPOS-AUTHORITATIVE" p="27"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-index/PROP-005#REALITY-WINS" p="28"/>
    <p p="29">The index location is derived from the registry's address and can be overridden per registry with an environment variable named after the registry, `VIBEVM_INDEX_URL_&lt;NAME&gt;`; the literal value `none` switches index lookups off for that registry.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-index/PROP-005#INDEX-URL-TODAY-IS-AN-ENVIRONMENT-VARIABLE" p="30"/>
    <p p="31">A registry entry may pin its index with `index_url`; without one, a public GitHub organisation maps to its `index` repository on the raw content host and any other host to `&lt;registry-url&gt;/index`. A probe of the index has three outcomes: found, absent, or refused. Only absent falls through quietly to a live listing, because nobody promised an index; an index that is there and cannot be read is reported. `vibe search` asks each configured index the question directly rather than downloading the whole catalogue.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-index/PROP-005#INDEX-URL-CONFIG" p="32"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-index/PROP-005#INDEX-URL-DEFAULT" p="33"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-index/PROP-005#A-PROBE-HAS-THREE-OUTCOMES-NOT-TWO" p="34"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-index/PROP-005#AN-ABSENT-INDEX-FALLS-BACK-WITHOUT-A-WORD" p="35"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-index/PROP-005#INT-SEARCH" p="36"/>
  </section>
  <section id="mirrors-and-overrides" title="Mirrors, overrides and git sources">
    <p p="37">A *mirror* is another address for the same registry, tried first for availability and verified against the same fingerprints; a mirror that serves different bytes for a known version is refused, not trusted. Mirrors never appear in the [lock file](../glossary/index.xml#lock-file): the canonical address is what gets recorded, so switching mirrors changes nothing for your teammates.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#MIRROR-INTEGRITY-MANDATORY" p="38"/>
    <p p="39">An *override* replaces one package with a copy from elsewhere, for a hotfix or a patch waiting upstream; it short-circuits the registry walk for that one coordinate and is marked as such in the lock file, so nobody mistakes it for a published version.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#OVERRIDE-SHORT-CIRCUIT" p="40"/>
    <p p="41">An override relaxes nothing: the copy's fingerprint is still pinned in the lock file and verified on every install, and the entry carries `overridden = true`.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#OVERRIDE-SEMANTICS" p="42"/>
    <p p="43">A dependency may also point straight at a git repository, at a tag, a commit or a branch. A tag and a commit are pinned; a branch is re-walked on update, and the lock file records the commit that was actually installed.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#ROW-GS-BRANCH-MEANING" p="44"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#GIT-SOURCE-DECL" p="45"/>
    <p p="46">A [git source](../glossary/index.xml#git-source) is written as an inline table on the requirement, with a `git` address and exactly one of `tag`, `rev` or `branch`; none or two is refused, because guessing a default branch is not acceptable on a surface that decides what code enters your project. The source's `auth` is declared on the source itself, never borrowed from a registry on the same host. When the repository arrives, vibe reads the package's own manifest and refuses one whose kind and name differ from what you required.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#GS-WIRE-FORM" p="47"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#GS-EXACTLY-ONE-REF" p="48"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#GS-AUTH-EXPLICIT" p="49"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#GS-IDENTITY-VERIFICATION" p="50"/>
    <p p="51">The source of a requirement is decided in a fixed order: an override first, then a git source declared on the requirement, then the registry walk. A branch is followed only by `vibe update`; `vibe install` keeps the commit the lock recorded.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#GS-RESOLUTION-ORDER" p="52"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#GS-MUTABILITY" p="53"/>
  </section>
  <section id="authentication" title="Authentication">
    <p p="54">A public registry needs no credentials, and vibe sends none: it silences git's credential helpers so an install in a script never hangs on a password prompt. A private registry declares its regime in the manifest: a token read from an environment variable, the system's credential helper, or SSH keys. The token comes from your environment and never lands in a file vibe writes.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#TOKEN-NEVER-ON-DISK" p="55"/>
  </section>
  <section id="local-sources" title="Packages on this machine">
    <p p="56">A vibe built from a source checkout treats that checkout's in-tree packages as an [embedded registry](../glossary/index.xml#embedded-registry): on by default for such a build, off for a distributed one, and off for one command with `--no-default-registry`. Version enumeration still unions the embedded and the declared registries, so a newer published version is seen; an override or a git source on a requirement stays above the embedded registry. `--embedded-short-circuit` stops enumeration at the embedded registry for the packages it serves, so a fully embedded graph resolves with no network at all.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#KNOB-DEFAULT" p="57"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#KNOB-SUPPRESS" p="58"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#ENUM-UNION" p="59"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#EXPLICIT-ABOVE" p="60"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#FLAG-EMBEDDED-SHORT-CIRCUIT" p="61"/>
    <p p="62">A package resolved this way is recorded with `source_kind = "embedded"`, and `vibe check` warns that such a lock is not portable. In `--frozen` and other non-interactive runs the embedded registry is off, so a lock that only works on one developer's machine cannot pass in a build server.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#LOCK-EMBEDDED" p="63"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#GUARD-WARN" p="64"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#GUARD-CI-OFF" p="65"/>
    <p p="66">A project that carries a `packages/` folder beside its manifest gets that folder opened as a local registry with no declaration at all. Packages resolved from it record `source_kind = "local"`, which is portable, because every checkout resolves the same folder to the same content. `--no-prefer-local` bypasses the folder for one command.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#LOCAL-AUTO-OPEN" p="67"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#LOCAL-SOURCE-KIND" p="68"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#LOCAL-NO-PREFER-FLAG" p="69"/>
  </section>
  <section id="edge-cases" title="Edge cases and rules">
    <p p="70">A vibe built from a source checkout treats that checkout's in-tree packages as an ambient registry, consulted first: a developer of vibe installs the packages being developed without publishing them. A distributed vibe has no such registry.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-030#AMBIENT-DEFAULT" p="71"/>
    <p p="72">The source repository of vibe itself is mirrored on two hosts, but that is a different thing from the package registry: the mirrors carry the program's source, the registry carries packages, and the credentials for the two are never shared.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-016#ORTHOGONALITY-LAW" p="73"/>
    <p p="74">vibe drives registries through the `git` program on your `PATH` and checks for it before it starts; `VIBE_GIT_BINARY` points it at another copy. A registry clone older than one hour is refreshed before an install, a younger one is used as is, and `vibe registry sync` refreshes regardless of age.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-001#RISK-GIT-IN-PATH" p="75"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-001#OPEN-GIT-BINARY-PATH" p="76"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-001#FRESHNESS-TTL" p="77"/>
    <p p="78">A file the resolver needs, a manifest or a redirect stub, is read straight from the host over HTTPS when the host is GitHub or GitVerse, with a credential sent as a header and never in the address; a miss settles the question only for a tag or a commit, whose content is fixed, and on a branch git is asked next. A host the table does not name never enters this path.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#RAW-READ-FAST-PATH" p="79"/>
    <p p="80">A read the host refuses for the moment, with a rate limit or a server error, is retried a few times with a short pause before the reader falls back to git; a plain «not found» is never retried.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#RAW-READ-BACKOFF" p="81"/>
  </section>
</spec>
