❯ /architecture▊
One event loop, no render races
The agent runs in a spawned task and reaches the interface only through events. Nothing that renders mutates state, and nothing that thinks touches the screen.
62k
lines of Rust across 207 files
~900
tests, none of which touch the network
51
slash commands, one file each
16
built-in tools before a single MCP server
── the shape
Everything hangs off one select!
Conversations own their state, the runtime owns the turns, and the renderer owns nothing at all.
one tokio::select! loop
main ─ App (thin coordinator on a single select! loop)
├─ AppState
│ └─ Conversations ── focused + background chats
each owns: messages · forked session · agent task
├─ AgentRuntime.spawn(TurnSpec) ── the one place a turn starts
│ └─ run_agent_loop ── LLM ↔ tools, events tagged by id
│ ├─ semantic hint ── skills + MCP tools per prompt
│ └─ task tool ⇒ sub-agent (fg) | detached (bg)
├─ SemanticService ── e5-small ONNX + TF-IDF + RRF
├─ ToolRegistry ── bash · edit · write · task · todo …
├─ MCPManager ── stdio / http / sse, OAuth in the keyring
├─ providers ── DeepSeek web · OpenAI · Anthropic · Gemini
└─ TUI render ── reads the focused chat; never mutates
CPU-heavy work — ONNX embeddings, the SHA-3 proof-of-work — runs on blocking threads, so a long hash never costs you a frame.
── a turn
What happens between Enter and the answer
Six steps, and you can stop it at any of them.
01
Match
The prompt is scored against skills and MCP tools. The top hits become an ephemeral hint that never persists into the conversation history.
02
Send
The provider forks a session for this chat. On DeepSeek that means solving its SHA-3 proof-of-work locally, then streaming the reply over SSE.
03
Call
Tool calls come out of the stream — native ones where a provider emits them, parsed ones everywhere else, with the provider’s own call id.
04
Ask
Anything with side effects stops at an approval modal with a readable preview: a real diff for edit, the actual text for write, a warning for paths outside the workspace.
05
Checkpoint
Before a write lands, the old content goes into an append-only journal. /undo puts it back — and refuses when the file changed after the edit, because then someone else was editing too.
06
Judge
In GOAL mode a second agent reads the result against your success criteria and either signs off or sends concrete fixes back into the loop.
── src/
Where everything lives
Layering is enforced by the module graph: tools know nothing about the app, the renderer knows nothing about providers.
- app/
- The coordinator: conversations, the event loop, the agent runtime, keys, GOAL, the search screen, the providers panel.
- provider/
- DeepSeek web (auth, PoW, SSE, sessions) plus OpenAI-compatible, Anthropic Messages and Gemini clients.
- agent/
- The agent loop, the sub-agent runner, the tool-call parser.
- semantic/
- The local RAG layer: embedder, hybrid index, corpora, history store, eval harness.
- tools/
- Shell and PTY, edit and write, todo, timers, task, and the semantic builtins.
- mcp/
- Clients, transports, config discovery across eight sources, the manager, OAuth.
- server/
- The OpenAI-compatible gateway: catalog routing, hyper transport, the dialect itself.
- tui/
- ratatui views, widgets, markdown rendering — and the theme table this website borrows.
- update/
- Channels, manifest verification, the staged binary swap.
- acp/
- Agent Client Protocol server mode: JSON-RPC over stdio, for IDEs that speak it.
── rails
The parts that say no
An agent with a shell is a security surface. These are the places where it is deliberately less convenient.
- scoped approvals
- A rule is a tool plus a scope: bash · cargo test allows that prefix, edit · <folder> allows writes there. A compound command gets no scope at all — git status && rm -rf / starts with git status.
- checkpoints
- Every edit and write is journaled first. Files that look like secrets (.env, *.pem, id_rsa) and anything over 8 MiB are never copied anywhere — such an edit is honestly marked irreversible instead.
- the keyring
- The DeepSeek session and MCP OAuth tokens live encrypted in the OS keyring, never in a plaintext config file.
- untrusted text
- Project instructions (AGENTS.md, CLAUDE.md…) come from someone else’s repository: symlinks aren’t followed, the text arrives inside an envelope with a one-time marker, and the absolute rules are repeated after it.
- off-limits files
- The edit tool refuses to write the agent’s own config or any MCP config, and aborts when a file changed since it was read.
── evidence
Measured, not asserted
Claims on this page are checkable in the repository, and most of them are checked on every push.
- ~900 tests
- Unit tests with no network, run on Windows, Linux and macOS.
- MRR evals
- Retrieval quality is a number, not a feeling: 0.927 for skills, 0.836 for MCP tools.
- field ladder
- A scenario harness runs the agent against real tasks — and fails a run where every tool call errored but the summary sounded fine.
- gates
- fmt, clippy -D warnings and the suite block the commit locally and the merge in CI.
- --locked
- Cargo.lock is committed and CI builds from it: a release is the exact dependency set the tests passed on.
ci
✓ cargo fmt --check
✓ cargo clippy -- -D warnings
✓ cargo test --bin pooprusteek ~900 tests, no network
✓ cargo test semantic::eval -- --ignored
skills MRR 0.927
mcp tools MRR 0.836
✓ build: windows x64/arm64 · linux x64/arm64 · macos arm64
✓ package: pooprusteek-setup.exe + install.sh + manifest