# Читать документацию локально {#root}

@status:doc/work @audience:user

[p01] Документацию пакетов, которыми вы пользуетесь, включая приватные, можно читать на собственной машине, ничего никуда не отправляя. Эта страница скачивает руководство на вашу машину и открывает читалку в браузере.

[p02]
```prompt
Скачай руководство VibeVM, пакет org.vibevm.core/vibevm-docs, в машинное хранилище, открой локальную читалку документации и скажи мне адрес, который открыть в браузере.
```

- needs: навык vibevm, установленный у вашего агента; доступ по сети к реестру один раз, или пакет, уже лежащий в хранилище

outcome: `vibe cache list` показывает `org.vibevm.core/vibevm-docs`; `vibe doc serve` запущен и печатает адрес на `127.0.0.1`; браузер показывает первую страницу руководства

- assert: `vibe cache list --quiet`

## Что происходит {#what-happens}

[p03] Агент выполняет `vibe cache add org.vibevm.core/vibevm-docs`. Пакет документации никогда не ставится в проект; он прогревается в машинное [хранилище](../glossary/index.xml#store) вместе с пакетами, которые описывает, чтобы каждое правило, которое он цитирует, разрешалось без сети. Затем агент выполняет `vibe doc serve`: vibe запускает маленький веб-сервер, который слушает только на вашей машине, отрисовывает каждую страницу из хранилища по запросу и печатает адрес. Пока вы читаете, из интернета ничего не скачивается, и ни одна страница не покидает машину.

> [p04] `vibe install` MUST refuse a `doc` package with a hint naming the warm-up command; documentation is warmed into the machine store with `vibe cache add` (§11), and the local reader and `vibe explain` read the store.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#KIND-DOC-NOT-INSTALLED>

> [p05] `vibe doc serve` starts an HTTP server **on 127.0.0.1 only**, serves the shell and, on every request, glues in the island rendered from the machine store, the current project's lock file or a private registry. The language preference comes from the project's `[i18n].preferred` when present. The mode is fully autonomous: no request to vibevm.org, no external CDN or fonts, everything in the bundle. The server serves files only from known roots (the store, the shell), without path traversal and without directory listing, with a content security policy naming no external source.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOCAL-SERVE>

## Руками {#by-hand}

[p06] 1. Прогрейте хранилище. Внутри проекта источник — его [реестры](../glossary/index.xml#registry); вне проекта — реестры всей машины:

[p07] Example `cache-add-docs` is copied from the source page at projection time.

[p08] 2. Запустите читалку и откройте напечатанный адрес в браузере. Остановите её через Ctrl+C:

[p09] Example `doc-serve` is copied from the source page at projection time.

[p10] 3. Выберите язык переключателем на любой странице. Там, где у страницы нет перевода, читалка показывает язык самого руководства и говорит об этом.

## Приватные пакеты {#private-packages}

[p11] Та же читалка показывает документацию пакетов из приватного реестра или только с вашей машины: что лежит в хранилище, то она и отрисовывает. Это и есть задуманный путь для проприетарной документации, и потому читалка никогда не обращается к публичному сайту.

> [p12] **The local reader listens on 127.0.0.1 only, serves only known roots, loads nothing external, and contacts the network only for a shell download the user explicitly confirmed.**
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#INV-LOCAL-IS-OFFLINE>

## Оболочка читалки {#the-shell}

[p13] Выпущенный `vibe` несёт интерфейс читалки внутри бинарника. `vibe`, собранный из исходников, несёт простую запасную оболочку; `vibe doc shell install` скачивает полный интерфейс для своей версии из ассетов выпуска в `~/.vibe/opt/`, проверив размер и отпечаток, и только по вашей просьбе. Без него читалка работает, просто скромнее, а `vibe doc serve --print-shell` говорит, какую из двух оболочек она держит.

> [p14] When the instance's shell pin names a shell that is not in the shell store and there is no network, the reader falls back to the bare shell and warns; it never contacts the network without consent (§12).
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOCAL-OFFLINE-SHELL>

## Особые случаи и правила {#edge-cases}

[p15] Прогрев пакета документации прогревает и его [предметы](../glossary/index.xml#subject), так что правила, которые цитирует страница, разрешаются без сети.

> [p16] Warming a `doc` package with `vibe cache add` warms its subjects too, so that `spec://` citations resolve offline.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#REL-WARMUP-CLOSURE>

[p17] Внутри проекта, чей локальный реестр держит пакет прямо в дереве, `vibe cache add --offline` прогревает его без сети. Язык читалки берётся из `[i18n].preferred` проекта или из флага при запуске.

> [p18] The store is warmed with `vibe cache add <coordinate>` from a registry, or `vibe cache add --offline <coordinate>` from a project root whose project-local registry holds the package in-tree; the sources of `vibe-doc` are the store (`lookup`, `list_all`), the lock file (`Lockfile::read`, `slot_abs_path`), a registry (`resolve_and_fetch`) and a checkout (`LocalRegistry`).
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOCAL-WARMUP>

> [p19] The local reader serves the same from the store; the preference comes from the project's `[i18n].preferred` or a launch flag.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOC-LOCAL>

[p20] На сайте та же страница живёт под `/doc/`: язык идёт следующим сегментом пути, а у языка источника префикса нет. Адрес с номером версии показывает текущее содержимое этой версии, потому что версию могут опубликовать заново, а реестр не хранит прошлых публикаций.

> [p21] The site is mounted under the path `/doc` of the main domain. The language is the path segment after `/doc/`; the source language of a documentation carries no prefix. The address map is deterministic and needs no index:
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#SITE-MOUNT>

> [p22] An address with a version number always shows the **current** content of that version in the registry: one number may be published ten times a day, and the site shows the last publication. There are no permanent links to past publications — they do not exist in the registry either (§14).
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#SITE-VERSION-SHOWS-CURRENT>

[p23] Читалку может встроить плагин редактора через iframe; тогда плагин передаёт при запуске собственный origin, и читалка принимает фреймы только из него.

> [p24] The policy is sent as a header, not a `<meta>`: `default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; media-src 'self'; object-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors <origin>`, where `frame-ancestors` names only the origin of the host that launched the reader — the launch parameter `vibe doc serve --frame-ancestor <origin>`, because a webview's origin changes from window to window — and is `'none'` without the parameter. The reader has no CORS layer at all and sends `x-content-type-options: nosniff`. The public site is not embeddable in frames.
>
> <spec://org.vibevm.core/vibevm/common/PROP-057#LOCAL-CSP>

[p25] Агент читает то же хранилище: `vibe explain "spec://org.vibevm.core/vibevm-docs-ru/start/what-vibevm-is"` печатает страницу или блок текстом.

