Magi Agent — Terminal AI Assistant in Rust
Magi Agent (magi-rs) is a terminal AI assistant in Rust, modeled on Claude Code. It drives an LLM provider through a multi-turn tool loop with sandboxed filesystem and shell access, and persists every conversation to a locally-encrypted SQLite store. Nothing leaves your machine except the model API calls you explicitly authorize.
Why Magi?
Most AI coding agents are SaaS-bound and tied to a single vendor. Magi is built for the opposite constraint: environments where source code cannot leave the machine.
| Principle | What it means in Magi |
|---|---|
| Local-first | A single static Rust binary. Conversation history and project knowledge live in an encrypted SQLite file on disk — never a third-party vault. |
| Encrypted at rest | Every stored record is sealed with Argon2id → AES-256-GCM-SIV → Reed-Solomon FEC. The DB master key lives in the OS keyring, separate from the LLM API key. |
| Sandboxed by default | Every filesystem tool is confined to the workspace via PathGuard; the shell tool runs a strict command allowlist with a hard ban on shell metacharacters. |
| Human-in-the-loop | Each tool call must be approved inline in the TUI before it runs. |
| Fails safe | If the OS keyring is unavailable, the session degrades to ephemeral (no persistence) rather than ever encrypting with a constant key. |
Features
| Area | Capability |
|---|---|
| TUI front-end | ratatui app with Normal / Selection / Visual modes, UTF-8-safe cursor handling, system clipboard integration |
| Agent loop | Multi-turn orchestration, bounded tool calls (max 15), repetitive-call detection, ANSI/control-char sanitization, interactive approval gate |
| Provider | Anthropic Messages API with SSE streaming + tool_use assembly and 429 retry; StaticProvider fallback when no key is configured |
| Sandboxed tools | ls, view, edit, grep, bash (strict allowlist), project_knowledge (persistent facts) |
| Encrypted memory | SQLite (WAL) with one cached key derivation per session (Argon2id + per-DB salt), AES-256-GCM-SIV, Reed-Solomon FEC, salt-integrity self-heal |
| OAuth login | PKCE flow against the Anthropic Console (/login in the TUI) |
| OS keyring | API key in magi-rs, DB master key in magi-rs-internal (kept separate); magi-rust legacy names auto-migrated |
Installation
Prerequisites
- A Rust toolchain (stable, edition 2021) — install via rustup.
ripgrep(rg) onPATHfor thegreptool.- An Anthropic API key from console.anthropic.com (recommended), set via
ANTHROPIC_API_KEYorkey.txt./login(OAuth) also works but is best-effort — see Configuration.
Build from source
Run
Usage
Launch the TUI and type a prompt. The agent streams its reply, and any tool it wants to run pauses for your approval.
TUI modes
| Mode | Enter with | Keys |
|---|---|---|
| Normal | (default) | type to chat · Ctrl+S → Selection · Ctrl+V paste · Ctrl+C copy selection / quit if none |
| Selection | Ctrl+S |
↑/↓ pick a message · y copy whole message · Enter → Visual |
| Visual | Enter (in Selection) |
Shift+←/→ character-level selection · y copy |
Tool approval
When the agent requests a tool, an inline prompt appears: y approves, c / Esc denies. The agent blocks up to 5 minutes waiting for your response.
Slash commands (handled by the UI, never sent to the model)
| Command | Effect |
|---|---|
/login |
Start the OAuth (PKCE) login flow — best-effort, may be rate-limited (see Configuration); prefer an API key |
/logout |
Clear stored API keys |
/clear |
Clear the on-screen conversation |
/help |
Show available commands |
/exit, /quit |
Leave the app |
Tools
| Tool | Purpose |
|---|---|
ls |
List directory contents (sandboxed) |
view |
Read file contents (sandboxed) |
edit |
Create / overwrite a file (sandboxed) |
grep |
RipGrep-backed search (sandboxed) |
bash |
Run a shell command — strict allowlist |
project_knowledge |
Persist project facts to encrypted memory |
The bash allowlist is: ls git npm cargo rg cat echo pwd grep mkdir touch find rm diff node python pytest (with cargo restricted to test / build / check), plus a hard ban on the shell metacharacters | & ; > < ` $ ( ) { } \.
Configuration
API key & model discovery
Resolved in order, first hit wins:
ANTHROPIC_API_KEYenvironment variable- OS keyring, service
magi-rs, keyANTHROPIC_API_KEY - OS keyring, service
magi-rust(legacy) — auto-migrated tomagi-rson read key.txtin the working directory: line 1 = API key, line 2 = optional model
The model is read from ANTHROPIC_MODEL, then key.txt line 2, defaulting to claude-sonnet-4-6. With no key found, the agent falls back to StaticProvider.
A standard API key is the recommended, supported path. Create one at console.anthropic.com (with billing enabled) and set ANTHROPIC_API_KEY or put it in key.txt.
/login(OAuth) is best-effort. It reuses Anthropic's Claude Code OAuth client to mint a key on your account — a flow intended for Anthropic's own clients — so it may be rate-limited, throttled, or blocked at any time and is not guaranteed. Prefer a standard API key.
key.txtand its variants are gitignored. Never commit a real key.
How It Works
┌───────────────────────────────┐
│ main.rs │
│ config discovery · keyring │
│ master-key · tool registration│
└───────────────┬───────────────┘
│
┌───────────────┴───────────────┐
▼ channels ▼
┌──────────────────┐ ◄───────────► ┌──────────────────┐
│ TUI (ratatui) │ │ Agent │
│ Normal/Sel/Vis │ │ history · loop │
└──────────────────┘ │ approval gate │
└────────┬─────────┘
┌──────────────────────────────────┼──────────────────────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Provider │ │ Tools │ │ EncryptedSqlite │
│ Anthropic (SSE) │ │ ls/view/edit │ │ CryptoVault │
│ Static fallback │ │ grep/bash/know. │ │ Argon2→GCM-SIV→RS│
└──────────────────┘ └──────────────────┘ └──────────────────┘
The agent loop
- The user message is appended to history (and persisted to encrypted memory if attached).
provider.stream_messages(...)streamsTextDeltachunks to the TUI; each chunk is sanitized of ANSI / control characters.- The assembled assistant
Messageis collected onMessageDone. - If it contains
ToolUseblocks, each tool is approved, executed, and its result pushed back as aUser-roleToolResult— then the loop repeats. - With no tool requested, the final assistant text is returned.
Invariants: at most 15 tool calls per query; three consecutive identical tool calls abort ("repetitive tool call detected"); each tool call needs UI approval within 5 minutes or it is denied.
Security Model
- Encrypted memory. Argon2id (OWASP 2025 parameters: 64 MiB, t=3, p=4) derives a 32-byte key from the DB master password and a per-database random salt. The key is derived once per session and cached (
Zeroizing) — no longer per record. AES-256-GCM-SIV (nonce-misuse resistant) provides authenticated encryption with a freshOsRngnonce per record; Reed-Solomon FEC wrapsnonce‖ciphertextagainst bit-rot. Blob layout:[u8 version][u32 LE len][RS(nonce‖ciphertext)]. - Salt integrity & self-heal. The per-DB salt is stored RS-encoded with a SHA-256 checksum. An absent / corrupt / unrecoverable salt is treated as absent and the store resets to a fresh start (no on-disk migration) rather than bricking; minor bit-rot is corrected and prior history survives.
- Secrets separation. The LLM API key (keyring
magi-rs) and the DB master password (keyringmagi-rs-internal) are kept in separate keyring services. Rotating the API key never invalidates the local conversation DB. - Filesystem sandbox. Every file-touching tool canonicalizes its target and validates it against the workspace root via
PathGuard(handling Windows\\?\verbatim prefixes, null-byte attacks, and lexical normalization). - Shell sandbox. The
bashtool enforces a per-binary argument allowlist and bans shell metacharacters to prevent subshell injection on both PowerShell and bash.
Project Structure
src/
main.rs -- config discovery, master-key bootstrap, tool registration, entry
agent/
mod.rs -- Agent orchestrator: multi-turn tool loop + approval gate
provider.rs -- Provider trait; AnthropicProvider (SSE) + StaticProvider
tools/
mod.rs -- Tool trait + ToolError
ls.rs read.rs write.rs grep.rs bash.rs knowledge.rs
system/
database.rs -- EncryptedSqliteMemory (MemoryStore) over SQLite + CryptoVault
fs.rs grep.rs secrets.rs path_guard.rs
utils/
crypto.rs -- CryptoVault: Argon2id → AES-256-GCM-SIV → Reed-Solomon FEC
services/
oauth.rs -- OAuth PKCE login (callback on 127.0.0.1:54545)
tui/
mod.rs -- ratatui app (Normal / Selection / Visual)
docs/ -- public overview & philosophy (OVERVIEW.md)
Cargo.toml -- edition 2021, MIT OR Apache-2.0
Testing
Full verification (matches the project's per-phase gate):
Some tests use real OS resources:
system::secretstests write to the real OS keyring under servicemagi-rs-test-suite, and the OAuth callback server binds port54545— avoid two interactive/loginflows at once. DB/crypto tests are isolated viatempfile.
Requirements
| Component | Required | Notes |
|---|---|---|
| Rust toolchain (stable, edition 2021) | Yes | via rustup |
ripgrep (rg) |
For the grep tool |
on PATH |
| OS keyring | For persistence | Windows Credential Manager / macOS Keychain / Secret Service. Without it the session runs ephemeral |
| Anthropic API key | For live replies | env var, keyring, key.txt, or /login |
Documentation
docs/OVERVIEW.md— what Magi is, themagi-corefoundation, and the multi-perspective philosophy behind the name.
License
Dual-licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Credits
The Magi name comes from Neon Genesis Evangelion (1995, Hideaki Anno / Gainax), where three supercomputers — Melchior, Balthasar, and Caspar — govern critical decisions through structured consensus. The same multi-perspective philosophy backs the sibling magi-core crate, which Magi Agent integrates for its planned multi-perspective consult workflow.