D4C: Building a Terminal Coding Agent in Rust from Scratch
Most coding agents optimize for freeform chat — and you find out the model misunderstood you only after your files change. D4C makes planning a first-class, interactive step. Built from scratch in Rust with a native TUI.
What is D4C?
D4C — short for Dirty Deeds Done Dirt Cheap — is a lightweight, modular terminal coding agent built from scratch in Rust with a native TUI. It shares no source code with Claude Code, OpenCode, or any existing agent — it's inspired by their usability, then rebuilt around a different core idea.
That idea: guided workflows over open-ended chat. Most agents take your request and immediately start editing files — you discover scope or misunderstanding only after changes are made. D4C integrates model providers through APIs and treats planning as a first-class, interactive step: repository context is gathered, ambiguities are resolved through a structured questionnaire, assumptions are surfaced for review, and only an approved plan is executed, with checkpoints along the way.
The name is a nod to the JoJo's Bizarre Adventure reference. It stuck.
Why Rust, Why from Scratch
I use coding agents daily, and three frustrations kept coming up — none of them fixable by tweaking someone else's tool:
The problems: freeform chat wastes iterations on misunderstandings; autonomous edits on real codebases are hard to trust; and nothing records why a change was made. On top of that, most agents lock you into one vendor's CLI and treat local models as an afterthought.
So D4C is built from scratch in Rust. Three reasons:
Startup under 100ms
A coding agent should feel like a terminal tool, not a web app. Rust plus Ratatui gets D4C to its first interactive UI frame in under 100ms — no Node runtime booting, no framework hydration.
Provider-agnostic by design
D4C integrates model providers through APIs, not through one vendor's CLI. Self-hosted and local models get first-class support, not a bolted-on compatibility layer.
Guided, auditable workflows
The planning-first interaction model is the core differentiator. Every change traces back to an approved plan, and checkpoints make autonomous edits reviewable instead of scary.
"Most terminal agents optimize for freeform chat. D4C optimizes for getting it right before touching your files."
Key Features
D4C's feature set follows from the planning-first philosophy. Each one exists to reduce surprise, not to add surface area.
Planning-First Workflows
The flagship feature. Before any code changes, D4C gathers repository context, resolves ambiguities through a structured questionnaire, and surfaces its assumptions for review. Only after you approve the plan does execution begin — with checkpoints along the way. This separation of thinking and doing dramatically reduces hallucination and builds trust in autonomous edits.
Native Ratatui TUI
D4C renders with Ratatui + crossterm — a true terminal UI, not a REPL with colored text. Fast startup, full keyboard control, and a layout that stays responsive while streaming model output in the background.
Native MCP Client
D4C implements the Model Context Protocol natively in the Rust core — no external MCP launcher process. Tools and context servers plug in through a standard protocol instead of vendor-specific glue.
Automatic Model Selection
A small embedded router picks the model based on task complexity — cheap models for routine edits, stronger ones for gnarly refactors. No separate heavy service, no external dependency, and it's transparent: you can always see and override what was chosen.
Slash-Command Architecture
Slash commands are the primary interaction surface — not buried menus or chat keywords. Everything the agent can do is discoverable, scriptable, and consistent.
Why an embedded router instead of a bigger service? Model choice is a per-task decision, not a per-session config. Keeping the router small and inside the agent means startup stays fast, there's nothing else to deploy, and the selection logic stays auditable in one place.
Feature Summary
Setup & Architecture
D4C is a Rust workspace split into three crates, each independently testable:
Core Stack
- Rust 2024 — single language, no runtime
- d4c-core — agent logic, tools, MCP client
- d4c-tui — Ratatui + crossterm terminal UI
- d4c-cli — headless / non-interactive entry
- Tokio — async runtime for streaming model I/O
- reqwest — provider API calls over rustls
Architecture Principles
- Crates split: core / TUI / CLI independently testable
- Provider abstraction — no vendor lock-in
- MCP implemented natively in the core crate
- Plans, checkpoints, and tool calls are first-class records
- Model router embedded — no external service
Challenges & Fixes
Building an agent from scratch means building everything twice: once as code, once as an interaction model. These four problems shaped the project the most:
The Trust Problem
The whole reason D4C exists. Early prototypes edited files directly from chat and I stopped trusting them on real codebases. The fix wasn't a confirmation dialog — it was restructuring the interaction: context gathering, a structured questionnaire for ambiguities, surfaced assumptions, and an approved plan with checkpoints before execution starts.
Streaming Output in a TUI
Rendering live model output while keeping a Ratatui layout responsive is trickier than printing to stdout. The solution was an event-driven design on Tokio: model streams push events into a channel, and the TUI redraws from state snapshots — the render loop never blocks on the network.
MCP Without the Glue
Most agents shell out to an external MCP launcher process. D4C implements the protocol natively in the Rust core, which means better error handling and no process-management headaches — but it also meant implementing the protocol's lifecycle, tool discovery, and error semantics by hand.
Provider Abstraction
Every provider's API differs in streaming format, tool-call shape, and error behavior. The abstraction layer normalizes all of it into one internal format — which is also what makes the automatic model router possible: routing is just choosing among normalized providers per task.
"Building from scratch wasn't the hard part. Deciding what the agent should ask before it acts was."
What's Next
D4C is in active development as my daily coding agent. Here's the direction:
Session Memory Persistence
Remember decisions and repository context across sessions. If the agent mapped your project structure yesterday, it shouldn't rediscover it today.
In ProgressRicher Checkpoint Review
Deeper diff inspection at each checkpoint, plus plan revision mid-execution when reality disagrees with the approved plan.
PlannedMulti-Agent Orchestration
Specialized sub-agents for parallel task execution — one builds while another researches, coordinated through the planning layer.
ExploringLocal Model Hardening
D4C is provider-agnostic by design; the next step is first-class support for self-hosted inference (Ollama, vLLM) with the same streaming and tool-call guarantees as hosted APIs.
Exploring