Build a Daily Health Monitor with Claude

Use the Claude API to analyze daily health logs and surface wellness patterns.

Introduction

30 Second Summary

You probably notice patterns in your health all the time. Maybe you sleep badly after skipping exercise, or your energy dips every Wednesday. The tricky part is remembering enough data points to confirm what's actually a pattern versus a coincidence.

In this project, you will build a command-line health monitor powered by Claude AI. You'll log daily check-ins and ask Claude to analyze your history for patterns you might miss.

What You'll Build

A Python CLI tool that logs daily health metrics to a JSON file and uses the Claude API to analyze patterns across multiple days of entries. Each time you run it, you answer a few quick prompts about your sleep, mood, and exercise, then ask Claude to spot correlations you might not notice on your own.

By the end of this project, you'll have:

  • A working health_monitor.py script that logs daily entries (sleep, mood, exercise, symptoms) to a local JSON file.
  • A carefully crafted system prompt that turns Claude into a personal wellness pattern analyst.
  • Multi-day trend analysis that surfaces correlations and actionable insights as you log more data.
  • Secret Mission: A weekly summary report that Claude generates and saves as a formatted markdown file.

Are there any prerequisites?

You'll need basic Python knowledge (variables, functions, loops). No prior AI or API experience is needed.

Set Up Your Environment

Before writing any code, you need to confirm all the pieces of your environment are connected and working together. A quick verification now saves debugging headaches later.

In this step, you'll confirm Python, your API key, and the Anthropic SDK are all ready. Then you'll create the file where your health monitor will live.

In this step, get ready to:
  • Confirm Python and your virtual environment are working.
  • Verify your Anthropic API key is set correctly.
  • Create the health_monitor.py file for your project.
Verify Python

The Anthropic SDK requires Python 3.9 or higher. Your virtual environment is already active, so a quick version check confirms everything is in order.

  • Confirm your Python version by running this command in your terminal:
python3 --version

You should see output like Python 3.9.x or higher (for example, Python 3.11.5).

Seeing command not found?

Make sure your virtual environment is still active. You should see its name in parentheses at the start of your terminal prompt.

If your virtual environment is active but python3 isn't found, your Python installation may not be on your system PATH.

Help me fix my Python version or PATH issue

Verify your API key is set

The Anthropic SDK automatically reads your API key from the ANTHROPIC_API_KEY environment variable. You don't need to pass it in your code, but it must be set in your current terminal session.

  • Confirm the environment variable is set by running:
echo $ANTHROPIC_API_KEY

You should see your API key value printed in the terminal.

Why an environment variable?

Storing your API key as an environment variable keeps it out of your source code. If you ever share or version-control your project, the key stays private on your machine.

🙋‍♀️ Seeing a blank line instead of your key?

The variable may not be set in this terminal session. Re-export it by running:

export ANTHROPIC_API_KEY='your-api-key-here'

Replace your-api-key-here with the key you copied from console.anthropic.com.

Help me set my ANTHROPIC_API_KEY environment variable

Verify the SDK and create your project file

One final check before you start coding. You'll confirm the Anthropic SDK imports correctly, then create the file where all your health monitor code will live.

  • Test that the SDK is importable by running:
python3 -c "import anthropic; print('SDK ready')"

You should see SDK ready printed in your terminal.

Seeing ModuleNotFoundError?

This means the anthropic package isn't installed in your active virtual environment. Reinstall it by running:

pip install anthropic

Then try the import test again.

Help me fix my anthropic SDK import error

  • Create your project file by running:
touch health_monitor.py
  • Confirm the file exists by running:
ls

You should see health_monitor.py listed in the output.

What is this file for?

The health_monitor.py file is where you'll write all the code for your health monitor. It will handle logging daily check-ins, storing data, and sending your health history to Claude for analysis.

  • Open health_monitor.py in Cursor by clicking on it in the Explorer sidebar.

The file is empty for now. You'll start adding code in the next step.

Your environment is locked and loaded. Next up, you'll build the data logger that captures your daily health check-ins.

Build the Health Data Logger

Your environment is set up and the Anthropic SDK is ready to go. Before you connect Claude, you need a way to capture and store daily health data.

In this step, you will build the data layer for your health monitor. This means creating functions that save health entries to a JSON file and an interactive prompt that collects your daily check-in.

In this step, get ready to:
  • Create functions that load and save health entries to a JSON file.
  • Build an interactive logging prompt with input validation.
  • Test your logger by recording entries and viewing them.
Create the data model

Every health entry needs a consistent structure so Claude can analyze it later. You will track seven metrics: sleep hours, sleep quality, mood, energy, exercise, symptoms, and notes.

  • In health_monitor.py, add the imports and data file constant by copying the following code:
