Files
zesdex/CLAUDE.md
T

4.7 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Build & Test

# Build (debug)
cargo build

# Release build
cargo build --release

# Run all tests
cargo test

# Run a single test
cargo test test_name

# Lint
cargo clippy

# Lint with warnings-as-errors
cargo clippy -- -D warnings

Test modules are located inline in production files (not a separate tests/ dir):

  • src/app/harness.rs — guard/verdict parsing tests
  • src/app/runtime/stream/mod.rs — SSE parser tests
  • src/model/memory.rs — memory CRUD + slugify tests
  • src/model/editlog.rs — edit log append/reload tests
  • src/tool/fs/helpers.rs — tool argument extraction tests

Tests use #[cfg(test)] mod tests blocks. There are 37 unit tests total.

Tracing output goes to ~/.local/share/zesdex/zesdex.log. Set RUST_LOG=debug for verbose logging.

Architecture Overview

Zesdex is an autonomous AI coding agent with a TUI — an OpenAI/Anthropic-compatible LLM client wrapped in a tool-use harness with 28 built-in tools.

Detailed architecture documentation is in docs/CODEMAPS/:

File Covers
docs/CODEMAPS/architecture.md System layout, process modes, data flow, key files
docs/CODEMAPS/backend.md Provider, OAuth, IPC, workflow engine, MCP, review, bg bash
docs/CODEMAPS/frontend.md TUI render pipeline, 16 overlays, toasts, input handling
docs/CODEMAPS/data.md Persistence, SQLite msglog, memory files, settings/config
docs/CODEMAPS/dependencies.md 23 Rust crates, 5 external services

Entry Points

src/main.rs — three modes:

  • Single-process (default): TUI + agent loop in one process
  • Daemon (--daemon): background Unix socket server, handles LLM calls
  • Attach (--attach <id>): TUI-only client that connects to a daemon

Core Flow

Controller (key input → Action) → Event Loop → LLM stream → Tool execution → State mutation → TUI render
  │                              │                              │
  │ src/controller/input.rs      │ src/app/runtime/actions/     │ src/tool/
  └── maps keys to Action enum   │── dispatches Action::*      └── 28 tool impls
                                 │    matching on Action variant
                                 │── applies state mutations

Key Patterns

  • State mutationAppStateRest is mutable in-place from actions/mod.rs and controller/input.rs. No generic update function.
  • No DI — modules call Settings::load(), AppConfig::load(), all_tools() directly.
  • Loggingtracing::warn! to ~/.local/share/zesdex/zesdex.log (not stderr, avoids TUI corruption).
  • Error handlinganyhow::Result and anyhow::bail! throughout. No custom error types.
  • Static strings — MCP tool descriptions use Box::leak + OnceLock cache.
  • Toolstrait Tool { fn name() -> &str, fn run() -> Result<String> }, 28 impls, gated by Harness.
  • Shell safetytool/shell_filter/ blocks credential leaks and destructive git commands.

Code Documentation

Every function, struct, enum, trait, module, and significant code block must have a doc comment (/// or //!) that explains:

  • What the function/module does (purpose, not how)
  • Flow — a brief ASCII or prose description of the code flow / data flow above each non-trivial function
  • Why — non-obvious decisions, edge cases, invariants
  • Return — what the caller gets back, especially for Result types

Examples:

/// Parse an SSE data chunk into one or more StreamEvents.
///
/// Flow: buffer → split on '\n' → flush on blank line → JSON parse → match event type
///       → return Token / ToolCallDelta / Usage / Done.
///
/// Edge case: chunk may split mid-line; remaining bytes stay in buffer
/// for the next feed() call.
fn feed(&mut self, chunk: &str) -> Vec<StreamEvent> { ... }

/// The single source-of-truth state struct for the entire application.
///
/// Mutated in-place from two locations: actions/mod.rs (apply_action)
/// and controller/input.rs (key event handlers). Read-only from
/// every other module.
struct AppStateRest { ... }

Rules:

  • Every pub fn needs a doc comment
  • Every pub struct / pub enum / pub trait needs a doc comment
  • Non-trivial private functions (≥10 lines) need a doc comment
  • Write the comment above the code it documents (not inline in the body)
  • Update comments when code behavior changes — stale docs are worse than no docs