Air-gapped install and queries
Install urna on a machine with no network: copy the release files, point the installers at file://, build the Python env from a local wheelhouse.
This guide installs urna on a machine that cannot reach the internet and shows which queries work there. The binary and the embedder payload install from a local directory through URNA_RELEASE_BASE. The Python env is the part that needs care: urna setup builds it with pip or uv, which want a package index.
What opens a socket
Once installed, urna doctor opens no socket, and neither do ask, retrieve or the explorer's ask tab on a potion corpus. Network access happens only in these steps:
| Step | Tool | What it fetches |
|---|---|---|
install.sh | curl | the release archive, the embedder payload and their .sha256 files |
install.ps1 | Invoke-WebRequest | the same four files |
urna setup, payload step | a curl child process | the payload and its .sha256 |
urna setup, Python env step | uv or pip | numpy and tokenizers from the configured package index (uv may also download a Python) |
| registry-model embedders in a checkout | Hugging Face libraries | model weights, only when URNA_ALLOW_DOWNLOAD=1 |
The binary itself links no network stack. Why the design works this way is in offline by construction.
Collect the files on a connected machine
Download the archive for the target, the embedder payload, both .sha256 files and the installer script. Use the same release for all of them.
mkdir urna-offline && cd urna-offline
base=https://github.com/hoffresearch/urna/releases/download/v0.5.1
for f in urna-x86_64-unknown-linux-musl.tar.xz urna-embedder-payload.tar.gz; do
curl -fLO "$base/$f"
curl -fLO "$base/$f.sha256"
done
curl -fLO https://raw.githubusercontent.com/hoffresearch/urna/main/scripts/install.shReplace the archive name with the target of the offline machine: aarch64-unknown-linux-musl, x86_64-apple-darwin, aarch64-apple-darwin, or urna-x86_64-pc-windows-msvc.zip on Windows. Verify the files here, while you still have network access for gh attestation verify.
Then collect the two Python packages the embedder imports, as wheels:
python3 -m pip download --dest wheelhouse "numpy>=1.26" "tokenizers>=0.20"pip download picks wheels for the machine it runs on. Run it on a machine with the same OS, CPU architecture and Python version as the offline one, or pass pip's --platform, --python-version and --only-binary=:all: options.
Copy the whole directory to the offline machine:
Install the binary and the payload
With the one-liner script, point URNA_RELEASE_BASE at the directory. The script checks both SHA-256 digests before it writes anything:
cd urna-offline
URNA_RELEASE_BASE="file://$PWD" sh install.shIf the binary arrived another way (Homebrew from a local tap, a copied archive, a package mirror), lay down only the payload with urna setup:
URNA_RELEASE_BASE="file://$PWD" urna setup --yes --no-pythonUntil the Python env from the next section exists, this run ends with a doctor code (2 or 3) from its verify step. The payload is in place once the output shows ok embedder payload.
Both commands read the files by name from the base, so keep the release file names unchanged. When URNA_RELEASE_BASE is set, install.sh --version and urna setup --version are ignored.
urna setup accepts only https:// and file:// bases, and follows redirects only to HTTPS: an internal http:// mirror is refused. install.sh accepts any URL curl does. On Windows, urna setup takes a file:///C:/... base; install.ps1 downloads with Invoke-WebRequest, and whether that accepts file:// depends on your PowerShell version, so the tested route there is urna setup.
Mirrors
Setup's curl has a 20 second connect timeout and two retries, but no overall time limit. A mirror that accepts the connection and then stalls can hang urna setup.
Build the Python env from the wheelhouse
urna setup cannot build its venv offline: its Python step runs uv pip install or pip install against whatever package index those tools are configured with. Build the env yourself instead. Two ways work.
Create the venv where setup would put it. The binary checks that location second, right after URNA_PYTHON, so nothing else needs configuring:
python3 -m venv ~/.local/share/urna/venv
~/.local/share/urna/venv/bin/python -m pip install --no-index --find-links ./wheelhouse "numpy>=1.26" "tokenizers>=0.20"Use the data directory the payload went to: $URNA_DATA_DIR/urna/venv if you set it, $XDG_DATA_HOME/urna/venv if that is set, %LOCALAPPDATA%\urna\venv on Windows (with Scripts\python.exe instead of bin/python). The full lookup order is in paths.
Or install the wheels into any interpreter and pin it:
export URNA_PYTHON=/opt/py312/bin/pythonURNA_PYTHON wins over every other interpreter. If you later run urna setup with an URNA_PYTHON that lacks the packages, setup blocks its Python step (exit 14) rather than build a venv the pin would hide.
Prove the install
urna doctorurna doctor makes no network request. It runs the interpreter, imports the packages, finds the embedder and the potion table, and embeds a probe string. Exit 0 means ask and retrieve will work on potion corpora. Any other code names the first failing check; the table is in urna doctor.
Query offline
On an installed binary, any corpus whose model starts with minishlab/potion answers offline:
urna stats corpus.urna | grep '^model:'
urna ask corpus.urna "your question"Registry-model corpora need a checkout
The payload carries only the potion query embedder. A corpus built with a registry model (wemm, clip, jina) routes to embed_query_model.py, which no release artifact ships, so an installed binary cannot ask it, online or offline. See known limits.
To query such a corpus offline, copy a repo checkout to the machine together with the model's Python packages and its weights on disk. The embedders never download weights unless URNA_ALLOW_DOWNLOAD=1, so point them at the local copy: --model-path on ask and retrieve, or URNA_MODEL_DIR_<PRESET> (for example URNA_MODEL_DIR_WEMM_2B). Presets that run remote model code also need URNA_ALLOW_REMOTE_CODE naming the preset. The per-preset requirements are in the model registry.
The pip wheel offline
The wheel bundles the potion table, so it needs no payload and no setup. Move it like any other Python package:
# connected machine
python3 -m pip download --dest wheelhouse "urna[embed]"
# offline machine
python3 -m pip install --no-index --find-links ./wheelhouse "urna[embed]"The same platform rule as above applies to pip download. The wheel needs Python 3.12 or newer.
Every variable used here is in environment variables.
Give a corpus to an agent
Wire a .urna corpus into an LLM agent as a tool: urna retrieve JSONL as the tool result, urna cite as verification, and rules for quoting stored text.
Verify what you installed
Check urna release files with SHA-256 digests, GitHub attestations and the signed tag, and see which checks each channel and artifact actually has.