import anthropic
import json
import os
from datetime import datetime, date


DATA_FILE = "health_data.json"

What does this code do?

These imports bring in the libraries your project needs.

  • anthropic is the Claude SDK (you will use it in the next step).
  • json handles reading and writing your health data file.
  • os checks whether the data file exists before trying to read it.
  • datetime and date stamp each entry with today's date automatically.
  • DATA_FILE is a constant that names the JSON file where entries are stored.
  • Save health_monitor.py.

You won't see a change yet. The next chunk uses these imports to build the persistence functions.

  • Below the DATA_FILE line, add the load_entries() function:
def load_entries():
    if os.path.exists(DATA_FILE):
        with open(DATA_FILE, "r") as f:
            return json.load(f)
    return []

What does this code do?

load_entries() reads all existing health entries from health_data.json. If the file does not exist yet (first run), it returns an empty list so your code never crashes on a missing file.

  • Save health_monitor.py.

You won't see a visible change yet. The next function completes the save side of the pair.

  • Below load_entries(), add the save_entries() function:
def save_entries(entries):
    with open(DATA_FILE, "w") as f:
        json.dump(entries, f, indent=2)

What does this code do?

save_entries() writes the full list of entries to health_data.json. The indent=2 argument makes the file human-readable so you can open it and inspect your data anytime.

  • Save health_monitor.py.

You won't see a change yet. The next chunk builds the interactive prompt that uses both of these functions.

Seeing a syntax error?

  • Make sure each function starts at column 0 (no leading spaces before def).
  • Check that you have two blank lines between DATA_FILE and def load_entries(), and two blank lines between each function definition.

Help me fix a syntax error in my health_monitor.py file

Build the logging interface

Now you need a way to actually record a health check-in. The log_entry() function will prompt you for each metric and validate numeric inputs so bad data does not sneak in.

  • Below save_entries(), add the log_entry() function:
def log_entry():
    print("\n--- Daily Health Check-In ---\n")

    today = date.today().isoformat()
    print(f"Date: {today}")

    sleep_hours = input("Hours of sleep last night (e.g., 7.5): ").strip()
    try:
        sleep_hours = float(sleep_hours)
    except ValueError:
        sleep_hours = 0.0

    sleep_quality = input("Sleep quality (1-10): ").strip()
    try:
        sleep_quality = int(sleep_quality)
        sleep_quality = max(1, min(10, sleep_quality))
    except ValueError:
        sleep_quality = 5

    mood = input("Mood (1-10): ").strip()
    try:
        mood = int(mood)
        mood = max(1, min(10, mood))
    except ValueError:
        mood = 5

    energy = input("Energy level (1-10): ").strip()
    try:
        energy = int(energy)
        energy = max(1, min(10, energy))
    except ValueError:
        energy = 5

    exercise = input("Exercise today (e.g., '30 min walk' or 'none'): ").strip()
    symptoms = input("Any symptoms (e.g., 'headache, fatigue' or 'none'): ").strip()
    notes = input("Additional notes (or press Enter to skip): ").strip()

    entry = {
        "date": today,
        "sleep_hours": sleep_hours,
        "sleep_quality": sleep_quality,
        "mood": mood,
        "energy": energy,
        "exercise": exercise,
        "symptoms": symptoms,
        "notes": notes,
    }

    entries = load_entries()
    entries.append(entry)
    save_entries(entries)

    print(f"\nEntry saved for {today}!")
    return entry

What does this code do?

This function walks you through a daily check-in with seven prompts.

  • Numeric fields (sleep_hours, sleep_quality, mood, energy) use try/except blocks. If you type something that is not a number, the code falls back to a safe default instead of crashing.
  • max(1, min(10, value)) clamps ratings between 1 and 10 so the data stays consistent for Claude's analysis later.
  • Text fields (exercise, symptoms, notes) accept any string. No validation needed.
  • At the end, the function loads existing entries, appends the new one, and saves everything back to disk.
  • Save health_monitor.py.

You won't see a change yet. You will test this function in the next substep.

Indentation errors in log_entry?

Python is strict about indentation. Every line inside the function must be indented by exactly 4 spaces. The try and except keywords must align at the same level, and the lines inside each must be indented one more level.

Help me fix indentation errors in my log_entry function

  • Below log_entry(), add the view_entries() function:
