Home

Chapter 1 · Project

Build a CLI AI assistant

Estimated time: 2–3 hours

Overview

You have called the OpenAI API, managed conversation history, and extracted structured data. Now you will wire all three together into a real, usable tool.

You are building a command-line AI assistant that supports persistent conversations, a configurable system prompt, API error handling, and a --structured mode that extracts a JSON summary from any text. When you finish, you will have a tool you can actually use day-to-day.

Prerequisites

  • Lesson 1: uv project, .env file
  • Lesson 2: OpenAI client, .create(), error handling
  • Lesson 3: messages list, REPL loop, JSON persistence
  • Lesson 4: Pydantic models, .parse()

Specification

Your CLI tool (assistant.py) must support the following usage:

Interactive chat mode (default)

uv run assistant.py

Starts a REPL loop. Conversation history is saved to history.json and reloaded on the next run. The user types messages; the assistant replies. Typing quit or exit ends the session.

One-shot question mode

uv run assistant.py "What is the speed of light?"

Sends the question, prints the answer, exits. Does not save to history.

Custom system prompt

uv run assistant.py --system "You are a Python code reviewer. Be terse."

Overrides the default system prompt for the session. Works in both modes.

Structured extraction mode

uv run assistant.py --structured "Invoice INV-001, total $500 USD, due 2025-03-01"

Extracts a TextSummary object from the input and prints each field. Does not use conversation history.

Clear history

uv run assistant.py --clear

Deletes history.json and exits with a confirmation message.

Requirements

Suggested approach

Build in this order — each step is runnable before the next:

  1. Set up argparse and print which mode was selected. Verify flags work.
  2. Implement one-shot mode first (no history, single call).
  3. Add interactive REPL mode with in-memory history.
  4. Add JSON persistence (save/load history.json).
  5. Add history trimming.
  6. Add the --structured mode with the Pydantic model.
  7. Add --clear.
  8. Add error handling throughout.
Test each step before moving to the next. It is much easier to find a bug in 20 lines than in 150.

Completion checklist

Extension challenges

Finished early? These are not required, but push the project closer to production quality:

Community Showcase

Finished this project? Share your GitHub repo link in the discussion below. Browse what others built to get inspiration and give feedback.