Rift roadmap

July 10, 2026 · View on GitHub

Where rift goes from v0.4.x. Ordered by phase; each phase is shippable on its own. Principles that don't change along the way:

  • Local-first. Everything works offline against your own server. Cloud providers become an option, never a requirement.
  • Zero tool-calling errors. Every new provider or feature keeps the hardening that made local models reliable (truncation detection, textual tool-call recovery, alias resolution, doom-loop guard).
  • One small binary. No runtimes, no daemons. Watch the size budget (currently 9.5MB; tree-sitter grammars are the main pressure).

v0.4 — Agent plan view + trust

The agent should show its plan and ask before dangerous things.

  • Interactive pickers (shipped 0.4.0) — /model and /sessions open ↑↓/Enter list overlays; direct /model <name> still works

  • Elicitation (shipped 0.4.0) — ask_user tool: the model asks clarifying questions mid-turn; choices reuse the picker, free-text answers go through the input box; headless/swarm runs stay autonomous

  • Plan tool + activity-pane checklist (the to-do list)

    • New built-in plan tool the model calls to set/update its task list: plan(set=["fix parser", "add test", "run tests"]), plan(done=1)
    • Rendered pinned at the top of the activity pane: ☑ fix parser, ◐ add test (in progress), ☐ run tests
    • System prompt nudges the model to plan first on multi-step tasks and check items off as it goes — also measurably helps local models stay on track
    • /plan command to view/clear it
  • Write/bash approval mode

    • Today rift auto-executes everything. Add --approve mode (and config default) where write/edit/bash pause for y/n in the TUI, with a per-session "always allow" memory; deny list stays as the hard floor
  • Input editing basics — cursor movement (←/→, word jumps, Home/End), insert anywhere, bracketed paste. Today input is append/backspace only; this is the biggest day-one UX gap

  • Load RIFT.md automatically/init generates it, but the agent doesn't read it back yet. Inject it into the system prompt when present (that's the whole point of the file). Also loads AGENTS.md and CLAUDE.md (the cross-tool standards), concatenated and capped

  • Skills (Agent Skills standard, pi/Claude-style) — .rift/skills/

    • ~/.config/rift/skills/ SKILL.md files with frontmatter; listed to the model by name+description, bodies loaded on demand via the skill tool; user-invocable as /skill:<name> [task] with palette completion; /skills
  • /config + /approve — view config, edit in $EDITOR with hot-reload of permissions, session-level approval toggle

v0.5 — Command + UX expansion

  • More slash commands (shipped 0.5.0):
    • /retry — re-run the last prompt (after an interruption or bad answer)
    • /stats — session totals: tokens, calls, tool counts, compactions
    • /system [text] — view or override the system prompt
    • /temp <t> · /ctx <n> — runtime knobs without restarting
    • /worktrees — list swarm worktrees + patches with cleanup hints
    • /save <name> · /sessions named sessions (not just timestamps)
    • /quit
  • @-file mentions (shipped 0.6.x) — @src/main.rs in a prompt auto-attaches an outline (not the raw file — stay token-stingy), with palette completion like the / popup; unsupported file types attach a capped head instead
  • Syntax highlighting (shipped 0.6.x) — syntect in fenced code blocks, stateful per block; pushed the binary to ~12MB so it sits behind a default-on highlight feature (--no-default-features builds lean)
  • Streaming diff pane (shipped 0.6.x) — Ctrl+D flips the activity pane to a live working-tree diff, refreshed after every write/edit tool result and at turn end
  • Themes (shipped 0.6.x) — built-in dark/light/mono palettes; "theme" in config, /theme <name> at runtime; syntect theme follows

v0.6 — Provider abstraction (beyond Ollama, part 1: local)

The architectural step: extract a Provider trait so OllamaClient becomes one implementation, not the foundation.

  • Provider trait (shipped 0.6.0): chat_stream, show, tags — everything the agent loop and swarm already consume
  • OpenAI-compatible provider (shipped 0.6.0, hardened 0.6.1/0.6.2) — unlocks vLLM, LM Studio, llama.cpp server, LiteLLM, OpenRouter, and Ollama's own compat endpoint; 0.6.x added timeouts, transport retries, mid-stream error surfacing, SSE tail flushing, and tool-call id repair
  • Config + model addressing (shipped 0.6.0): openrouter/qwen3 routes through per-provider base URLs and keys in config; project config merges over user config with tighten-only permissions (0.6.2)
  • Token accounting per provider (shipped 0.6.0; usage fields normalized into the shared ChatStats)
  • Per-provider hardening test suite (shipped 0.6.4) — two layers: a deterministic mock-server suite in CI (SSE/NDJSON framing across split reads, missing [DONE], mid-stream error events, tool-call accumulation and id handling, stream_options rejection recovery, truncated-argument errors, front-truncation detection, proxy error statuses), plus an env-gated live suite (RIFT_LIVE_OLLAMA / RIFT_LIVE_OPENAI + RIFT_LIVE_MODEL) run against real servers before a provider is called supported. v1.0's "provider matrix green in CI" builds on the live layer