def view_entries():
    entries = load_entries()
    if not entries:
        print("\nNo entries yet. Log your first health check-in!")
        return

    print(f"\n--- Your Health Log ({len(entries)} entries) ---\n")
    for entry in entries[-7:]:
        print(f"  {entry['date']} | Sleep: {entry['sleep_hours']}h (quality: {entry['sleep_quality']}/10) | "
              f"Mood: {entry['mood']}/10 | Energy: {entry['energy']}/10 | "
              f"Exercise: {entry['exercise']}")
    if len(entries) > 7:
        print(f"\n  (Showing last 7 of {len(entries)} entries)")

What does this code do?

view_entries() displays your most recent health log in a compact one-line-per-day format.

  • It shows only the last 7 entries so the output stays readable even after weeks of logging.
  • If you have no entries yet, it prints a friendly message instead of crashing on empty data.
  • Save health_monitor.py.

You won't see a visible output yet. The next substep tests both functions together.

✔️ Awesome, I've got everything!

Great. Double check you have saved health_monitor.py with all four functions.

ⓧ I'd like to double check the full code

Here is the complete health_monitor.py so far:

import anthropic
import json
import os
from datetime import datetime, date


DATA_FILE = "health_data.json"


def load_entries():
    if os.path.exists(DATA_FILE):
        with open(DATA_FILE, "r") as f:
            return json.load(f)
    return []


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


def log_entry():
    print("\n--- Daily Health Check-In ---\n")

    today = date.today().isoformat()
    print(f"Date: {today}")

    sleep_hours = input("Hours of sleep last night (e.g., 7.5): ").strip()
    try:
        sleep_hours = float(sleep_hours)
    except ValueError:
        sleep_hours = 0.0

    sleep_quality = input("Sleep quality (1-10): ").strip()
    try:
        sleep_quality = int(sleep_quality)
        sleep_quality = max(1, min(10, sleep_quality))
    except ValueError:
        sleep_quality = 5

    mood = input("Mood (1-10): ").strip()
    try:
        mood = int(mood)
        mood = max(1, min(10, mood))
    except ValueError:
        mood = 5

    energy = input("Energy level (1-10): ").strip()
    try:
        energy = int(energy)
        energy = max(1, min(10, energy))
    except ValueError:
        energy = 5

    exercise = input("Exercise today (e.g., '30 min walk' or 'none'): ").strip()
    symptoms = input("Any symptoms (e.g., 'headache, fatigue' or 'none'): ").strip()
    notes = input("Additional notes (or press Enter to skip): ").strip()

    entry = {
        "date": today,
        "sleep_hours": sleep_hours,
        "sleep_quality": sleep_quality,
        "mood": mood,
        "energy": energy,
        "exercise": exercise,
        "symptoms": symptoms,
        "notes": notes,
    }

    entries = load_entries()
    entries.append(entry)
    save_entries(entries)

    print(f"\nEntry saved for {today}!")
    return entry


def view_entries():
    entries = load_entries()
    if not entries:
        print("\nNo entries yet. Log your first health check-in!")
        return

    print(f"\n--- Your Health Log ({len(entries)} entries) ---\n")
    for entry in entries[-7:]:
        print(f"  {entry['date']} | Sleep: {entry['sleep_hours']}h (quality: {entry['sleep_quality']}/10) | "
              f"Mood: {entry['mood']}/10 | Energy: {entry['energy']}/10 | "
              f"Exercise: {entry['exercise']}")
    if len(entries) > 7:
        print(f"\n  (Showing last 7 of {len(entries)} entries)")
Test logging entries

Your data functions are ready. Time to run them and confirm entries are being saved to disk.

  • Load your script in interactive mode by running this command:
python3 -i health_monitor.py

What does this command do?

The -i flag tells Python to run the script and then drop you into an interactive prompt (>>>). This loads all your function definitions so you can call them directly.

  • At the >>> prompt, call log_entry() by running:
log_entry()
  • The script will prompt you for each metric. Fill in some test values:
  • Enter 7.5 for hours of sleep.
  • Enter 8 for sleep quality.
  • Enter 7 for mood.
  • Enter 6 for energy level.
  • Enter 30 min walk for exercise.
  • Enter none for symptoms.
  • Press Enter to skip the notes field.

You should see the message Entry saved for followed by today's date.

  • Now view your saved entry by running:
view_entries()

You should see a formatted line showing today's date, your sleep hours, mood, energy, and exercise.

  • Exit the interactive prompt by pressing Ctrl+D (macOS) or Ctrl+Z then Enter (Windows).
  • Confirm the data file was created by running:
cat health_data.json

You should see your test entry formatted as a JSON array with all seven fields (date, sleep_hours, sleep_quality, mood, energy, exercise, symptoms, notes).

Seeing 'ModuleNotFoundError: No module named anthropic'?

This means your virtual environment is not active. Activate it again before running the script:

source venv/bin/activate

