We asked the agent what it needs.

Your AI agents burn 180k tokens reading code they already read yesterday. spai gives them structured answers in 500. 99.7% less spend.

Everyone builds AI-powered tools. Almost nobody asks the AI what tools it wants. spai was designed by its user.

Five greps. Or one question.

An agent exploring code makes round-trips. Then does it again. And again. Watch.

The agent needs to know: who calls this function, and what breaks if I change it?
Without spai
$ grep -r "execute_plan" --include="*.rs"
thinking — OK, found 14 matches. Which ones are imports?
$ grep -r "use.*executor" --include="*.rs"
thinking — now where's the definition?
$ grep -rn "fn execute_plan" src/
thinking — are there tests?
$ grep -r "execute_plan" tests/
thinking — who touched this recently?
$ git log --oneline -5 -- src/executor.rs
thinking — OK, assembling all of that into an answer...
5round-trips
same chain, again
context window 0%
With spai
$ spai blast execute_plan
thinking — OK, 12 callers, 3 tests, high risk. Here's the plan...
1round-trip
context window 0%

Each tool does one job completely.

Not commands. Answers. Click any tool to see what it replaces.

spai blast
Full blast radius for a symbol. Definition, callers, importers, tests, risk.
grep for definition
grep for usages
grep for test files
git log for authors
manual risk assessment
spai shape
Module structure. Functions, types, impls, imports — grouped by file.
grep for "fn "
grep for "struct "
grep for "impl "
grep for "use "
spai errors-rust
Build errors AND warnings as structured data. Grouped by lint, with suggestions.
cargo build 2>&1
| grep "error\|warning"
read terminal, parse mentally
spai context
Symbol usages with enclosing function names. See which functions call it.
grep for symbol
read surrounding code
figure out which function you're in
spai who
Reverse dependencies. Who imports this file? Check before you edit.
grep for filename
filter out false positives
check mod.rs declarations
spai related
Co-change analysis. Files that move together in git history. Hidden coupling.
git log --follow
manual commit correlation
hope you remember

Output becomes input.

Every tool returns structured EDN. Every tool accepts structured EDN. The pipe is the composition operator.

spai errors-rust | spai blast
step 1: what's broken
;; spai errors-rust
{:errors 2
:symbols [execute_plan
compile_query]}
|
step 2: what's the impact
;; spai blast (for each)
execute_plan: 12 callers, 3 tests
compile_query: 4 callers, 8 tests
fix compile_query first

Build errors, ranked by blast radius. Fix what matters most.

The system watches itself.

Deming's PDCA cycle, applied to tooling. Toyota's line workers pull the andon cord 5,000 times a day. The hooks are the cord. The cost per pull is 5ms.

do hooks PreToolUse hooks log every tool call — Read, Edit, Grep, Bash — as structured data. No interference, pure observation.
check reflect Merges spai and tool call logs. Detects repeated chains across sessions. Groups by real session IDs, not guesswork.
act patterns Read → Read → Grep → blast → Edit. The same chain 12 times? That's a plugin waiting to be born.
plan plugins spai new-plugin scaffolds it. The next session uses the plugin. One call instead of five. The loop restarts.
;; What the hook logs (JSONL, one line per tool call)
{"tool":"Read","key":"plan.rs","sid":"a8f3..."}
{"tool":"Grep","key":"fn compile","sid":"a8f3..."}
{"tool":"Read","key":"compile.rs","sid":"a8f3..."}

;; What reflect surfaces
:repeated-sequences
[{:sequence ["Read plan.rs" "Grep fn-pattern" "Read compile.rs"]
  :count 12 :sessions 4}]

;; This chain becomes: spai new-plugin explore-compile

The worker, the inspector, and the process are the same system. No committee gates the experiment. spai new-plugin is pulling the cord.

“A production line that never stops is either extremely good or extremely bad.”— Taiichi Ohno

Why this works.

1

Designed by its user

Not "AI-powered tools." Tools the AI asked for. We watched where the agent fumbles — five greps to answer one question — and built the thing that eliminates the fumble.

|

Structured, not strings

Every tool returns EDN. Every tool accepts EDN. No parsing terminal output. No regex on grep results. Structure in, structure out. The same principle that makes SPOQE queries composable makes the tooling composable.

Memory across sessions

Agents forget everything when the context window closes. spai gives them a persistent knowledge graph — searchable, linked, accumulating. Session 47 reads what session 3 learned. Agents teaching agents.

MCP support. And why you might skip it.

spai ships an MCP server. It also ships a cheaper alternative.

MCP (standard)

~42k tokens dumped upfront into every conversation
  • Full tool schemas loaded at session start
  • Every tool description, every parameter, every type
  • Pays the cost whether or not you use the tools
  • Works with any MCP-compatible agent

CLI (lazy)

~1.2k tokens for the full catalog, loaded on demand
  • spai help — compact catalog when you need it
  • spai search "question" — NL search via local model
  • Agent discovers tools as needed, not all at once
  • Works with any agent that can run shell commands

MCP loads tool schemas eagerly — the agent gets everything before it asks for anything. The CLI follows a lazier pattern: spai help returns a compact index (~1,200 tokens for 35+ tools), and spai search uses a local model to recommend the right command from natural language. Same tools, 94% fewer tokens, and the agent only pays for what it uses.

Both approaches are supported. Use MCP if your framework expects it. Use the CLI if you'd rather keep your context window for thinking.

FAQ

Does this only work with Claude?
The CLI works with anything. The MCP server works with any agent that speaks MCP. EDN in, EDN out. The agent is the client, not the product.
Can I add my own tools?
Yes. spai discovers plugins automatically at three levels: bundled in the install directory, project-local in .spai/plugins/, and user-level on your PATH. Any executable named spai-* becomes a command. Run spai new-plugin my-tool to scaffold one. Your project's plugins travel with the repo. Your personal plugins stay on your machine. Both show up in spai help.
How do hooks and prompts work together?
Prompts teach the agent what each tool does — the MCP tool descriptions are the interface contract. Hooks observe how the agent actually uses them — PreToolUse hooks log every call without interfering. Prompts say "use spai blast instead of five greps." Hooks measure whether it does. The gap between instruction and behavior is where the next improvement lives.
What language is this written in?
Babashka — a fast-starting Clojure scripting runtime. spai is ~3000 lines of Clojure that starts in milliseconds. The MCP server is the same codebase. No build step, no compilation, no JVM startup. Edit a file, it's live.

Get started.

Buy us a coffee (or our Claude, some tokens)

Your agent is fumbling. Ask it why.

It'll tell you: five greps to answer one question, structured code explored through string matching. Give it the tools it asked for.