Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

.nornir/howto-remote-collaborator.md

How-to: share your nornir server with a friend (Tailscale)

Goal: you run one nornir-server that owns the warehouse; a friend on the same Tailscale tailnet drives it from his machine — his nornir CLI, his Claude Code agents (over MCP), and the nornir-ui viz — all reading/writing your warehouse over gRPC. See also running-as-a-server.md (systemd, the lock rule) and the live viz in design.md.

Why a server at all (the lock rule)

The warehouse is redb-backed: single writer per process. Only one process may open it directly. So exactly one nornir-server opens it; everyone else — your friend, his agents, his viz, and even your own clients — connects over gRPC instead of opening the files. That's the whole point of the thin-client split.

1. Host side (you) — start the server

# build once (server feature)
cargo build --release --features cli --bin nornir-server   # in the nornir repo

# pick a strong shared secret (>=16 chars) and BIND WIDE so Tailscale can reach it
export NORNIR_SERVER_TOKEN='choose-a-long-random-secret'
export NORNIR_SERVER_ADDR='0.0.0.0:7878'        # default is 127.0.0.1 = loopback-only!
export NORNIR_CONFIG=/path/to/workspace_nornir-catalog/release/nornir.toml
./target/release/nornir-server
# → "nornir-server: listening on 0.0.0.0:7878"

2. Friend side (same tailnet) — the two env vars

Everything the friend runs needs the same two variables (your Tailscale address

export NORNIR_SERVER='http://100.x.y.z:7878'     # your Tailscale IP / MagicDNS name
export NORNIR_SERVER_TOKEN='choose-a-long-random-secret'

Or skip the exports and just watch it:

nornir viz --server http://100.x.y.z:7878 --token 'the-shared-secret'

One line, no setup — the viz opens as a thin client and shows all your workspaces. (The token can also live in ~/.nornir/token so even --token is optional next time. See viz-modes.md.)

a) His nornir CLI (thin client)

With NORNIR_SERVER set, every warehouse-touching command routes to your server instead of opening a (nonexistent, locked) local warehouse:

nornir docs history nornir-catalog
nornir search "tpch" --corpus bench_history
nornir bench history-show nornir-catalog

b) His Claude Code agents — nornir over MCP

nornir-mcp is an MCP server (stdio) that exposes the whole nornir surface as tools; when NORNIR_SERVER is set it relays every tool to your server over gRPC. The friend registers it in Claude Code one of two ways:

Full step-by-step — including NORNIR_WORKSPACE to scope the tools to a monitored workspace (njord/holger/…) — is in mcp-from-claude-code.md.

Option 1 — claude mcp add (CLI):

claude mcp add nornir \
  --env NORNIR_SERVER=http://100.x.y.z:7878 \
  --env NORNIR_SERVER_TOKEN='choose-a-long-random-secret' \
  -- nornir-mcp

Option 2 — .mcp.json in his project (commit-or-not, his choice):

{
  "mcpServers": {
    "nornir": {
      "command": "nornir-mcp",
      "env": {
        "NORNIR_SERVER": "http://100.x.y.z:7878",
        "NORNIR_SERVER_TOKEN": "choose-a-long-random-secret"
      }
    }
  }
}

nornir-mcp must be on his PATH (cargo install --path . --bin nornir-mcp from the nornir repo, or copy the built binary). Then in a Claude Code session the tools appear as mcp__nornir__*, and he just asks Claude Code to use them, e.g. "use the nornir MCP to show nornir-catalog's bench history" or "search the warehouse docs corpus for the mashup design." No NORNIR_SERVER set → the same binary runs embedded (and would need its own warehouse), so the env vars are what point it at your server.

c) His nornir-ui viz — pointed at your server

cargo install nornir --features viz          # or: cargo build --release --features viz
NORNIR_SERVER=http://100.x.y.z:7878 NORNIR_SERVER_TOKEN='…' nornir viz

3. Verify / troubleshoot