Then try python3 -i health_monitor.py again.

Help me fix a ModuleNotFoundError for the anthropic module

🙋‍♀️ No health_data.json file after running log_entry()?

  • Make sure you answered all the prompts. If you pressed Ctrl+C during the prompts, the function exits before saving.
  • Check you are in the correct directory. Run ls and confirm you see health_monitor.py listed.

Help me figure out why health_data.json was not created

Your data logger is working. Next up, you will connect Claude as your health analyst and write a system prompt that turns raw data into personalized wellness insights.

Connect Claude as Your Health Analyst

Your health logger can record daily check-ins and display them back to you. That's useful, but you're still the one spotting patterns across entries.

In this step, you'll connect Claude as your personal health analyst. You'll write a function that sends your logged health data to the Claude API and receives back pattern-based insights you might not notice on your own.

In this step, get ready to:
  • Set up the Anthropic client inside a new analysis function.
  • Engineer a system prompt that turns Claude into a wellness pattern analyst.
  • Build and test the full analysis function that calls the Claude API.
Set up the Anthropic client

The Anthropic Python SDK automatically reads your ANTHROPIC_API_KEY environment variable when you create a client. You already have import anthropic at the top of your file, so all you need is to instantiate the client inside a new function.

  • In health_monitor.py, scroll to the bottom of the file (below the view_entries() function).
  • Add the start of your analyze_health() function by copying the following code:
def analyze_health():
    entries = load_entries()
    if len(entries) < 2:
        print("\nLog at least 2 days of data before requesting an analysis.")
        return

    client = anthropic.Anthropic()

What does this code do?

  • load_entries() pulls in all saved health entries from your JSON file.
  • The guard clause checks you have at least 2 entries. Pattern analysis needs multiple data points to be meaningful.
  • anthropic.Anthropic() creates the API client. It automatically finds your ANTHROPIC_API_KEY from your environment.

You won't see a change yet. The next chunk adds the system prompt that tells Claude how to behave.

Engineer the health analysis prompt

A system prompt is a set of instructions that shapes how Claude responds. For health analysis, you want Claude to look for correlations, reference specific data points, and keep suggestions actionable.

  • Directly below the client = anthropic.Anthropic() line you just added, paste the following system prompt:
    system_prompt = """You are a personal wellness pattern analyst. Your role is to analyze daily health log entries and identify meaningful patterns, correlations, and trends.

When analyzing health data:
- Look for correlations between metrics (e.g., sleep quality vs. next-day energy, exercise vs. mood)
- Identify positive patterns the user should maintain
- Flag concerning trends that deserve attention
- Be specific: reference actual dates and numbers from the data
- Keep insights actionable: suggest one concrete thing to try
- Be encouraging but honest
- You are NOT a doctor. Frame insights as observations, not diagnoses.

Format your response as:
1. Key Patterns (2-3 observations with specific data references)
2. What's Working Well (1-2 positives)
3. Something to Try (1 specific, actionable suggestion)

Keep your response concise and conversational."""

Why does this prompt work well?

The prompt gives Claude a clear role (wellness pattern analyst), specific behaviors (reference dates, stay actionable), boundaries (not a doctor), and a structured output format. This is prompt engineering in action. The more specific your instructions, the more useful the responses.

The response format (Key Patterns, What's Working Well, Something to Try) ensures you always get structured, scannable output instead of a wall of text.

You won't see a change yet. The next chunk sends this prompt to Claude along with your health data.

Build the analysis function

Now you need to format your health entries as text, send them to Claude Haiku 4.5 along with the system prompt, and display the response.

  • Directly below the system_prompt string you just added, paste the following code to complete the function:
    entries_text = json.dumps(entries[-14:], indent=2)

    message = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=1024,
        system=system_prompt,
        messages=[
            {
                "role": "user",
                "content": f"Here are my recent health log entries. Please analyze them for patterns and insights:\n\n{entries_text}",
            }
        ],
    )

    print("\n--- Claude's Health Insights ---\n")
    print(message.content[0].text)
    print()

What does this code do?

  • entries[-14:] grabs up to 14 recent entries. This keeps the API request focused and avoids sending too much data.
  • json.dumps(..., indent=2) converts the entries into a readable JSON string that Claude can parse.
  • client.messages.create() sends the request to the Claude API. The system parameter passes your prompt as a top-level instruction, not inside the messages array.
  • model="claude-haiku-4-5" selects Claude Haiku 4.5, a fast and affordable model ideal for structured analysis tasks.
  • message.content[0].text extracts Claude's text response from the API response object.

