The five ways to run it

1 · Offline mode — the default

No models, no network. Build the graph, query it, verify authored intent, and render docs. This alone is a complete tool.

# Scaffold the store, git hooks, an AGENTS.md block and an agent skill
# (.agents/skills/roteiro/SKILL.md; also .github/skills when the repo uses .github)
roteiro init

# Build / incrementally update the graph for the working tree
roteiro sync

# Explain a node — its provenance-labelled neighbourhood
roteiro query 'sym:rust:crates/rto-graph/src/store.rs#Store'
roteiro query --kind fn                 # list every function node

# Verify authored links against the code; non-zero exit on drift (CI gate)
roteiro check

# Shortest path between two nodes, and outstanding intent-debt markers
roteiro path 'file:src/main.rs' 'adr:0001'
roteiro debt

# Render the graph to a docs site or an OKF bundle
roteiro render docs
roteiro render okf

# …or one bundle spanning a whole workspace, members and all
roteiro render okf --workspace-name payments

Without --workspace-name, render okf renders the current project with its sections at the bundle root, even when that repository is a member of a configured workspace. With one, each member's concepts nest under /<member>/. That is what keeps them apart: node keys are repository-relative, so every repository's README.md is the same key — file:README.md — and the directory does the separating rather than a naming scheme. Each member is read with its own roteiro.toml.

Two things to know before you rely on a bundle: the output directory is deleted and rebuilt on every render, so your own notes belong outside it and link into it by name — and the format changed in 4.0.0, with no migration: render obsidian and the vault it wrote are gone. Both are explained on the OKF bundle page.

A bundle is shareable, and what it shares is the graph. It names every file, symbol, configuration key and intent-debt marker in the repository, and carries the whole text of the prose it ingested — the ADRs, the blueprints, the documents — so a bundle of a private repository is private. Two things it does not carry, because neither is a graph node: analyzer findings and agent memory live in stores of their own and no render reaches them. A configuration key appears by name, never with its value.

The workspace vault's _Home had two summaries a bundle has no home for yet — the cross-member findings summary and the version-pin table. They are recorded as not-yet-reimplemented in ADR-0021 rather than left to be noticed.

2 · Online mode — richer inference with local models

Pull a real embedding or generative model once (with consent), then run everything locally — the “online” is a one-time, explicit download, after which inference is offline again. Requires --features inference-local-models.

# See models curated for THIS machine's resources, then pull one
roteiro model list
roteiro model pull bge-small-en-v1.5-gguf
#   Download bge-small-en-v1.5-gguf (~65 MB, MIT) from …? [y/N]

# Suggest inferred similarity edges using the pulled embedding model
roteiro infer --model bge-small-en-v1.5-gguf --min-confidence 0.5

# Report likely-duplicate content (same blob, or near-identical embeddings)
roteiro duplicates --min-similarity 0.9

# Draft a house-style, graph-grounded ADR/blueprint with a generative model
roteiro spec scaffold "rate limiting" --kind adr
roteiro spec draft draft-adr.md         # fills placeholder sections
“Online mode” means the download, not the inference. The one-time model pull is the only thing that touches the network here; after it, every model above runs on this machine and nothing you ask is sent anywhere. The separate, default-off capability that does call a hosted model at use time is the remote model tier — a different feature, a different name, and a consent model of its own. If you enabled inference-local-models, you did not enable that.

3 · Serving mode — the network HTTP server

roteiro serve is the networked server: an OpenAI-compatible /v1 API over your installed models, the read-only /v1/graph API and the explorer web UI — all on one loopback port. Built with --features serve and a model installed, it also enables the Ask tab; without the model feature (or none installed) it degrades gracefully to the model-free graph API + UI. Binds [serve] addr (default 127.0.0.1:8017); set [serve] tls_cert/tls_key for in-process HTTPS.

# Network server on 127.0.0.1:8017 — /v1 + /v1/graph + the web UI
roteiro serve                            # → prints the URL to open

# Call /v1 on that default bind like any OpenAI endpoint
curl http://127.0.0.1:8017/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-0.6b","messages":[{"role":"user","content":"hello"}]}'