v0.7 — Cloud providers + cross-provider swarm

  • Anthropic + OpenAI native providers (shipped 0.7 phase 1) — rift-anthropic speaks the Messages API natively (SSE content-block events, tool_use/tool_result blocks, thinking with signature round-trip via Message::provider_data, adaptive thinking, /v1/models discovery), with its own mock + live hardening suites (RIFT_LIVE_ANTHROPIC). OpenAI rides the existing rift-openai protocol. anthropic/<model> and openai/<model> work with just ANTHROPIC_API_KEY / OPENAI_API_KEY in the env — no config entry needed; kind: "anthropic" on a provider entry selects the protocol for custom endpoints. API keys via env/config; never required
  • Cross-provider WarpDrive (shipped 0.8.0) — race gemma4:26b (free, local) vs anthropic/claude-sonnet-4-6 (cloud) on the same task in isolated worktrees and merge whoever wins: each candidate's model string resolves through a provider factory, so one race spans providers. No other TUI does this
  • Cost display for metered providers (shipped 0.8.0) — /stats and the headless summary show estimated $; billed input tracked as summed per-call prompt tokens (not last-of-turn); built-in Anthropic rates, config pricing map for everything else
  • Swarm auto-judge (shipped 0.8.0) — --judge <model> scores every candidate's diff and recommends a winner (TUI: verdict in the winner's log, tab auto-selected; headless: machine-parseable JUDGE: winner= line). bench/judge_bench.py measures judge accuracy against verify.sh ground truth — discriminative-case accuracy is the headline number
  • Turn traces + failure counters — the hardening layer already detects the interesting failures (textual tool-call recovery, alias resolution, doom-loop guard, truncation detection, fuzzy edit misses) and then discards the signal. Count them per turn in TurnStats, and add an opt-in JSONL trace export (--trace <path> / config) recording model, tokens, tool calls, failure flags, and outcome per turn. Local files only, never on by default — this is the data source every optimization item below consumes
  • Bench model matrixbench.py --models a,b,c runs the suite across models and diffs pass rate / prompt tokens / wall time per model; bench runs always emit traces. Every model-specific optimization needs this as its fitness function

v0.8 — Context engine v2

Method for this phase: design offline, implement deterministically. Feed traces + compaction logs + bench results to a frontier model acting as performance engineer; implement its packing strategy as plain Rust; gate every change on the bench matrix. The frontier model is never in the inference path.

  • Hydrate-on-demand (shipped 0.9.0) — an unbounded read of a 500+ line source file returns its line-numbered outline; the model fetches exact ranges. Measured on the hard tier: −18.4% prompt tokens suite-wide, −66% on the buried-bug big-module task, pass rate held (BENCHMARKS.md)
  • Persistent repo-map cache (shipped 0.8.x) — outlines cached per repo root keyed by (mtime, size); a hit skips the read and the tree-sitter parse. Best-effort JSON under the user data dir, LRU-capped
  • Smarter compaction triggers (shipped 0.8.x) — the budget check also runs right after each turn completes, so pruning/summarizing happens while the user reads the reply instead of mid-turn while they wait
  • Benchmark suite v2 (shipped 0.9.0) — hard tier (bench/tasks2/, --dir tasks2): multi-file symptom-not-location bugs, tamper-guarded fix-the-tests, long-session big-module tasks; --runs N reports per-run pass counts + flaky tasks; numbers published per release in BENCHMARKS.md/CHANGELOG
  • Repo-map ranking heuristics v2 (shipped 0.9.0) — import-centrality primary, recency tiebreak (cheap textual import extraction, cached with outlines; no embeddings, no index); degrades to pure recency when no imports resolve. Traces now record tool-call targets for future tuning

v0.8.5 — Model targets