Before testing, make sure you have at least 2 entries in your health_data.json file. If you only logged one entry in the previous step, you'll need to log a second one first.

  • Save health_monitor.py.
  • Test your analysis function by running this command in your terminal:
python -c "from health_monitor import analyze_health; analyze_health()"

You should see Claude's health insights printed to your terminal, organized into Key Patterns, What's Working Well, and Something to Try sections.

Not seeing any output?

  • If you see "Log at least 2 days of data before requesting an analysis", you need more entries. Run python -c "from health_monitor import log_entry; log_entry()" to add another entry, then try the analysis again.
  • If you see an authentication error, confirm your ANTHROPIC_API_KEY is set in the same terminal session. Run echo $ANTHROPIC_API_KEY to check.
  • If you see an indentation error, make sure all the code inside analyze_health() is indented with 4 spaces. Every line after def analyze_health(): needs to be indented.

Help me debug my Claude API call in health_monitor.py

✔️ Awesome, I've got everything!

Great. Double check you've saved health_monitor.py.

ⓧ I'd like to double check the full code

Here's what your full health_monitor.py should look like at this point:

import anthropic
import json
import os
from datetime import datetime, date


DATA_FILE = "health_data.json"


def load_entries():
    if os.path.exists(DATA_FILE):
        with open(DATA_FILE, "r") as f:
            return json.load(f)
    return []


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


def log_entry():
    print("\n--- Daily Health Check-In ---\n")

    today = date.today().isoformat()
    print(f"Date: {today}")

    sleep_hours = input("Hours of sleep last night (e.g., 7.5): ").strip()
    try:
        sleep_hours = float(sleep_hours)
    except ValueError:
        sleep_hours = 0.0

    sleep_quality = input("Sleep quality (1-10): ").strip()
    try:
        sleep_quality = int(sleep_quality)
        sleep_quality = max(1, min(10, sleep_quality))
    except ValueError:
        sleep_quality = 5

    mood = input("Mood (1-10): ").strip()
    try:
        mood = int(mood)
        mood = max(1, min(10, mood))
    except ValueError:
        mood = 5

    energy = input("Energy level (1-10): ").strip()
    try:
        energy = int(energy)
        energy = max(1, min(10, energy))
    except ValueError:
        energy = 5

    exercise = input("Exercise today (e.g., '30 min walk' or 'none'): ").strip()
    symptoms = input("Any symptoms (e.g., 'headache, fatigue' or 'none'): ").strip()
    notes = input("Additional notes (or press Enter to skip): ").strip()

    entry = {
        "date": today,
        "sleep_hours": sleep_hours,
        "sleep_quality": sleep_quality,
        "mood": mood,
        "energy": energy,
        "exercise": exercise,
        "symptoms": symptoms,
        "notes": notes,
    }

    entries = load_entries()
    entries.append(entry)
    save_entries(entries)

    print(f"\nEntry saved for {today}!")
    return entry


def view_entries():
    entries = load_entries()
    if not entries:
        print("\nNo entries yet. Log your first health check-in!")
        return

    print(f"\n--- Your Health Log ({len(entries)} entries) ---\n")
    for entry in entries[-7:]:
        print(f"  {entry['date']} | Sleep: {entry['sleep_hours']}h (quality: {entry['sleep_quality']}/10) | "
              f"Mood: {entry['mood']}/10 | Energy: {entry['energy']}/10 | "
              f"Exercise: {entry['exercise']}")
    if len(entries) > 7:
        print(f"\n  (Showing last 7 of {len(entries)} entries)")


def analyze_health():
    entries = load_entries()
    if len(entries) < 2:
        print("\nLog at least 2 days of data before requesting an analysis.")
        return

    client = anthropic.Anthropic()

    system_prompt = """You are a personal wellness pattern analyst. Your role is to analyze daily health log entries and identify meaningful patterns, correlations, and trends.

When analyzing health data:
- Look for correlations between metrics (e.g., sleep quality vs. next-day energy, exercise vs. mood)
- Identify positive patterns the user should maintain
- Flag concerning trends that deserve attention
- Be specific: reference actual dates and numbers from the data
- Keep insights actionable: suggest one concrete thing to try
- Be encouraging but honest
- You are NOT a doctor. Frame insights as observations, not diagnoses.

Format your response as:
1. Key Patterns (2-3 observations with specific data references)
2. What's Working Well (1-2 positives)
3. Something to Try (1 specific, actionable suggestion)

Keep your response concise and conversational."""

    entries_text = json.dumps(entries[-14:], indent=2)

    message = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=1024,
        system=system_prompt,
        messages=[
            {
                "role": "user",
                "content": f"Here are my recent health log entries. Please analyze them for patterns and insights:\n\n{entries_text}",
            }
        ],
    )

    print("\n--- Claude's Health Insights ---\n")
    print(message.content[0].text)
    print()

