Using AI at work

Build Your First Tool with Claude Code: Monthly Totals from an Expense CSV

Use the fictional expenses.csv and requirements note from the previous articles to practice building a first small Python tool. Put the input example, expected output, and constraints in the request, then run the completed summarize.py separately in the Python tool in GPT chat—not in Claude Code—to verify the result.

Show contents

Who this is forBeginners who have completed Claude Code installation and the first read-only exercise and are ready to try generating code for one small file

What you need
  • Have the vibe-expenses practice folder and fictional expenses.csv ready
  • Understand the workflow of checking proposed changes before allowing Claude Code to modify files
  • Have Python installed and be able to run the python command in a terminal
  • Use only fictional data rather than real personal information or payment records

01Start small with one input and one output

The goal of the first hands-on exercise is not a feature-rich expense-tracking app, but a single file, summarize.py, that reads expenses.csv and prints only monthly amount totals. Keeping the scope small makes it easier to verify the AI-generated result yourself. The input is a UTF-8 CSV with the columns date, category, and amount. Assume date uses YYYY-MM-DD and amount is an integer.

ItemFixed requirement for this exerciseVerification criterion
Input fileexpenses.csvDo not modify the original file
Input columnsdate, category, amountDo not arbitrarily require other columns
OutputMonthly amount totals2026-09 = 26600, 2026-10 = 9800
Implementation scopeOne summarize.py fileDo not add unnecessary config files or packages
LibraryPython standard libraryNo external package installation

The important point at this stage is not to make a broad request such as 'build me an expense tracker.' Reduce the chance that AI arbitrarily expands the task with a UI, database, charts, login, or other features, and delegate only a task whose answer can be checked in a single run.

02Put the input, expected output, and constraints in the request

When asking Claude Code to do the task, provide both the input-file structure and the correct answer. An expected output makes it clear what the generated code has to match, and lets you compare the result visually. Also state the boundaries explicitly—for example, 'use only the standard library,' 'do not modify the original CSV,' and 'write only summarize.py.'

Prompt
Create summarize.py in the current folder so that it reads expenses.csv and prints monthly amount totals.

Input:
- UTF-8 CSV
- Column names: date, category, amount
- date format: YYYY-MM-DD
- amount is an integer

Expected output:
2026-09 = 26600
2026-10 = 9800

Constraints:
- Use only the Python standard library
- Do not modify expenses.csv
- Run with python summarize.py expenses.csv
- First explain the required file and planned changes, then create only summarize.py.

This code block is a request for the user to enter, not a Claude Code response. Because the request already contains values that serve as the correct answer, you can later compare the two numbers exactly instead of merely judging whether the result looks plausible.

03Check what will be created before allowing file edits

Claude Code can read the files it needs and may ask for approval before modifying files or running commands. When an approval screen appears, do not press Yes immediately. Check which files were read, whether summarize.py is the only new file, and whether expenses.csv will remain untouched. If it wants to run an unfamiliar command, you can ask it to explain the command's purpose first.

Prompt
Before making changes, confirm the following.
1) Tell me which file you will read and which file you will create.
2) Confirm that expenses.csv will not be modified.
3) Confirm that no external packages will be installed.
4) In one line, tell me how to compare the result with the expected output after running it.

A real Claude Code response can vary by environment and time, so this article does not invent a particular response and present it as a success example. What matters is the file scope and command scope, not the style of the response.

04Review the completed reference code and run command

The summarize.py below is a completed reference implementation that satisfies the requirements in this article. It reads each row with csv.DictReader, takes the first seven characters of date to obtain YYYY-MM, converts amount to an integer, and adds the values by month. It sorts the month keys to make the output order deterministic. This code is not copied from an actual Claude Code-generated response; it was written to reproduce the exercise result and was executed separately for verification.

Prompt
import csv
import sys
from collections import defaultdict

def summarize_monthly(path):
    totals = defaultdict(int)

    with open(path, "r", encoding="utf-8", newline="") as f:
        reader = csv.DictReader(f)
        for row in reader:
            month = row["date"][:7]
            amount = int(row["amount"])
            totals[month] += amount

    return totals

def main():
    if len(sys.argv) != 2:
        raise SystemExit("Usage: python summarize.py expenses.csv")

    totals = summarize_monthly(sys.argv[1])
    for month in sorted(totals):
        print(f"{month} = {totals[month]}")

if __name__ == "__main__":
    main()

Only the standard library is used, so no separate package installation is required. The run command is shown below. On Windows, if py is configured instead of python, you can use `py summarize.py expenses.csv`.

Prompt
python summarize.py expenses.csv

05Compare the output with the expected values line by line

In the Python tool in GPT chat, the code above and the fictional expenses.csv were saved as files and `python summarize.py expenses.csv` was actually run. Standard output exactly matched the two lines below. This verification was not performed in Claude Code.

Prompt
2026-09 = 26600
2026-10 = 9800
MonthExpectedActualResult
2026-092660026600Match
2026-1098009800Match

At this stage, confirm only that these two lines matched. Do not overgeneralize this result to assume that the tool also handles other CSV formats, blank values, or invalid numbers. The result matched only for the current test data and current requirements.

You can also check the totals by hand once. September is 12000 + 1450 + 8500 + 3200 + 1450 = 26600, and October contains one entry of 9800, so the total is 9800. With a small example like this, cross-checking program output against a human-calculated reference value makes it easier to trace where results diverge when the functionality is expanded later.

06Stop when the answer is correct instead of adding more features

A common form of scope expansion in a first tool is, 'Since we've built this much, let's also add category totals, charts, and automatic saving.' But the completion condition for this article is simply that the two monthly-total lines are correct. Once that condition is met, keep the current state as a baseline and separate additional features into later requests.

  • Confirm that no unexpected files other than summarize.py were created.
  • Confirm that the contents of expenses.csv did not change.
  • Confirm that no external package installation was added.
  • Confirm that the two output lines exactly match the expected values.
  • Keep additional features out of this request and separate them into the next task.

The next article puts the project rules in CLAUDE.md so you do not have to rewrite long constraints every time. That file is also project context read by Claude Code at session start rather than an enforcement mechanism, so the key is to keep it short and specific.

What to check yourself

In the Python tool in GPT chat, saved summarize.py and the fictional expenses.csv using Python 3, then ran `python summarize.py expenses.csv` · Claude Code not actually run

  • Confirmed that the Python code uses only the standard-library modules csv, sys, and collections.defaultdict
  • Confirmed that expenses.csv is opened read-only as UTF-8 and the original is not modified
  • Confirmed that the first 7 characters of date are used as the month and amount is converted with int before summation
  • Confirmed that actual stdout exactly matches the two lines `2026-09 = 26600` and `2026-10 = 9800`
  • Confirmed that the request includes the input, expected output, standard-library constraint, and prohibition on modifying the original file
  • Confirmed that the article does not incorrectly state that execution or verification was performed in Claude Code
Verification limits

Verification was performed only with the six-row fictional CSV in this article. It does not verify exception cases such as blank values, invalid dates, or nonnumeric amount values, and Claude Code's own generated result or interface was not actually tested.