One hardcoded system prompt goes to every model today, but open models differ dramatically in what prompting and formatting they want. Treat each model family as a compiler target, with the bench matrix as the fitness function.

  • Prompt-target machinery (landed early, alongside v0.7 phase 2) — crates/rift-core/prompts/<family>.md (markdown + frontmatter, the SKILL.md idiom: multi-line-friendly, zero new deps) embedded at compile time (include_str! — keeps the one-binary promise); match: substrings select a target by model name; ~/.config/rift/prompts/ overrides for experimenting without recompiling (user-level only — a cloned repo must never be able to replace the system prompt). Swarm candidates each get their own family prompt, so cross-provider races compare tuned targets
  • Family targets (shipped 1.8.0 — see the v1.8 section below) — qwen/deepseek/glm/mistral files embedded alongside the provisional gemma.md; workflow in crates/rift-core/prompts/README.md. All await matrix validation: the first 3-model run (2026-07) showed gemma4:26b at 40/50 with 8 chat-only failures and 3× the tokens of ornith/qwen
  • Prompt evolution gate (shipped 1.8.0) — scripts/prompt_gate.py; prompts are code: benchmark → review → revise → benchmark → merge
  • Tool-schema A/B on the matrix (shipped 1.8.0) — bench.py --schema lean|rich; measure per family, don't assume

v0.9 — Distribution + community

  • Homebrew tap (shipped 0.8.1) — brew tap exYze/tap && brew install rift, formula auto-regenerated by the release workflow from published checksums; scoop manifest installable from its raw URL. Still open: winget submission; homebrew-core once the repo clears the notability bar
  • Demo GIF/VHS tape in the README (shipped 0.8.1) — a real recorded session (VHS tape committed for reproducibility)
  • CHANGELOG.md, CONTRIBUTING.md, issue templates (shipped 0.8.1)
  • CI test matrix on macOS/Linux/Windows (build + test on all three landed early, in 0.4.x — Linux-only CI had let a Windows bug ship)
  • Publish crates to crates.io (rift-ollama is useful standalone)

v1.0 — The promise

Ship when: config format stable for 6 months of releases, provider matrix green in CI against live servers, benchmark numbers published per release, and rift update has carried users through 10+ versions without a manual reinstall. 1.0 means breaking changes now require a major version — trust, codified.

Shipped 2026-07-06. The 1.x line since (highlights): concurrent sub-agents (1.0), model roles (1.1), vision attachments (1.2), post-edit hooks (1.3), remote MCP (1.4), web_search (1.5), VS Code sidebar chat on --serve (1.6), granular permission rules + inline diff review (1.7), and merge-to-release CI. Full detail in CHANGELOG.md.

v1.8 — Model targets, finished

Absorbs the open v0.8.5 items — each model family treated as a compiler target, the bench matrix as the fitness function.

  • Family targets (shipped 1.8.0): qwen/deepseek/glm/mistral prompt files embedded, each derived from its family's documented failure modes. All provisional — first gate run against default.md pending hardware, same status as gemma.md
  • Prompt evolution gate (shipped 1.8.0): scripts/prompt_gate.py runs the matrix with the embedded incumbent then the candidate as a user override, diffs pass rate / tokens / time / failure counters, and prints a PR-ready verdict; a candidate merges only if it wins every model
  • Tool-schema A/B on the matrix (shipped 1.8.0): RIFT_TOOL_SCHEMA=lean (bench: --schema lean) cuts tool descriptions to the first sentence and drops per-parameter docs; results tag which variant produced them — measure per family, don't assume
  • Per-family bench numbers published in BENCHMARKS.md — needs the DGX matrix run (methodology + planned matrix already recorded there)

v1.9 — Distribution, finished

Closes the v0.9 tail so every mainstream install path works.

  • winget (shipped 1.9.0): scripts/make_winget.sh generates the manifest trio from a release's checksums; the release workflow submits version bumps automatically via wingetcreate once the WINGET_TOKEN secret exists. The package's FIRST submission to winget-pkgs is manual — packaging/winget/README.md has the two routes
  • crates.io (shipped 1.9.0): the five library crates carry full publish metadata (internal deps versioned via workspace.dependencies); the release workflow publishes them in dependency order once the CARGO_REGISTRY_TOKEN secret exists. rift-tui stays releases-only
  • homebrew-core PR once the repo clears the notability bar (external — the tap install works today)
  • Quick-wins batch (shipped 1.9.0): /copy argument completion in the palette, mouse-wheel scroll moves the palette selection, --version prints a cache-only update nudge (headless runs nudge on stderr too), autosaved session files capped at 10MB (whole turns trimmed from the front; live context untouched)

