Ask questions of your code

Two ways to interrogate the graph: structured queries that need no model and run fully offline, and natural-language questions answered by a local model that calls the graph's tools for you. Both read the same provenance-tagged store, so answers are grounded in your actual code and decisions — not the model's training data.

The natural-language path is also the Ask tab in the graph explorer — same tools, same grounding, in your browser.

Structured — offline, no model

Precise lookups straight against the graph. Deterministic, instant, and scriptable (add --json to any of these).

# Find, then explain: ranked text search — curated ADRs/blueprints rank first
roteiro search "provenance model"

# Explain a returned node: its provenance-labelled neighbourhood
roteiro query 'sym:rust:crates/rto-graph/src/store.rs#Store'

# Everything relevant to a symbol — callers, callees, governing ADRs
roteiro context 'sym:rust:crates/rto-graph/src/sync.rs#sync'

# How are two things connected? Shortest path between nodes
roteiro path 'file:src/main.rs' 'adr:0006'

# What decisions and docs exist? List by kind, or find open debt
roteiro query --kind adr
roteiro debt

# What changed on this branch, and does it drift from authored intent?
roteiro review --base main

Natural language — via a local model

Serve your installed models over the OpenAI-compatible /v1 endpoint, then ask in plain English. The server runs an agent loop that calls the graph's search, context and path tools and answers from what it finds — so “what should this project be used for?” is answered from your ADRs and blueprints, not guessed. Requires --features serve.

# Start the network server (loopback; pick another port with --addr if 8017 is taken)
roteiro serve

# Ask it like any OpenAI chat endpoint — grounded in your graph
curl -s http://127.0.0.1:8017/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"model":"qwen3-8b","messages":[{"role":"user",
       "content":"What should Roteiro be used for?"}]}' \
  | jq -r '.choices[0].message.content'

# More examples — each triggers a grounded tool call
#   "Where is the git-native store implemented?"
#   "How does sync relate to ADR-0006?"
#   "What outstanding intent-debt is there?"
“Like any OpenAI chat endpoint” has one important exception. Send no tools array and you get the mode above — Roteiro’s graph tools, grounded in your code. Send your own tools array and they replace the graph tools, because a client bringing its own tools is using this as a general backend. Roteiro never executes a tool you supplied; it returns the call and stops. The endpoint’s full contract sets out both modes, the declared divergences from OpenAI, and the parameters that are accepted and dropped.
Pick a model that can call tools. Grounded answers depend on the model actually invoking the graph tools. qwen3-8b is the reliable default — it tool-calls consistently and runs comfortably on a 16 GB MacBook Air (M3). The tiny qwen3-0.6b is great for spec draft but too small for agentic tool use — it tends to answer from memory and hallucinate. Set it once in roteiro.toml under [models] generative = "qwen3-8b", or name it per request as above.
Already using an AI agent? Skip curl entirely — run roteiro mcp and your agent gets the same search / context / path / debt tools natively, grounded in the same graph. See MCP mode. roteiro init also drops an agent skill at .agents/skills/roteiro/SKILL.md (the portable, cross-tool location; also .github/skills/ for GitHub Copilot when the repo already uses .github) that teaches any agent how to drive the graph — when to search vs query vs context, the provenance model, and the plan/review flows.
Many repos, one server. roteiro serve --workspace ~/code (or a [workspace] config) hosts every repo under a root from a single process — the model is loaded once and each project's graph is opened on demand (ADR-0008). The graph tools gain a project argument and a list_projects tool, so one endpoint answers questions about any of your projects: "in beta, where is auth handled?". Omit --workspace for the single-repo default.