Your health monitor now has an AI analyst built in. Next up, you'll add multi-day pattern recognition and a menu system so the whole tool works as a polished interactive CLI.

Add Multi-Day Pattern Recognition

You now have a health logger that collects entries and a Claude-powered analyst that can spot patterns in your data.

In this step, you'll bring everything together into a polished command-line tool. You'll add a navigation menu so you can easily switch between logging, viewing, and analyzing your health data. Then you'll pre-populate a full week of sample entries so Claude has enough data to surface meaningful multi-day patterns.

In this step, get ready to:
  • Verify your prompt handles multi-day trend detection.
  • Add a menu system to navigate between features.
  • Test with a week of sample data to see Claude identify patterns.
Implement trend detection prompting

Your system prompt from the previous step already includes instructions for multi-day pattern recognition. Let's confirm it covers the key directives Claude needs to compare entries across days.

  • In health_monitor.py, scroll to the system_prompt variable inside your analyze_health() function.
  • Verify that the prompt includes the line about correlations:
- Look for correlations between metrics (e.g., sleep quality vs. next-day energy, exercise vs. mood)

Why does this line matter for multi-day analysis?

The phrase "next-day energy" tells Claude to look across entries, not just within a single day. Without cross-day directives, Claude might only summarize individual entries instead of finding patterns like "your mood consistently drops the day after poor sleep."

The prompt also limits data to entries[-14:] (the last 14 entries). This gives Claude enough history for trend detection without exceeding token limits on longer journals.

Your prompt is already set up for multi-day pattern recognition. No changes needed here.

Add a menu system

Right now you can only run individual functions by calling them directly. A menu loop gives users a clean way to navigate between logging, viewing, and analyzing without restarting the script each time.

  • At the bottom of health_monitor.py (after the analyze_health() function), add the main() function by pasting this code:
def main():
    print("=" * 40)
    print("  Daily Health Monitor (Powered by Claude)")
    print("=" * 40)

    while True:
        print("\nWhat would you like to do?")
        print("  1. Log today's health check-in")
        print("  2. View recent entries")
        print("  3. Get AI health insights")
        print("  4. Quit")

        choice = input("\nChoice (1-4): ").strip()

        if choice == "1":
            log_entry()
        elif choice == "2":
            view_entries()
        elif choice == "3":
            analyze_health()
        elif choice == "4":
            print("\nStay healthy! Goodbye.")
            break
        else:
            print("\nPlease enter 1, 2, 3, or 4.")

What does this code do?

The main() function creates an infinite loop that displays a numbered menu after each action. The user picks an option, and the corresponding function runs. Choosing 4 breaks the loop and exits the program.

Each menu option maps directly to a function you already built: log_entry() for option 1, view_entries() for option 2, and analyze_health() for option 3.

  • Directly below the main() function, add the entry point guard:
if __name__ == "__main__":
    main()

What is the entry point guard?

The if __name__ == "__main__" pattern tells Python to only run main() when you execute the file directly (e.g., python health_monitor.py). If you ever import this file from another script, the menu loop won't start automatically.

  • Save health_monitor.py.
  • Test the menu by running:
python health_monitor.py
  • You should see the header banner and a numbered menu with 4 options.
  • Type 4 and press Enter to quit for now.

Menu not showing up?

Make sure the if __name__ == "__main__": line is at the very bottom of your file, outside any function definition. It should not be indented.

Check that main() is defined before the guard line. Python reads top to bottom, so the function must exist before you call it.

help me debug why my health monitor menu isn't appearing when I run the script

Test with sample data

Claude needs multiple days of varied data to find meaningful patterns. Let's pre-populate a full week of entries with realistic variation so you can see the analysis in action.

  • Open health_data.json in your editor and replace its contents with the following sample data:
