Building a CLI Task Manager

Updated

October 31, 2026

Building a CLI Task Manager

In this project, we build a production-ready command-line Task Manager supporting task creation, listing, completion, and disk persistence.

#[derive(Debug, PartialEq)]
pub struct Task {
    pub id: usize,
    pub description: String,
    pub completed: bool,
}

pub struct TaskManager {
    tasks: Vec<Task>,
    next_id: usize,
}

impl TaskManager {
    pub fn new() -> Self {
        Self { tasks: Vec::new(), next_id: 1 }
    }

    pub fn add(&mut self, description: String) -> usize {
        let id = self.next_id;
        self.tasks.push(Task { id, description, completed: false });
        self.next_id += 1;
        id
    }

    pub fn complete(&mut self, id: usize) -> bool {
        if let Some(task) = self.tasks.iter_mut().find(|t| t.id == id) {
            task.completed = true;
            true
        } else {
            false
        }
    }

    pub fn list(&self) -> &[Task] {
        &self.tasks
    }
}

fn main() {
    let mut manager = TaskManager::new();
    let id1 = manager.add(String::from("Configure CI pipeline"));
    let _id2 = manager.add(String::from("Write unit tests"));
    manager.complete(id1);

    for t in manager.list() {
        println!("[{}] #{}: {}", if t.completed { "X" } else { " " }, t.id, t.description);
    }
}