Agentic coding assistant (TUI) for self-hosted LLMs via Ollama or any OpenAI-compatible server. Rust, edition 2024.
cargo build # debug build
cargo build --release # -> target/release/thoth
cargo test # unit tests
cargo test -- --ignored # network tests (need internet)
cargo clippy -- -D warnings # CI enforces zero warningsmain.rs: CLI args and subcommands, config resolution, model discovery, spawns the agent task, picks TUI or one-shot print mode (-p).client.rs: LLM transport. Two paths: OpenAI-compatible SSE (/chat/completions) and Ollama native (/api/chat, auto-detected via/api/version) which allows settingnum_ctxper request. Streams content, thinking and tool-call deltas.ThinkFilterroutes inline<think>tags to reasoning.agent/mod.rs: the agentic loop (model call, tool calls, results, repeat). Owns conversation history, permission gating, duplicate-call breaker, auto-compact at 2/3 of the window, truncation recovery, /compact, /recap, editor-context injection,!commandruns.agent/prompt.rs: system prompt. Environment (cwd, os, date, git branch), project scan, guardrail rules, instruction file (THOTH.md/AGENTS.md/ CLAUDE.md, pointers followed), project memory.agent/session.rs: per-project state under~/.thoth/projects/<key>/: saved transcript for--continueand the persistent permission allowlist. Written atomically, owner-only on unix.tools/:fs.rs(read/write/edit, read-coverage registry, unified diffs),search.rs(grep with optional context lines),shell.rs(foreground with timeout, background mode),web.rs(DuckDuckGo or Google CSE, html to text),memory.rs(project memory, session recap, project key),mod.rs(tool schemas, dispatch, permission rules).editor.rs: VS Code awareness. Reads state files written by the companion extension (thoth-for-vscode) from~/.thoth/ide/, falls back to window titles on Windows.ui/mod.rs: ratatui interface. Transcript with an incremental wrap cache, streaming, permission prompts, input history, mouse scroll, ctrl+o.ui/render.rsturns blocks into styled lines,ui/theme.rsholds colors and glyphs,ui/input.rshandles@pathattachments and completion.upgrade.rs:thoth upgrade, replacing the running binary with the latest verified GitHub release.
- Guardrails go in code, not in the prompt, whenever possible. See the
read registry in
tools/fs.rs: write_file needs every line of a file covered by earlier reads, not just "a read happened". - Anything that touches the user's machine must be visible in the UI: full command lines, full diffs, even when auto-approved.
- "Always allow" is scoped, never a blanket grant: shell is keyed by
program (
shell:cargo), web_fetch by host. Seepermission_keyintools/mod.rs. - Tool output sizes are budgeted for 16-32k token windows. Keep the caps in
tools/mod.rsandtools/fs.rsin that spirit. - Anything parsed from the network or from a file can be hostile: no slicing by byte offset, no unvalidated value in a filesystem path.
- Prefer runtime
cfg!(windows)over#[cfg]so both branches compile on every platform.#[cfg]items need a non-Windows stub. - No new heavyweight dependencies without a good reason.