Tech With Galvan

Capstone: Build a CLI Tool from Scratch

2-4 hours • Beginner • Module 12

Design, build, and polish an original command-line tool using everything from this course.

Capstone: Build a CLI Tool from Scratch

Eleven modules. Seventy lessons. Hundreds of lines typed by your own hands. Time to prove it: one original command-line tool, designed and built by you, from an empty file to a working program.

The brief

Build a command-line tool that manages some data with a menu. Requirements:

  1. Menu loop — options displayed, user picks, action runs, repeat until quit
  2. CRUD — Create, Read (view), Update, and Delete entries
  3. Persistence — data survives restarts (JSON, from Module 8)
  4. Error handling — bad input never crashes it (try/except, from Module 8)
  5. Functions — every menu action is its own function (Module 7)
  6. At least one OOP element — a class holding the data logic (Module 9)

Ideas (pick one, or invent your own)

  • Contact book — name, phone, email; search by name
  • Inventory tracker — items, quantities, low-stock warnings
  • Expense logger — amounts with categories, monthly totals
  • Quiz maker — store question banks, take quizzes, save scores
  • Habit tracker — daily checkmarks, streak counting

Pick the one you’d actually use. Boring and finished beats exciting and abandoned.

The architecture (start from this skeleton)

"""My Tool — manages ___ data, stored in data.json."""

import json
import os

DATA_FILE = "data.json"


def load_data():
    if os.path.exists(DATA_FILE):
        with open(DATA_FILE) as f:
            return json.load(f)
    return []


def save_data(data):
    with open(DATA_FILE, "w") as f:
        json.dump(data, f, indent=2)


def view_items(data):
    ...


def add_item(data):
    ...


def main():
    data = load_data()
    while True:
        print("\n1. View  2. Add  3. Update  4. Delete  5. Quit")
        choice = input("Choice: ")
        if choice == "1":
            view_items(data)
        elif choice == "2":
            add_item(data)
            save_data(data)
        # ... 3, 4
        elif choice == "5":
            save_data(data)
            break
        else:
            print("Invalid choice")


if __name__ == "__main__":
    main()

That skeleton already satisfies requirements 1, 3, and 5. Your job: the CRUD functions, the class, the polish.

The build order (how professionals actually work)

Step 1 — The skeleton runs. Menu loop with placeholder functions that print “not implemented yet.” Verify the loop quits cleanly.

Step 2 — Add and View. The core loop of value: put data in, see it come back out. Save after every change.

Step 3 — Update and Delete. Find-by-index or find-by-name, confirm before deleting.

Step 4 — Error-proofing. Letters where numbers go, empty inputs, deleting from an empty list. Try to break your own tool — every crash you find is a try/except you add.

Step 5 — The class. Wrap the data logic in a class (e.g., ContactBook with .add(), .search(), .remove()) and slim the menu functions down to thin wrappers.

Step 6 — One flourish. Search. Sorting. A summary line. One delight feature — not ten.

Self-review rubric

Check Question
Survives Kill it mid-action — does data.json stay valid?
Survives fools Type letters into every numeric prompt
Reads Could a stranger understand each function in 30 seconds?
Persists Restart the program — is everything still there?
Structure Any function longer than ~25 lines? Split it

When you finish

  1. Put it on GitHub with a README (screenshot + how to run)
  2. Deploy or share the repo — your first portfolio piece from your own design
  3. Then walk into the Streamlit course — you’ll build the same skills as beautiful web apps

If you get stuck

Every bug you’ll hit was taught: NameError (scope, Module 7), KeyError (dicts, Module 5), JSONDecodeError (Module 8), infinite loops (Module 6). The course is your search engine — every lesson you completed is now a reference manual.

This is the exam. Open book. Go build. 🚀