Welcome to a new series. In the upcoming posts, we will see step by step how I’ve been slowly cooking up a CLI application to manage tasks (To-Do’s). This idea was born with the purpose of solving one of the challenges proposed by CodeCrafters: Project #1 - CLI To-Do List App.

This first article serves as an entry point and recipe book. The goal is for you to be able to read each chapter with the repository open on your other screen and, instead of just sticking to the theory, you can follow every architectural decision and every ingredient we add directly in the real code.
Base project repository: github.com/rafafrdz/todo-cli-rs
How to read this series (without getting lost) #
Recommended order:
- Architecture and boundaries,
- Domain and errors,
- Persistence: contract vs implementation, 3.1. Testing strategy and technical debt,
- CLI and output contract,
- Evolution to TUI with ratatui.
That order is no accident. It naturally reflects how the project was built: first design decisions, then implementation by layers.
Series chapters (the tasting menu) #
1) The kitchen’s foundations (Architecture) #
- Post:
Todo CLI in Rust 1. Hexagonal architecture in a small project - Recommended link: docs/architecture.md
- Complement: docs/step-1-mvp.md
Here we explain why hexagonal + screaming architecture was chosen in a small project, and what problems it avoids when you start iterating.
2) The main ingredients (Domain and errors) #
- Post:
Todo CLI in Rust 2. Immutable domain and typed errors by layer - Links:
This block is the heart of the system: invariants, state transitions, and error propagation with context.
3) The pantry (Persistence: contract vs implementation) #
- Post:
Todo CLI in Rust 3. JSON persistence, contract vs implementation - Links:
This chapter defines the repository contract with a trait, implements two adapters (in-memory and JSON to disk), and delves into dependency inversion materialized in Rust.
3.1) The tastings (Testing strategy and technical debt) #
- Post:
Todo CLI in Rust 3.1. Testing strategy and explicit technical debt - Links:
- src/tasks/adapters/persistence/in_memory_task_repository.rs (
testsmodule) - src/tasks/adapters/persistence/json_file_task_repository.rs (
testsmodule)
- src/tasks/adapters/persistence/in_memory_task_repository.rs (
Quality control for the pantry: behavior tests for each adapter, isolation with tempdir, why we don’t share tests between implementations, and the technical debt we document instead of hiding.
4) Basic plating (CLI Layer) #
- Post:
Todo CLI in Rust 4. Creating the CLI with clap - Links:
Here terminal UX is connected with the technical contract: strong parsing, typed Uuid, and dual table/json output.
5) Michelin Star: from CLI to TUI (ratatui) #
- Post:
Todo CLI in Rust 5. Next step, moving from CLI to TUI with ratatui - Links:
This closing proposes the natural evolution of the project: adding a new interface adapter (TUI) by reusing the current domain and use cases.
What you take away if you try the full menu #
By the time you finish devouring the 6 articles, you will have seen:
- How to design a CLI in Rust without turning
main.rsinto a tangled mess of coupled spaghetti. - How to use Hexagonal Architecture to pragmatically isolate the domain, application, and infrastructure.
- How to model strongly typed errors that help both the diner (end user) and the chef (developer).
- How to prepare the project to evolve the recipe (adding graphical interfaces or changing databases) without the sauce breaking.
If you are interested in building terminal tools in Rust that withstand real changes and feel robust, this series will bring you much more than a “15-minute microwave todo app” tutorial. See you at the stoves in the first chapter!