docsv0.5.1

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:

StepToolWhat it fetches
install.shcurlthe release archive, the embedder payload and their .sha256 files
install.ps1Invoke-WebRequestthe same four files
urna setup, payload stepa curl child processthe payload and its .sha256
urna setup, Python env stepuv or pipnumpy and tokenizers from the configured package index (uv may also download a Python)
registry-model embedders in a checkoutHugging Face librariesmodel 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.sh

Replace 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.sh
urna-x86_64-unknown-linux-musl.tar.xz
urna-x86_64-unknown-linux-musl.tar.xz.sha256
urna-embedder-payload.tar.gz
urna-embedder-payload.tar.gz.sha256

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.sh

If 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-python

Until 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/python

URNA_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 doctor

urna 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.

On this page