v1.10 — Serve protocol v1

The bridge to the platform: the --serve surface becomes something third parties can build on without fear.

  • Versioned protocol (shipped 1.10.0): protocol_version in ready, a capabilities event acks hello with the negotiated set — docs/SERVE.md is the contract, with the additive-vs-breaking rules spelled out (breaking = version bump = 2.0-class change)
  • Compatibility tests (shipped 1.10.0): the conformance suite in serve.rs pins every event's exact wire shape; the VS Code extension checks protocol_version and warns on a mismatch — it is the reference consumer
  • Integration guide + reference client (shipped 1.10.0): SERVE.md's "writing an integration" section + scripts/serve_client.py, an interactive minimal client for Neovim/JetBrains plugin authors

v1.11 — Platform preview

Everything 2.0 will stabilize ships here first, behind flags, so the breaking release is a promotion — not a surprise.

  • Experimental plugin API (shipped 1.11.0, behind "experimental": {"plugins": true}): plugin.json manifests in .rift/plugins/ (project) and ~/.config/rift/plugins/ (user). Commands (prompt templates with {args}) ride the skill machinery — /skill:<name>, listed to the model. Tools (subprocess: args JSON on stdin, stdout = result) register from USER plugins only in the preview — a cloned repo must not register commands to execute; project-tool trust and themes/prompt-target contributions land with 2.0's stabilization
  • Config schema v2 + migrator (shipped 1.11.0): rift config migrate [--dry-run] [--project] rewrites deprecated bash_allow/bash_deny globs to Bash(...) rules, stamps "version": 2, backs up the original; runs before config load so a broken config can't block it
  • Deprecation warnings (shipped 1.11.0): loading a config with bash_allow/bash_deny warns that they stop loading in 2.0 and names the migrator as the way out

v2.0 — The agent platform

Breaking changes, bundled once, and only these:

  • Plugin API stable (shipped 2.0.0, on by default): commands, tools (project plugins behind a one-time manifest trust prompt, like hooks), post_edit hooks, JSON themes (themes/<name>.json, plus ~/.config/rift/themes/), and prompt targets (prompts/<family>.md, user plugins only — a cloned repo never replaces the system prompt)
  • Config schema v2 with one-shot automatic migration (shipped 2.0.0): a v1 user config is rewritten in place on first load, with a .v1.bak backup; if the file can't be written, the migrated form is used in memory — old configs keep working either way. Project .rift.json files are never rewritten; their legacy bash_deny keeps loading (tighten-only) with a nudge toward rift config migrate --project
  • Serve protocol v1 frozen (shipped 2.0.0): PROTOCOL_VERSION = 1, the conformance suite pins every wire shape, and 2.0's additions (skills in ready, /skill: prompt expansion) are additive — editor integrations built on v1 keep working across every 2.x release
  • The 1.0 stability promise resets for 2.x: config + protocol stable, provider matrix green, benchmarks per release

Engineering process (ongoing, not versioned)

Frontier models (Fable/Opus-class) act as an offline performance engineer — they profile, recommend, and leave. Never in the inference path, never a runtime dependency, so the local-first promise holds.

  • Per-release architectural review: source tree + bench deltas + PROJECT.md in; prioritized engineering tasks out
  • Failure-cluster analysis as traces accumulate: cluster failure counters by model/task/tool, turn root causes into roadmap items — improving rift itself, not just prompts
  • Offline design, deterministic implementation: prompt, packing, and ranking strategies are designed against trace data, land as plain Rust (or frozen prompt files), and must win on the bench matrix to merge

Quick wins (grab whenever)

  • /copy palette completion for all/log arguments
  • Mouse-wheel scroll on the palette popup
  • rift --version check against the update cache (nudge in headless too)
  • Session file size cap (compact stored history past N MB)
  • RIFT.md template improvements as real-world usage accumulates

Known risks

riskmitigation
Provider shims reintroduce the bugs rift exists to fixper-provider hardening tests against live servers; capability matrix gates "supported" status
Binary size creep (tree-sitter, syntect)track size in CI; feature-flag heavy deps
Scope creep toward generic chat appevery feature must serve the coding-agent loop; say no to the rest
Solo-maintainer bus factorCI is the reviewer: clippy -D warnings, tests, live PTY smoke tests