# Or override the bind address/port and terminate TLS in-process (then use https://…)
roteiro serve --addr 0.0.0.0:8443 --tls-cert fullchain.pem --tls-key privkey.pem
No auth on /v1. A non-loopback bind like 0.0.0.0:8443 is warned about — use in-process TLS ([serve] tls_cert/tls_key) or a reverse proxy. In-process TLS is a serve feature; roteiro explorer serves plain HTTP only.

4 · MCP mode — the graph, for AI agents

Expose the knowledge graph to an MCP-capable agent (Claude, editors, custom tooling). Agents get typed tools to query nodes, fetch a node's context bundle, find paths and list debt — grounded in the same graph humans review. Requires --features mcp.

# Default: the MCP graph server over stdio (for a local agent to spawn)
roteiro mcp

# Or networked over streamable HTTP (terminate TLS at a reverse proxy)
roteiro mcp --http 127.0.0.1:8080

# Restrict what this server exposes — by class, by name, or to everything read-only
roteiro mcp --tools query,quality        # drops the security + sandbox prose: about two fifths of the surface
roteiro mcp --tools search,explain,context,path
roteiro mcp --tools read-only            # drops sandbox_clear, the one mutating tool
The server decides what it exposes. --tools (and [mcp] tools in config) bounds both tools/list and tools/call — a tool that is not advertised is not callable either, because a client that already knows the name is exactly the case a restriction is for. An unknown name, or a restriction leaving nothing to serve, is a startup error rather than a server that quietly advertises everything. It bounds the served-chat tools on the same terms, so one server never tells its MCP client and its chat client different things about itself.
Four classes, and a class you did not load stays discoverable. query (search, explain, context, path, list_kind, list_projects), quality (check, debt, debt_density, coupling, config_secrets), security and sandbox. Every advertised tool costs tokens on every turn whether or not the session could ever reach it, and security + sandbox are roughly two fifths of the advertised bytes — a code-navigation session pays that every turn to advertise tools it will never call. The default is still every class; narrowing is opt-in. list_tool_classes is advertised whatever you withhold, so a model asked about analyzer findings on a query-only server answers "that class is not loaded in this session" rather than "Roteiro cannot do that".
Read the figures off your own server, not off this page. The exact byte counts move whenever a tool is added or a description is edited, so they are deliberately not pinned here — an earlier version of this page quoted a total that had already gone stale without anyone noticing, which is what a number nothing checks does. A restricted server prints the real figures for your build on startup:
roteiro tools: advertising 7 of 16 tools — 4803 of 19155 advertised bytes — withheld: …
That line is the authority, and it is printed whether or not --mcp is passed, because the selection bounds the served-chat tools too.
Renamed in v1.5. The MCP graph server moved from roteiro serve to roteiro mcp; bare roteiro serve is now the network HTTP server. The old serve --http and serve --models spellings still work as deprecated aliases (with a notice).

5 · Explorer mode — the graph, in your browser

An interactive web view of the graph. Start at a workspace overview — the cross-repo topology, the config override matrix and drift — then click any repo to drop into its own node/edge graph: hotspots, intent-debt with reasons, a node detail panel, and a follow-the-link hop that jumps from a spoke's config key straight to the hub struct that defines it. Fully offline and model-free; requires --features explorer.

# Serve the explorer UI on loopback (no model needed)
roteiro explorer                        # → this directory's repo (--scope here, the default)

# Every configured workspace — what the default used to be
roteiro explorer --scope all

# One configured workspace, and only it
roteiro explorer --scope workspace payments

# One OKF bundle, ours or somebody else's — no graph, just the viewer
roteiro explorer --scope bundle ./their-bundle

# Pick which workspace the flat /v1/graph routes bind to (does NOT narrow)
roteiro explorer --workspace-name payments
--scope defaults to here. Serving every configured workspace is --scope all — a choice you make rather than what you get by standing in the wrong directory. If a config defines workspaces and you did not name a scope, the server says so on one line and names --scope all. A server started by a service manager has no useful working directory, so set [serve] scope in config instead of passing a flag. roteiro serve takes the same flag and the same default.
Chat to your graph in the browser. Build with --features serve,explorer and run roteiro serve: it serves the same explorer UI and the model endpoint on one port, which enables the Ask tab — natural-language questions answered by a local model calling the graph's tools. roteiro explorer on its own stays model-free, with Ask disabled.