[
  {
    "date": "2026-05-20",
    "sleep_hours": 7.5,
    "sleep_quality": 7,
    "mood": 7,
    "energy": 7,
    "exercise": "30 min walk",
    "symptoms": "none",
    "notes": "Felt good today"
  },
  {
    "date": "2026-05-21",
    "sleep_hours": 5.0,
    "sleep_quality": 3,
    "mood": 4,
    "energy": 3,
    "exercise": "none",
    "symptoms": "headache, fatigue",
    "notes": "Stayed up too late"
  },
  {
    "date": "2026-05-22",
    "sleep_hours": 6.5,
    "sleep_quality": 5,
    "mood": 5,
    "energy": 5,
    "exercise": "20 min yoga",
    "symptoms": "mild fatigue",
    "notes": "Recovering from yesterday"
  },
  {
    "date": "2026-05-23",
    "sleep_hours": 8.0,
    "sleep_quality": 8,
    "mood": 8,
    "energy": 8,
    "exercise": "45 min run",
    "symptoms": "none",
    "notes": "Great day overall"
  },
  {
    "date": "2026-05-24",
    "sleep_hours": 7.5,
    "sleep_quality": 7,
    "mood": 7,
    "energy": 7,
    "exercise": "30 min walk",
    "symptoms": "none",
    "notes": ""
  },
  {
    "date": "2026-05-25",
    "sleep_hours": 5.5,
    "sleep_quality": 4,
    "mood": 5,
    "energy": 4,
    "exercise": "none",
    "symptoms": "headache",
    "notes": "Poor sleep again"
  },
  {
    "date": "2026-05-26",
    "sleep_hours": 7.0,
    "sleep_quality": 6,
    "mood": 6,
    "energy": 6,
    "exercise": "15 min stretching",
    "symptoms": "mild fatigue",
    "notes": "Getting back on track"
  }
]

What patterns should Claude find?

This sample data has deliberate patterns baked in. On days with poor sleep (May 21 and 25), mood and energy are low and headaches appear. On days with exercise (May 20, 23, 24), all metrics score higher. Claude should spot these correlations and suggest maintaining the exercise habit.

  • Save health_data.json.
  • Run your health monitor again:
python health_monitor.py
  • Type 2 and press Enter to view your entries. You should see all 7 sample days listed.
  • Type 3 and press Enter to get AI health insights.
  • Claude will return a structured analysis referencing specific dates and metrics from your sample data.

Getting an API error on option 3?

Make sure your ANTHROPIC_API_KEY environment variable is still set in this terminal session. If you opened a new terminal, you'll need to activate your virtual environment and export the key again.

help me fix an API error when running my health monitor analysis

  • Type 4 and press Enter to quit.

✔️ Awesome, I've got everything!

Great. Double check you've saved both files.

ⓧ I'd like to double check the full code

import anthropic
import json
import os
from datetime import datetime, date


DATA_FILE = "health_data.json"


def load_entries():
    if os.path.exists(DATA_FILE):
        with open(DATA_FILE, "r") as f:
            return json.load(f)
    return []


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


def log_entry():
    print("\n--- Daily Health Check-In ---\n")

    today = date.today().isoformat()
    print(f"Date: {today}")

    sleep_hours = input("Hours of sleep last night (e.g., 7.5): ").strip()
    try:
        sleep_hours = float(sleep_hours)
    except ValueError:
        sleep_hours = 0.0

    sleep_quality = input("Sleep quality (1-10): ").strip()
    try:
        sleep_quality = int(sleep_quality)
        sleep_quality = max(1, min(10, sleep_quality))
    except ValueError:
        sleep_quality = 5

    mood = input("Mood (1-10): ").strip()
    try:
        mood = int(mood)
        mood = max(1, min(10, mood))
    except ValueError:
        mood = 5

    energy = input("Energy level (1-10): ").strip()
    try:
        energy = int(energy)
        energy = max(1, min(10, energy))
    except ValueError:
        energy = 5

    exercise = input("Exercise today (e.g., '30 min walk' or 'none'): ").strip()
    symptoms = input("Any symptoms (e.g., 'headache, fatigue' or 'none'): ").strip()
    notes = input("Additional notes (or press Enter to skip): ").strip()

    entry = {
        "date": today,
        "sleep_hours": sleep_hours,
        "sleep_quality": sleep_quality,
        "mood": mood,
        "energy": energy,
        "exercise": exercise,
        "symptoms": symptoms,
        "notes": notes,
    }

    entries = load_entries()
    entries.append(entry)
    save_entries(entries)

    print(f"\nEntry saved for {today}!")
    return entry


def view_entries():
    entries = load_entries()
    if not entries:
        print("\nNo entries yet. Log your first health check-in!")
        return

    print(f"\n--- Your Health Log ({len(entries)} entries) ---\n")
    for entry in entries[-7:]:
        print(f"  {entry['date']} | Sleep: {entry['sleep_hours']}h (quality: {entry['sleep_quality']}/10) | "
              f"Mood: {entry['mood']}/10 | Energy: {entry['energy']}/10 | "
              f"Exercise: {entry['exercise']}")
    if len(entries) > 7:
        print(f"\n  (Showing last 7 of {len(entries)} entries)")


