🧾

    Command-Line To-Do App

    Intermediate Project — Learn File Handling, Data Persistence, and OOP

    🧠 Project Overview

    A To-Do List app is one of the most essential beginner–intermediate Python projects. It teaches file management, user input handling, and object-oriented programming (OOP).

    In real life, the same logic is used in productivity software like Todoist or Microsoft To Do — just with a graphical interface instead of command line.

    🎯 Goal

    Build a command-line To-Do app that can:

    • • Add, delete, and update tasks
    • • Mark tasks as complete
    • • Save and load data from a file
    • • Organize tasks by category, due date, or priority
    • • Provide clean user experience through menus

    🧩 Core Concepts

    • • File I/O (reading and writing text or JSON files)
    • • Classes & Objects (OOP design)
    • • Input validation and error handling
    • • String and date manipulation
    • • Loops and conditional logic
    • • Data persistence

    💡 Technologies & Concepts Used

    FeatureDescription
    open()File reading/writing
    json moduleStructured storage
    datetimeFor due dates & reminders
    coloramaCLI color highlighting
    osCheck and manage file existence

    ⚙️ Starter Code

    💡 Note: Interactive Code

    This is a command-line app that uses input() for user interaction. The browser demo below shows a simplified version. For the full interactive experience, copy the code below and run it in your local Python environment (IDLE, VS Code, or terminal).Jump to the Browser Demo.

    Here's a functional starting version of your app. Copy it to your local Python editor and run it.

    import json
    from datetime import datetime
    
    class Task:
        def __init__(self, title, priority="Medium", category="General", completed=False, created=None, due=None):
            self.title = title
            self.priority = priority
            self.category = category
            self.completed = completed
            self.created = created or datetime.now().strftime("%Y-%m-%d %H:%M")
            self.due = due
    
        def mark_done(self):
            self.completed = True
    
        def to_dict(self):
            return self.__dict__
    
    class TodoApp:
        def __init__(self, filename="tasks.json"):
            self.filename = filename
            self.tasks = self.load_tasks()
    
        def load_tasks(self):
            try:
                with open(self.filename, "r") as f:
                    data = json.load(f)
                    return [Task(**t) for t in data]
            except (FileNotFoundError, json.JSONDecodeError):
                return []
    
        def save_tasks(self):
            with open(self.filename, "w") as f:
                json.dump([t.to_dict() for t in self.tasks], f, indent=4)
    
        def add_task(self):
            title = input("Task title: ")
            if not title.strip():
                print("❌ Title cannot be empty.")
                return
            priority = input("Priority (High/Medium/Low): ") or "Medium"
            category = input("Category: ") or "General"
            due = input("Due date (YYYY-MM-DD, optional): ") or None
            task = Task(title, priority, category, False, None, due)
            self.tasks.append(task)
            self.save_tasks()
            print(f"✅ Task '{title}' added.")
    
        def list_tasks(self):
            if not self.tasks:
                print("📭 No tasks found.")
                return
            for i, t in enumerate(self.tasks, 1):
                status = "✔️" if t.completed else "❌"
                print(f"{i}. {t.title} [{t.priority}] ({t.category}) - {status}")
    
        def mark_complete(self):
            self.list_tasks()
            try:
                index = int(input("Enter task number to mark complete: "))
                self.tasks[index-1].mark_done()
                self.save_tasks()
                print("✅ Task marked complete!")
            except (ValueError, IndexError):
                print("❌ Invalid selection.")
    
        def delete_task(self):
            self.list_tasks()
            try:
                index = int(input("Enter task number to delete: "))
                task = self.tasks.pop(index-1)
                self.save_tasks()
                print(f"🗑️ Deleted '{task.title}'.")
            except (ValueError, IndexError):
                print("❌ Invalid number.")
    
        def search_tasks(self):
            term = input("Search keyword: ").lower()
            results = [t for t in self.tasks if term in t.title.lower() or term in t.category.lower()]
            if results:
                print(f"🔍 Found {len(results)} result(s):")
                for t in results:
                    print(f"- {t.title} ({t.category}) [{t.priority}]")
            else:
                print("No matches found.")
    
        def menu(self):
            while True:
                print("
    --- TO-DO MENU ---")
                print("1. Add Task")
                print("2. List Tasks")
                print("3. Mark Complete")
                print("4. Delete Task")
                print("5. Search")
                print("6. Exit")
                choice = input("Choose option: ")
    
                if choice == "1": self.add_task()
                elif choice == "2": self.list_tasks()
                elif choice == "3": self.mark_complete()
                elif choice == "4": self.delete_task()
                elif choice == "5": self.search_tasks()
                elif choice == "6":
                    print("👋 Goodbye!")
                    break
                else:
                    print("❌ Invalid choice.")
                    
    if __name__ == "__main__":
        TodoApp().menu()

    🚀 How to Run Locally:

    1. 1. Copy the code above
    2. 2. Save it as todo_app.py
    3. 3. Open terminal and run: python todo_app.py
    4. 4. Follow the interactive menu to add, list, and manage tasks

    🎮 Browser Demo (Simplified Version)

    This demo version shows the core functionality without user input (browser limitation):

    To-Do App Demo

    Try the simplified browser-compatible version of the To-Do app

    Try it Yourself »
    Python
    import json
    from datetime import datetime
    
    class Task:
        def __init__(self, title, priority="Medium", category="General", completed=False):
            self.title = title
            self.priority = priority
            self.category = category
            self.completed = completed
            self.created = datetime.now().strftime("%Y-%m-%d %H:%M")
    
        def mark_done(self):
            self.completed = True
    
        def __str__(self):
            status = "✔️" if self.completed else "❌"
            return f"{self.title} [{self
    ...

    💬 Expected Output (Full Version)

    --- TO-DO MENU ---
    1. Add Task
    2. List Tasks
    3. Mark Complete
    4. Delete Task
    5. Search
    6. Exit
    Choose option: 1
    Task title: Study Python
    Priority: High
    Category: Study
    ✅ Task 'Study Python' added.

    🚀 Enhancement Ideas

    1️⃣ Add Colors (User Interface)

    Install colorama to make CLI text colorful:

    pip install colorama

    Then highlight statuses:

    from colorama import Fore, Style
    print(Fore.GREEN + "✔ Completed" + Style.RESET_ALL)
    print(Fore.RED + "❌ Pending" + Style.RESET_ALL)

    This simple change boosts readability — important for apps used daily.

    2️⃣ JSON Storage (Structured & Expandable)

    Instead of plain text lines, use JSON to save metadata:

    {
      "title": "Study Python",
      "priority": "High",
      "category": "Education",
      "completed": false,
      "created": "2025-11-09 20:14",
      "due": "2025-11-15"
    }

    You can then sort, filter, and search efficiently — similar to a small database.

    3️⃣ Due Dates & Notifications

    Use datetime and timedelta to detect overdue tasks:

    from datetime import datetime
    due_date = datetime.strptime(task.due, "%Y-%m-%d")
    if due_date < datetime.now():
        print("⚠️ Overdue!")

    Later, integrate plyer.notification for desktop popups or even email reminders with smtplib.

    4️⃣ Priority Levels & Sorting

    Store priority as integers (1=High, 2=Medium, 3=Low), then sort automatically:

    sorted_tasks = sorted(self.tasks, key=lambda t: {"High":1,"Medium":2,"Low":3}[t.priority])

    5️⃣ Categories & Filters

    Let users list tasks by category:

    cat = input("Enter category: ")
    for t in self.tasks:
        if t.category.lower() == cat.lower():
            print(t.title)

    Organizing by category is essential for productivity — exactly how project management tools work internally.

    6️⃣ Validation and Error Recovery

    Wrap critical operations with try/except and confirmations:

    try:
        index = int(input("Enter index: "))
        if index not in range(1, len(self.tasks)+1):
            raise ValueError
    except ValueError:
        print("❌ Please enter a valid task number.")

    7️⃣ CLI Menus and Keyboard Shortcuts

    Add quick commands like: a → Add task, l → List all, m → Mark complete. This improves speed for experienced users.

    8️⃣ Auto Backup

    Each time the app saves, also write a backup:

    import shutil
    shutil.copy("tasks.json", "tasks_backup.json")

    9️⃣ Analytics / Statistics

    Calculate: Completed vs pending tasks, Average task age, Most common category

    done = sum(t.completed for t in self.tasks)
    print(f"Progress: {done}/{len(self.tasks)} tasks done!")

    🔟 Simple Encryption

    To keep personal tasks safe:

    import base64
    def encrypt(data): return base64.b64encode(data.encode()).decode()
    def decrypt(data): return base64.b64decode(data).decode()

    Use this before saving JSON — basic, but effective for privacy.

    💡 NEXT STEPS — From Intermediate to Advanced

    To evolve this into a professional-level tool, start introducing modular architecture and optional GUI.

    🧱 1. Modularize Code

    Split into separate files:

    todo/
     ┣ main.py
     ┣ models.py (Task class)
     ┣ storage.py (save/load)
     ┣ utils.py (helpers)
     ┗ menu.py

    This teaches maintainable structure used in all professional codebases.

    🧠 2. Add CLI Arguments (sys / argparse)

    Let users run commands directly:

    python todo.py --add "Buy groceries"
    python todo.py --list

    Use Python's argparse library:

    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("--add")
    args = parser.parse_args()

    📦 3. Add SQLite Database

    Instead of JSON, use SQLite for instant data retrieval:

    import sqlite3
    conn = sqlite3.connect("tasks.db")

    Then map each task into a table with SQL CRUD operations — identical to backend app logic.

    💬 4. Add Natural Language Input

    Use simple parsing: "Add Buy milk tomorrow at 5pm"

    Then interpret "tomorrow" using libraries like dateparser to auto-create due dates.

    🪄 5. Add Notifications or Email Reminders

    Use:

    • plyer → desktop notifications
    • smtplib → email reminders
    • schedule → automated checks

    This makes your CLI feel like a background productivity daemon.

    🌐 6. Connect to Cloud Storage (Advanced)

    Save tasks online using Google Drive API, Firebase, or Supabase so you can access them anywhere. This brings your Python CLI closer to a SaaS-level product.

    🧑‍💻 7. Build GUI Version

    Turn this into a desktop app:

    • • Use tkinter for offline version
    • • Use customtkinter or PyQt5 for modern design
    • • Eventually connect to backend via Flask/FastAPI

    This is how you move from console → app development.

    📱 8. Export to Mobile

    Convert the same logic into a React Native or Flutter app with shared logic from your Python backend.

    🧩 9. Integrate AI Suggestions

    Let an AI assistant prioritize or label tasks automatically by reading their text:

    "Study Python OOP" → category = Education, priority = Medium

    This can use OpenAI or your future FlickAI when ready.

    🧾 10. Monetize It

    Add:

    • • Rewarded ads or donation links
    • • Premium features (cloud sync, reminders)
    • • Affiliate banners ("Buy productivity planner")

    Even a CLI can be monetized through GitHub Sponsors or Gumroad templates.

    ⚙️ Super Advanced Tips for Expert Coders

    • Use Async I/O: Replace normal file I/O with asyncio + aiofiles for instant responsiveness.
    • Add Unit Tests: Write automated pytest cases for each method (add_task, delete_task, etc.).
    • Implement Logging System: Use logging module for detailed app logs instead of prints.
    • Track Time Spent: Add start/stop timestamps for time management reports.
    • Command History: Store user actions in a log file to undo/redo actions.
    • Versioning: Auto-save task versions every edit like a lightweight Git system.
    • REST API: Convert into Flask REST API (backend) so frontends or other devices can sync tasks.
    • Voice Commands: Integrate speech_recognition to add tasks using microphone.
    • Cross-Platform Installer: Bundle into an .exe or .app using PyInstaller or cx_Freeze.
    • Cloud-Based Dashboard: Deploy to web (Render / Railway / Supabase) and manage via browser.
    • Machine Learning Add-On: Predict overdue likelihood or categorize automatically using simple models (e.g., scikit-learn).

    ✅ Next Steps

    1. Start with the base version above and test all functions.
    2. Add enhancements one by one (don't jump straight to everything).
    3. Learn to debug using print/logging and handle exceptions gracefully.
    4. Refactor into modular files for easier maintenance.
    5. Add small features like reminders and category filters first.
    6. Document your app with a README, screenshots, and usage examples.
    7. Push your finished project to GitHub or Replit and include in your portfolio or CV.

    Each new feature is a learning milestone — by finishing this project, you'll understand how real developers structure, persist, and maintain applications.

    Back to Projects

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service