# Work offline {#root}

@status:doc/work @audience:user

[p01] On a plane or behind a firewall, vibe keeps working from what the machine already holds. This page fetches what you will need before you leave and installs from it without a network.

[p02]
```prompt
Before I go offline, fetch into the machine store everything the VibeVM project in the current folder needs plus the package org.vibevm.world/multi-user-planning, then verify the store and show me that an offline install of this project succeeds.
```

- needs: the vibevm skill installed for your agent; network access now; a project with `vibe.toml`

outcome: `vibe cache list` shows the project's packages and the extra one; `vibe cache check` reports every entry intact; `vibe install --offline` completes without a network request

- assert: `vibe cache check`
- assert: `vibe reinstall --force --offline --assume-yes`

## What happens {#what-happens}

[p03] The agent runs `vibe cache add` for the extra package, which resolves it and its whole dependency closure and fetches every node into the [store](../glossary/index.xml#store) without touching the project. It runs `vibe install` once online so the project's own packages are in the store too, then `vibe cache check` to verify every stored entry against its [fingerprint](../glossary/index.xml#fingerprint). Finally it runs `vibe install --offline`: resolution and fetch are satisfied from the store alone, and the command fails loudly if anything is missing rather than installing a partial graph.

> [p04] Under `--offline`, resolution and fetch must be satisfiable entirely from local sources — the cache (§2.7), `[[mirror]]` entries with a `file://` URL, and the project's own `vibe.lock` + `vibedeps/`.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#OFFLINE-LOCAL-ONLY>

## By hand {#by-hand}

[p05] 1. Warm the store with a package and its dependencies. Inside a project its [registries](../glossary/index.xml#registry) are the source; outside one, the machine-wide registries:

[p06]
```sh
vibe cache add org.vibevm.world/wal
```

```output
Pre-warming the machine store (<TMP>/home/cache)
  ✓ created  org.vibevm.world/wal@1.0.0

1 fetched, 0 already present — nothing materialised into any project.
```

[p07] 2. See and verify what the store holds:

[p08]
```sh
vibe cache list
```

```output
GROUP             NAME  VERSION
org.vibevm.world  wal   1.0.0

1 package in <TMP>/home/cache.
```

[p09]
```sh
vibe cache check
```

```output
Integrity sweep of the machine store (<TMP>/home/cache)

1 ok, 0 mismatched, 0 unrecorded.
```

[p10] 3. Install without a network:

[p11]
```sh
vibe install org.vibevm.world/wal --path hello-vibe --offline --assume-yes
```

```output
Resolving 1 root package…

Materialising 1 package into vibedeps/:
  org.vibevm.world/wal@1.0.0

closure diff:
  → + org.vibevm.world/wal@1.0.0 (root-edge)
  → lane vibevm/vibespecs/boot/INDEX.md: 737 -> 854 B

Materialised 1 package into vibedeps/; regenerated boot artifacts for 1 node(s).
```

## Three ways to switch offline mode on {#switching-it-on}

[p12] The flag `--offline` on any command; the environment variable `VIBE_OFFLINE=1`; or the setting `offline = true` under `[net]` in `~/.vibe/config.toml`. The flag wins over the variable, and the variable over the setting. Online remains the default.

> [p13] It resolves through the established CLI config layering — flag, then a `VIBE_OFFLINE` environment variable, then a user-config `[net]` key; the flag wins. This mirrors the resolved-posture pattern already used for `--unattended` / `VIBE_UNATTENDED` (`output::resolve_unattended`).
>
> <spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#OFFLINE-LAYERING>

## A whole team without a network {#air-gapped}

[p14] For a machine that never sees the registry, `vibe registry vendor` writes a folder holding every package the [lock file](../glossary/index.xml#lock-file) references, ready to be used as a [mirror](../glossary/index.xml#mirror) with a `file://` address on the other side. The fingerprints travel with it, so the mirror is verified like any other.

> [p15] **Decision.** `[[mirror]]` entries are parallel alternative URLs for a specific registry (or `*` for any). During fetch:
>
> <spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-002#MIRROR-LAYER>

## Edge cases and rules {#edge-cases}

[p16] If an offline install refuses a package the store already holds, the project's registries were never cloned on this machine and vibe cannot learn which versions exist; one online install in any project clones them, and a `file://` mirror needs no clone at all.

[p17] Offline resolution sees the store as of its last refresh: a version published after you went offline is invisible until you are back and run `vibe registry sync` or an online install.

> [p18] Offline resolution is therefore computed against the cache **as of its last refresh**. This is correct and expected — Maven `mvn -o` and `cargo --offline` have the same property — but it must be explicit: a `--offline` resolve may pick an older version than an online resolve would.
>
> <spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#AS-OF-LAST-REFRESH>

[p19] A package in the store is usable even when its registry no longer lists it; a package that never reached the store is a hard error naming the missing [coordinate](../glossary/index.xml#coordinate).

> [p20] Anything not available locally is a **hard error with an actionable message**: it names the missing package and version and tells the operator how to recover (run once online, `vibe cache add`, or `vibe registry vendor`).
>
> <spec://org.vibevm.core/vibevm/modules/vibe-registry/PROP-010#OFFLINE-HARD-ERROR>

[p21] The program's own version manager obeys the same posture: under it `vibe self update`, `install` and `reinstall` refuse before their first request, naming the address they would have needed, and `self ls`, `current` and `which` answer from the machine as usual.

> [p22] Every `self` verb honours the offline posture the process resolved —
>   `--offline`, `VIBE_OFFLINE` or `[net] offline`, layered as PROP-010
>   `##OFFLINE-LAYERING` says. Under it a release-lane verb is refused before its
>   first request, naming the verb and the address it would have needed; a
>   source-lane rebuild runs without fetching when the checkout and the crates
>   are already local, and is refused the same way otherwise. The domain never
>   reads the environment for this: the composition root hands the resolved
>   posture in.
>
> <spec://org.vibevm.core/vibevm/common/PROP-019#CMD-OFFLINE>