def analyze_health():
    entries = load_entries()
    if len(entries) < 2:
        print("\nLog at least 2 days of data before requesting an analysis.")
        return

    client = anthropic.Anthropic()

    system_prompt = """You are a personal wellness pattern analyst. Your role is to analyze daily health log entries and identify meaningful patterns, correlations, and trends.

When analyzing health data:
- Look for correlations between metrics (e.g., sleep quality vs. next-day energy, exercise vs. mood)
- Identify positive patterns the user should maintain
- Flag concerning trends that deserve attention
- Be specific: reference actual dates and numbers from the data
- Keep insights actionable: suggest one concrete thing to try
- Be encouraging but honest
- You are NOT a doctor. Frame insights as observations, not diagnoses.

Format your response as:
1. Key Patterns (2-3 observations with specific data references)
2. What's Working Well (1-2 positives)
3. Something to Try (1 specific, actionable suggestion)

Keep your response concise and conversational."""

    entries_text = json.dumps(entries[-14:], indent=2)

    message = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=1024,
        system=system_prompt,
        messages=[
            {
                "role": "user",
                "content": f"Here are my recent health log entries. Please analyze them for patterns and insights:\n\n{entries_text}",
            }
        ],
    )

    print("\n--- Claude's Health Insights ---\n")
    print(message.content[0].text)
    print()


def main():
    print("=" * 40)
    print("  Daily Health Monitor (Powered by Claude)")
    print("=" * 40)

    while True:
        print("\nWhat would you like to do?")
        print("  1. Log today's health check-in")
        print("  2. View recent entries")
        print("  3. Get AI health insights")
        print("  4. Quit")

        choice = input("\nChoice (1-4): ").strip()

        if choice == "1":
            log_entry()
        elif choice == "2":
            view_entries()
        elif choice == "3":
            analyze_health()
        elif choice == "4":
            print("\nStay healthy! Goodbye.")
            break
        else:
            print("\nPlease enter 1, 2, 3, or 4.")


if __name__ == "__main__":
    main()

Your health monitor is fully functional. You have a polished CLI tool that logs entries, displays your history, and uses Claude to find patterns across multiple days of health data. Next up, try the Secret Mission to generate weekly summary reports.

Secret mission

Weekly Summary Report

Your health monitor gives you on-demand insights, but what about a weekly digest? In this secret mission, you'll add a command that generates a polished markdown report from your week's data and saves it to a file you can share or revisit.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally on your machine. The only ongoing cost comes from Claude API calls, which only happen when you actively run the script and choose the analysis or report options. There are no background services or cloud resources accumulating charges.

Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • Project files: health_monitor.py, health_data.json, and the reports/ directory.
  • Python virtual environment (inside your project folder).
  • The ANTHROPIC_API_KEY environment variable set in your terminal.

Keep everything running

No action needed. Choose this if you plan to keep logging daily health entries and running analyses.

  • Your health_data.json will continue to grow as you log more entries.
  • Claude's analysis improves with more data, so the tool gets more useful over time.
  • API costs are negligible for personal use (fractions of a cent per analysis call).
  • Your Anthropic account remains active with your API key stored in your shell profile.

Pause - I'll come back to this later

Shut down any running processes to free up resources while keeping your files intact for later.

  • If your virtual environment is active, deactivate it by running:
deactivate
  • Your project files, health data, and reports stay on disk. When you return, reactivate the virtual environment and pick up where you left off.

Delete - I don't want to use this again

Remove all project files and configuration. This is permanent.

  • If your virtual environment is active, deactivate it first by running:
deactivate
  • Navigate to your Desktop and delete the project folder (the one containing health_monitor.py) by running:
cd ~/Desktop
rm -rf health-monitor
  • This removes health_monitor.py, health_data.json, the reports/ directory, and your virtual environment.
  • Remove the ANTHROPIC_API_KEY environment variable from your current session by running:
unset ANTHROPIC_API_KEY
  • If you added the export ANTHROPIC_API_KEY line to your shell profile (~/.zshrc or ~/.bash_profile), open that file and delete the line as well.
  • Optionally, revoke your API key at console.anthropic.com by navigating to your API keys page and deleting the key you created for this project.

Nice Work!

Nice Work!

You just built a personal health monitoring tool powered by Claude AI. From logging daily check-ins to receiving AI-generated pattern analysis, you now have a practical CLI tool that gets smarter with every entry you add.

You've learned how to:

  • Integrate the Claude API using the official Anthropic Python SDK to send structured health data and receive intelligent responses.
  • Engineer domain-specific system prompts that turn Claude into a specialized wellness pattern analyst with structured output.
  • Build multi-day trend analysis that compares entries across days and surfaces correlations between sleep, mood, energy, and exercise.
  • Generated formatted weekly health reports saved as markdown files with structured sections and a metrics summary table.

Ready to quiz yourself?