A simple command-line todo application built with Rust. Learn Rust fundamentals through building a practical CLI tool with file persistence.
# Clone or create the project
cd cli-todo-rust
# Add dependencies
cargo add clap --features derive
cargo add serde --features derive
cargo add serde_jsonAll commands use 0-based indexing (tasks are numbered 0, 1, 2, 3...).
# Add a task
cargo run -- add "Buy groceries"
cargo run -- add "Walk the dog"
cargo run -- add "Finish homework"
# List all tasks
cargo run -- list
# Output:
# 0: Buy groceries [ ]
# 1: Walk the dog [ ]
# 2: Finish homework [ ]
# Mark a task as complete
cargo run -- complete 0
# Output: Task Buy groceries is completed!
# List again to see completed status
cargo run -- list
# Output:
# 0: Buy groceries [x]
# 1: Walk the dog [ ]
# 2: Finish homework [ ]
# Remove a task by index
cargo run -- remove 1
# Output: Removed: Todo { description: "Walk the dog", completed: false }- ✅ Add todos - Create new tasks with descriptions
- ✅ Remove todos - Delete tasks by index (0-based)
- ✅ List todos - Display all tasks with completion status
- ✅ Complete todos - Mark tasks as done without removing them
- ✅ JSON persistence - Data saved to storage/todo-file.json
- ✅ Error handling - Graceful handling of missing files and invalid indices
- ✅ Visual indicators - [ ]for incomplete,[x]for completed
cli-todo-rust/
├── src/
│   └── main.rs          # Main application code
├── storage/
│   └── todo-file.json   # JSON file storage (created automatically)
├── Cargo.toml           # Project dependencies
├── README.md            # This file
└── LEARNING_NOTES.md    # Rust learning notes on error handling
# Development build
cargo build
# Optimized release build
cargo build --release
# Run the release binary directly
./target/release/cli-todo-rust list┌─────────────────────────────────────┐
│  PROGRAM START                      │
└─────────────────────────────────────┘
           ↓
┌─────────────────────────────────────┐
│  Parse CLI arguments                │
│  (clap with derive macros)          │
│  → Command: Add/Remove/List/Complete│
└─────────────────────────────────────┘
           ↓
┌─────────────────────────────────────┐
│  load_data()                        │
│  → Check if storage/todo-file.json  │
│    exists                           │
│  → If yes: deserialize JSON         │
│  → If no: create empty Vec + file   │
│  → Return Result<Vec<Todo>, Error>  │
└─────────────────────────────────────┘
           ↓
┌─────────────────────────────────────┐
│  Match on command:                  │
│                                     │
│  Add → Push Todo to vec             │
│  Remove → vec.remove(index)         │
│  List → Print all with status       │
│  Complete → Set completed = true    │
└─────────────────────────────────────┘
           ↓
┌─────────────────────────────────────┐
│  save_todos(&vec)                   │
│  → Serialize vec to pretty JSON     │
│  → Write to storage/todo-file.json  │
│  → Return Result<(), Error>         │
└─────────────────────────────────────┘
           ↓
┌─────────────────────────────────────┐
│  Print feedback to user             │
│  PROGRAM EXIT                       │
└─────────────────────────────────────┘
// Todo struct (data model)
struct Todo {
    description: String,
    completed: bool
}
// Commands enum (CLI interface)
enum Commands {
    Add { description: String },
    Remove { index: usize },
    List,
    Complete { index: usize }
}Todos are stored in storage/todo-file.json as a JSON array:
[
  {
    "description": "Buy groceries",
    "completed": true
  },
  {
    "description": "Walk the dog",
    "completed": false
  }
]- See LEARNING_NOTES.mdfor detailed Rust error handling concepts
- Covers: Result types, ?operator, error propagation, unwrap variants
- clap 4.x - Command-line argument parser with derive macros
- serde 1.x - Serialization/deserialization framework
- serde_json 1.x - JSON support for serde
This project is a tutorial toy project demonstrating:
- Basic Rust syntax and ownership
- CLI argument parsing with clap
- File I/O and error handling
- JSON serialization with serde
- Pattern matching and enums
- Result types and error propagation