Roadmap
spai is a Claude-Code-style CLI agent. The roadmap below reflects that focus.
The earlier “AI-native OS” ambitions (FUSE, eBPF, PAM, a Wayland compositor, a
bootable ISO) are parked — see Parked ideas — in favour of
being an excellent terminal AI agent first.
Shipped
Section titled “Shipped”The core agent is built and working:
- Single in-process
spaibinary (no daemon, socket, or systemd) - Native tool-calling agent loop
- Multi-provider support — Anthropic (native), OpenAI-compatible, Ollama
- Tools —
bash,read_file,write_file,edit_file,glob,grep,list_dir - Parser-based command-safety classification (mvdan.cc/sh) with permission tiers
- Execution modes — manual / auto / plan
- Polished one-shot renderer — spinner, tool display, tier confirmations
- Rich inline REPL — history, slash commands,
@file, Ctrl+C interrupt -
spai initonboarding wizard with live connection test - File-backed sessions with token-aware auto-compaction;
spai resume -
spai !!, stdin piping,--local/--autonomous/--dry-run - Streamed markdown rendering (glamour) in the renderer
- Shift-Tab mode cycling and Esc-to-interrupt key handling
- Prebuilt release binaries — tagged cross-compiled releases + CI
- Live
/modelprovider/model switching inside the REPL - Diff preview for
edit_file/write_filebefore confirmation - MCP tool integration — connect external MCP servers, bridge their tools
- More tools —
web_fetch,apply_patch(structured patch/apply) - Expanded tool surface —
git,multi_edit,code_exec, vision input,todo_write,http_request - Test-coverage and permission-classifier hardening pass
- Project context & subagents —
SPAI.mdproject-instructions file,/initscaffold command,delegate(subagent) tool with a hard depth-1 limit, and per-project.spai/settings.tomlpermission overrides - Distribution & polish — shell completions (
completions/spai.{bash,zsh,fish}), amanpage (docs/spai.1), a Homebrew formula (Formula/spai.rb), and.deb/.rpmpackaging vianfpminrelease.yml - Prompt caching & performance — Anthropic
cache_control: ephemeralbreakpoints (system prompt, tools, conversation history), real input/output/cache-read/cache-creation token counts surfaced in/cost(replacing the chars/4 estimate), and a per-Agent-instance cache for theSPAI.mdproject-context disk lookup - Reliability & test coverage —
handleSlashdispatch and the REPL print helpers ininternal/cli/slash.go(46.7% → 59.3% package coverage), and provider streaming edge cases + shared helpers ininternal/ai(74.6% → 89.4% package coverage) - REPL/UX polish — a
/sessionsREPL command listing recent sessions (pinned/current/shell markers, message count, relative age) without leaving the interactive session, and acapOutputLinescap (40 lines) on longoutput-type tool responses in the TTY renderer -
cmd/spai&internal/apptest coverage — provider/config/MCP-lifecycle helpers ininternal/app(19.1% → 42.3% package coverage), and session, disclaimer, and git-branch CLI helpers incmd/spai(6.8% → 29.4% package coverage). TheRunAgent/RunSession/streamTextevent-loop and interactive prompts (main,init.go) remain out of scope — candidates for a future, heavier test-harness task - Provider & tool breadth — a new
web_searchtool (internal/tools/web_search.go) using DuckDuckGo’s keyless HTML endpoint (title/url/snippet results, capped at 10,TierRead), andcode_execlanguage support extended from Python/Node to also cover Ruby and Go (go run), withDescription/Schemaupdated accordingly
The seeded backlog is shipped; these are the next directions, grouped by leverage. Tier 1 is high-leverage, on-theme, and mostly self-contained; Tier 2 adds meaningful features; Tier 3 is polish.
Tier 1 — high leverage, mostly self-contained
Section titled “Tier 1 — high leverage, mostly self-contained”All Tier 1 items shipped — see Recently completed.
Tier 2 — meaningful features
Section titled “Tier 2 — meaningful features”All Tier 2 items shipped — see Recently completed.
Tier 3 — polish
Section titled “Tier 3 — polish”All Tier 3 items shipped — see Recently completed.
Recently completed
Section titled “Recently completed”- Cross-session learned memory — a
remember_facttool the agent calls to persist key/value facts (e.g. “build-command: make gen”) to.spai/memory.jsonl. Facts are deduped by key, capped at a configurable limit (default 200), and injected as a## Learned contextsection in the system prompt afterSPAI.mdon future sessions. Opt-in via[memory] enabled = trueinspaid.toml; disabled by default so existing sessions are unchanged. - Model routing — task-based model selection: a cheap/fast model
(
model_small) for summarisation and auto-compact calls, and a reasoning-capable model (model_strong) for the main agent tool-calling loop. Configured via[routing]inspaid.toml; both fields default to empty, preserving all existing behaviour unchanged. - REPL polish — three interactive niceties, each degrading to today’s plain
behaviour off a TTY (or under
NO_COLOR): multiline input via a"""fenced block or a trailing-backslash continuation, assembled into one agent turn; fuzzy@filecompletion that subsequence-matches a bounded, cached walk of the working tree and inserts the full relative path; and syntax-highlighted diffs that keep the add/remove polarity colors, bold the leading+/-marker, and honour theNO_COLORconvention. All three are invisible to piped/non-interactive use. - Pre/post-tool-use hooks — user-configured shell commands run around tool
execution via
[[hooks]]inspaid.toml. Apre_toolhook can refuse an already-approved tool call (a non-zero exit blocks it and its stderr becomes the model-visible reason); apost_toolhook observes a successful call (e.g. auto-gofmtan edited file) without ever undoing it. Hooks target tools by name glob and an optional matcher on the tool input. They are pure defense-in-depth layered on top of the tier/confirm gate — a hook fires only after the user has approved a call and can only add restrictions, never auto-approve, satisfy a confirm prompt, or change a tier. Zero[[hooks]]means behaviour identical to before. - Named specialized subagents — the
delegatetool now accepts an optionalprofileargument (reviewer,tester,general) that runs the sub-agent with a focused system prompt and a restricted tool allowlist. Built-in defaults work with zero config;[[subagent.profiles]]inspaid.tomladds or overrides profiles. Profile tool allowlists are a strict subset of the parent’s tools — a sub-agent can never be granted capabilities the parent lacks, and all sub-agent actions still go through the sameconfirmFntier gate. - Background / long-running
bash— arun_in_backgroundboolean on thebashtool starts commands without blocking the agent turn, captures combined stdout+stderr in an in-memory job registry keyed by integer id, and returns the job id immediately. A new/jobsREPL command lists all background jobs (id, status, command) and inspects one by id with full captured output. The same permission-classification gate applies to background commands as to foreground ones. -
gh/ PR integration tool — a first-classghtool wrapping the GitHub CLI for PR lifecycle (create, view, list, merge, close, comment, checkout) and convenience branch/push wrappers, with per-subcommand permission tiering: read-only queries (pr-view,pr-list,pr-status) at TierRead; local mutations (pr-checkout,create-branch) at TierWrite; outward-facing operations (push,pr-create,pr-comment,pr-merge,pr-close) at TierElevated. Bash classifier extended with aclassifyGHbranch coveringgh pr,gh run,gh repo,gh issue, andgh release. - OpenAI
reasoning_effortpassthrough — a newreasoning_effortconfig key in[provider](spaid.toml) passes the effort level (“low”, “medium”, “high”) to OpenAI-compatible reasoning models (o1, o3, o4-mini, …). An empty value (the default) omits the field entirely, keeping all existing non-reasoning-model behaviour unchanged. - Optional execution sandbox — an opt-in, default-OFF Linux sandbox
(native Landlock + seccomp, or
bwrapwhen present) restricting filesystem and network access forcode_execand untrustedbash, behind build tags with a compiling no-op fallback on non-Linux. Layered under the permission gate as defense-in-depth — it never replaces a confirmation. Tunable via the optional[sandbox]config section. - Checkpoint &
/undofor file edits — snapshot each file beforewrite_file/edit_file/apply_patch/multi_editmutates it (originals under.spai/checkpoints/<session>/), with/undoand/redoslash commands; create/edit/delete round-trip - Custom slash commands / prompt templates — discover
.spai/commands/*.mdand expand them into prompts with$ARGUMENTS/$1substitution, composing withSPAI.mddiscovery - Provider retry / backoff / rate-limit handling — a shared
http.RoundTripperwrapper retries 429 / transient 5xx with exponential backoff and jitter, honouringRetry-After(delta-seconds and HTTP-date), bounded attempts, and context-cancellation, across all three providers. Tunable via the optional[retry]config section. - First tagged release (
v0.1.0) — cut a tag and publish prebuilt binaries - Per-tool / per-MCP-server permission policy and allowlists
- Streaming MCP tool discovery +
/mcpstatus slash command - Cost/token usage reporting per session
-
@-completion for files and richer slash-command help -
gittool — structured status/diff/log/blame/branch, per-subcommand tiering -
multi_edit— regex find & replace across a glob of files -
code_exec— ephemeral Python/Node execution (explicitly not sandboxed) - Vision input — image files passed through to vision-capable providers
-
todo_write— in-session task list surfaced in the REPL -
http_request— generic REST tool (method/headers/body) -
SPAI.md— auto-discovered project-instructions file injected into the system prompt -
/init— REPL slash command that scaffolds a starterSPAI.md -
delegate— nested subagent tool, depth-limited to 1, sharing the parent’s confirmation gate - Per-project
.spai/settings.tomlpermission overrides, layered over global config - Shell completions —
completions/spai.{bash,zsh,fish}, installed byinstall.sh -
manpage —docs/spai.1, installed byinstall.sh - Homebrew formula —
Formula/spai.rb+brew tap/installinstructions -
.deb/.rpmpackaging vianfpm, wired intorelease.yml - Anthropic prompt caching —
cache_control: ephemeralbreakpoints on the system prompt, tool definitions, and conversation history - Real token usage & cache-hit reporting in
/cost, replacing the chars/4 estimate - Per-session
SPAI.mdproject-context caching on theAgent, avoiding a disk re-read on every turn - REPL slash-command test coverage —
handleSlashdispatch and print helpers ininternal/cli/slash.go - Provider streaming edge cases and shared-helper test coverage in
internal/ai(Anthropic/OpenAI/Ollama) -
/sessionsREPL command — list recent sessions without leaving the interactive session, reusingsession.ListSessions()/ReadPinned() - Terminal-friendly long tool-output display —
capOutputLinesline cap in the REPL renderer, separate from the tool layer’s byte-level cap -
internal/appprovider/config/MCP-lifecycle test coverage (19.1% → 42.3%) -
cmd/spaisession, disclaimer, and git-branch helper test coverage (6.8% → 29.4%) -
web_searchtool — keyless DuckDuckGo HTML-backend search, capped title/url/snippet results -
code_execlanguage breadth — added Ruby and Go (go run) alongside Python and Node
Parked ideas
Section titled “Parked ideas”Genuinely interesting, but out of scope for now. The most promising — ambient
post-error help and repeated-pattern → alias suggestions — can return later as an
optional shell hook that shells out to spai, without fragile keystroke
sniffing.
- FUSE filesystem (
cat /ai/explain/<path>) - eBPF syscall/network observation and anomaly detection
- PAM module for context-aware authentication
- Wayland compositor integration / GUI terminal
- Bootable ISO with
spaipre-installed
Versioning
Section titled “Versioning”Semantic versioning: MAJOR.MINOR.PATCH. The first tagged release of the
refactored agent will be v0.1.0.