Build a Live Code Monitor with AI

Watch your project files and get AI coaching streamed to your terminal on every save.

Introduction

30 Second Summary

You're in the middle of building something and you get stuck. You know the code isn't quite right, but you're not sure what to fix or what to build next.

In this project, you will build a terminal-based coding coach that watches your project files in real-time. Every time you save a file, it streams back an AI review with bugs spotted, improvements suggested, and a clear "here's what to do next" action plan.

What You'll Build

You save a file in VS Code, glance at your terminal, and see an LLM-powered review streaming in token by token, referencing your project goals by name and telling you exactly which file to edit next.

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

  • A live file monitor that detects every save in your project and streams an AI code review straight to your terminal.
  • A project-aware coaching system that reads your goals file and file structure to give specific, actionable "what to do next" guidance.
  • A reusable developer tool that works on any project in any language: Python, JavaScript, Go, Rust, HTML, whatever you're building.
  • Secret Mission: Add conversation memory so the coach builds on previous feedback instead of repeating itself.

Are there any prerequisites?

You should be comfortable with Python basics (functions, classes, and file I/O) and know how to use a terminal. You'll also need Python and VS Code installed on your machine.

No AI experience is needed. This project uses Groq's free tier, so there are no costs and no credit card required.

Before We Start

Before We Start...

Before we dive in, let's lock in what you're about to build and why it matters.

Set Up Your Project

Your live code monitor needs three ingredients to work: a connection to an AI model, a way to detect file changes, and secure storage for your API key.

In this step, you'll create a free Groq account to access an LLM, install the Python packages that power everything, and confirm your environment is ready to go.

In this step, get ready to:
  • Create a Groq account and generate your API key.
  • Set up the project folder and install dependencies.
  • Verify all packages load correctly.
Create a Groq account and get your API key

Groq provides a free API that lets you send code to a large language model and stream back its response. No credit card is required.

  • Open your browser and go to console.groq.com.
  • Click Sign Up and create an account using your email or Google login.
  • After signing in, navigate to API Keys in the left sidebar (or go directly to console.groq.com/keys).
  • Click Create API Key.
  • Give it a name like code-monitor and confirm.
  • Copy the key immediately and paste it somewhere safe (a notes app or text file). The key is shown only once.

Keep the key handy

You will paste this key into a file in the next substep. If you lose it, you can always delete the old key and create a new one from the same page.

Seeing a permissions error?

If you see a message about needing a developer role, try signing out and signing back in. New accounts sometimes need a moment to provision permissions.

help me fix a Groq API key permissions error

Set up the project folder and install dependencies

You need a dedicated folder for your monitor and three Python packages: the Groq SDK, watchdog for file system events, and python-dotenv for loading your key from a file.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Visual Studio Code and press Enter to open it.
  • Open the integrated terminal by pressing Ctrl+` (both macOS and Windows).
  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir code-monitor
cd code-monitor
  • Install the three packages your project needs by running:
pip install groq==1.6.0 watchdog==6.0.0 python-dotenv==1.2.2

You should see output ending with Successfully installed followed by the package names and versions.

Seeing 'pip: command not found'?

Try pip3 instead of pip. Some systems use pip3 for Python 3 packages.

help me fix pip not found when installing Python packages

Now you need to store your Groq API key in a file that your code can read without hardcoding the secret.

  • In VS Code, click File in the top menu bar.
  • Click Open Folder.
  • Navigate to your Desktop, select the code-monitor folder, and click Open.
  • If VS Code asks whether you trust the authors, click Yes, I trust the authors.
  • Create a new file by clicking the new file icon in the Explorer sidebar (or press Cmd+N on macOS, Ctrl+N on Windows).
  • Name the file .env and paste the following content, replacing your-api-key-here with the actual key you copied from Groq:
GROQ_API_KEY=your-api-key-here

Why a .env file?

The .env file keeps your API key out of your code. The python-dotenv library reads this file at runtime so your script can use the key without it ever appearing in your source code.

  • Save .env by pressing Cmd+S (macOS) or Ctrl+S (Windows).
Verify the setup works

Time to confirm everything is wired up. You will create a small test file that imports all three packages and prints a success message.

  • Create a new file in VS Code called monitor.py and paste the following code:
# Basic import test
from groq import Groq
from watchdog.observers import Observer
from dotenv import load_dotenv
print('Ready!')

What does this code do?

Each line imports one of the packages you just installed. If any import fails, Python raises an error immediately. The print('Ready!') at the end only runs if all three imports succeed.

  • Save monitor.py.

Before you run this, what do you expect to see if everything installed correctly?

  • Open the terminal in VS Code (Ctrl+`) and run:
python monitor.py

You should see a single word printed in your terminal:

Ready!

Not seeing 'Ready!'?

If you see ModuleNotFoundError, the package that failed to import was not installed. Re-run the pip install command from above and check for error messages in its output.

If you see python: command not found, try python3 monitor.py instead.

help me debug why my Python imports are failing

✔️ Awesome, I've got everything!

Great. Double check you have saved both .env and monitor.py.

ⓧ I'd like to double check the full code

Here is what each file should contain at this point.

.env

GROQ_API_KEY=your-api-key-here

monitor.py

# Basic import test
from groq import Groq
from watchdog.observers import Observer
from dotenv import load_dotenv
print('Ready!')

Your environment is locked in. You have Groq access, all three packages installed, and a working test script. Next up, you will send actual code to the AI and watch a streaming review appear in your terminal.

Stream a Live Code Review

Your packages are installed and your API key is stored. Now for the exciting part: talking to the LLM.

Before building any automation, you need to confirm the core interaction works. Can you send code to Groq and see a review stream back token-by-token in real-time? This is the building block every future feature relies on.

In this step, get ready to:
  • Build a streaming review function that sends code to Groq and prints the response token-by-token.
  • Wire up a CLI entry point so you can review any file from the terminal.
Build the basic review function

The review function needs three things: a connection to Groq, instructions telling the AI how to behave, and logic to stream the response. You will build these from top to bottom in monitor.py.

  • In VS Code, open monitor.py and delete everything in the file.
  • Replace the contents with the following imports, client setup, and system prompt:
import os
import sys
import time
from pathlib import Path

from dotenv import load_dotenv
from groq import Groq
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

# Load environment variables from .env
load_dotenv()

# Create the Groq client (reads GROQ_API_KEY automatically)
client = Groq()

# Instructions that shape how the AI reviews your code
SYSTEM_PROMPT = """You are a coding coach and pair programmer. You review code changes and help the developer complete their project.

When a file is saved, you will receive:
1. The project's goals (from PROJECT_GOALS.md)
2. The project's file structure
3. The file that was just modified

Your job is to:
- Review the code for bugs, improvements, and best practices
- Tell the developer what to do NEXT to move the project forward
- Be specific: name exact files, functions, and steps
- Keep responses concise and actionable (bullet points preferred)
- If the code has errors, point them out first before suggesting next steps

Be direct. No fluff. Act like a senior developer pair programming with them."""

What does this code do?

  • load_dotenv() reads your .env file and loads GROQ_API_KEY into your environment so the Groq SDK can find it.
  • client = Groq() creates your connection to Groq's API. It picks up the API key from the environment automatically.
  • SYSTEM_PROMPT is the personality you give the AI. It tells the model to act as a coding coach that reviews code, finds bugs, and suggests next steps.
  • Save monitor.py.
  • Confirm the imports and client load correctly by running this command in your terminal:
python monitor.py

You should see no output and no errors. The script loaded your API key and defined the system prompt, then exited.

Seeing a ModuleNotFoundError?

  • Make sure you ran pip install groq==1.6.0 watchdog==6.0.0 python-dotenv==1.2.2 in the same terminal session.
  • If you are using a virtual environment, confirm it is activated before running the script.

Still stuck? Help me fix a ModuleNotFoundError when running monitor.py

Now add the function that actually sends code to the AI. This first half reads the file, builds the prompt message, and prints a header banner.

  • Add the following code below SYSTEM_PROMPT in monitor.py:
def review_file(filepath):
    """Send the changed file to Groq for review."""
    try:
        content = Path(filepath).read_text(encoding="utf-8")
    except (UnicodeDecodeError, PermissionError):
        return

    # Skip files that are too large for a single review
    if len(content) > 10000:
        print(f"\n[Skipping {filepath} - file too large for review]")
        return

    # Build the prompt with the file contents
    user_message = f"""## File Just Saved: {filepath}
```
{content}
```

Review this file and tell me: what's good, what needs fixing, and what should I do next?"""

    # Print a visual separator so each review stands out
    print(f"\n{'='*60}")
    print(f"  Reviewing: {filepath}")
    print(f"{'='*60}\n")

What does this code do?

  • Path(filepath).read_text() reads the saved file into a string. The try/except skips binary files or files you cannot access.
  • The 10,000 character check prevents sending enormous files that would eat through your token budget.
  • user_message wraps the file contents in markdown formatting so the AI can clearly see the code boundaries.
Wire up the CLI entry point

The function reads and formats code, but it does not call the API yet. You will now add the streaming logic that sends the prompt to Groq and prints each token as it arrives. You will also add a simple entry point so you can call the script from your terminal.

  • Add the following code directly below the review_file function you just wrote (still inside the function body, at the same indentation level as the print statements above):
    # Send the prompt to Groq and stream the response
    try:
        stream = client.chat.completions.create(
            model="openai/gpt-oss-120b",
            messages=[
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": user_message},
            ],
            stream=True,
            temperature=0.3,
            max_tokens=1024,
        )

        # Print each token the moment it arrives
        for chunk in stream:
            delta = chunk.choices[0].delta.content
            if delta:
                print(delta, end="", flush=True)

        print("\n")

    except Exception as e:
        if "429" in str(e):
            print("\n[Rate limited - free tier allows ~1 review per minute. Wait a moment.]\n")
        else:
            print(f"\n[Error: {e}]\n")


if __name__ == "__main__":
    if len(sys.argv) > 1:
        review_file(sys.argv[1])
    else:
        print("Usage: python monitor.py <filepath>")

What does this code do?

  • stream=True tells Groq to send the response in small chunks instead of waiting for the full answer. This is what makes the text appear token-by-token.
  • print(delta, end="", flush=True) prints each chunk immediately without a newline, so the response flows smoothly in your terminal.
  • The 429 check catches rate-limit errors from the free tier and prints a friendly message instead of a stack trace.
  • The if __name__ == "__main__" block accepts a file path argument so you can run python monitor.py <file> from the terminal.
  • Save monitor.py.

Before you run this, what do you think the AI will say when it reviews its own source code?

  • Run the monitor against itself by running this command:
python monitor.py monitor.py

You should see a banner line followed by the AI's review streaming into your terminal token-by-token. It will comment on your code structure, point out potential improvements, and suggest what to build next.

Seeing a rate limit or authentication error?

  • If you see [Rate limited...], wait 60 seconds and try again. The free tier allows roughly one review per minute.
  • If you see AuthenticationError, open .env and confirm your GROQ_API_KEY is pasted correctly with no extra spaces or quotes around the value.
  • If you see Usage: python monitor.py <filepath>, you forgot to pass the filename. Make sure your command is python monitor.py monitor.py (the filename appears twice).

Still stuck? Help me debug my Groq API connection in monitor.py

✔️ Awesome, I've got everything!

Great. Double check you have saved monitor.py and confirmed the streaming review works.

ⓧ I'd like to double check the full code

Here is the complete monitor.py at this point. Compare yours against it:

import os
import sys
import time
from pathlib import Path

from dotenv import load_dotenv
from groq import Groq
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

load_dotenv()

client = Groq()

SYSTEM_PROMPT = """You are a coding coach and pair programmer. You review code changes and help the developer complete their project.

Scroll up and confirm you have the following sections in order:

  • Imports and client setup (the block ending with SYSTEM_PROMPT).
  • The review_file function (file reading, message building, header print, streaming API call, error handling).
  • The if __name__ == "__main__" block at the bottom.

You have a working AI code reviewer that streams feedback live. Next up, you will make it trigger automatically every time you save a file.

Watch Files Automatically

Running python monitor.py monitor.py every time you save a file is tedious. The whole point of a coding coach is that it watches over your shoulder without you asking.

In this step, you will wire up watchdog to detect file saves automatically. The moment you hit Ctrl+S in VS Code, your terminal will light up with a streaming review.

In this step, get ready to:
  • Build a file change handler that filters for code files only.
  • Add debouncing so rapid saves don't spam the API.
  • Start a background watcher that triggers reviews on every save.
Create the file watcher using watchdog

Watchdog works by letting you define a handler class that responds to file system events. You subclass FileSystemEventHandler and override the methods you care about.

  • In monitor.py, find the if __name__ == "__main__": block at the bottom of the file.
  • Delete the entire block (all 5 lines starting from if __name__ down to the print("Usage: ...") line).
  • In its place, add the following CodeChangeHandler class:
class CodeChangeHandler(FileSystemEventHandler):
    """Handles file system events, triggering reviews on save."""

    def __init__(self):
        self.last_trigger = 0
        self.cooldown = 5
        self.watch_extensions = {".py", ".js", ".ts", ".html", ".css", ".java", ".go", ".rs", ".md"}

    def on_modified(self, event):
        if event.is_directory:
            return

        filepath = Path(event.src_path)

        if filepath.suffix not in self.watch_extensions:
            return

        if any(part.startswith(".") for part in filepath.parts):
            return
        if "__pycache__" in str(filepath):
            return

        now = time.time()
        if now - self.last_trigger < self.cooldown:
            return
        self.last_trigger = now

        review_file(str(filepath.relative_to(Path.cwd())))

What does this code do?

  • watch_extensions limits triggers to code files only. Saving a .png or .log won't waste an API call.
  • The hidden-directory and __pycache__ checks filter out noise that VS Code generates behind the scenes.
  • The cooldown check uses time.time() to enforce a 5-second gap between reviews. VS Code often fires multiple save events for a single Ctrl+S, and this prevents spamming the API.

Why debounce with a cooldown?

VS Code may fire multiple on_modified events for a single save (temp file writes, auto-formatting, etc.). Without the cooldown, one Ctrl+S could trigger 2-3 reviews back-to-back.

The Groq free tier allows about 30 requests per minute. A 5-second cooldown keeps you well within those limits during normal coding.

  • Save monitor.py. The handler is ready, but nothing schedules it yet. The next chunk wires it up.
Add the startup loop and clean exit

The handler knows what to do when a file changes. Now you need to start an observer that feeds events into it and keeps the script running until you press Ctrl+C.

  • Directly below the CodeChangeHandler class, add the main() function and the new entry point:
def main():
    print("""
============================================
   CODE MONITOR - Your Coding Coach
============================================
   Watching for file changes...
   Save a file to get instant feedback!
   Press Ctrl+C to stop.
============================================
""")

    handler = CodeChangeHandler()
    observer = Observer()
    observer.schedule(handler, path=".", recursive=True)
    observer.start()

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("\n\nMonitor stopped. Happy coding!")
        observer.stop()
    observer.join()


if __name__ == "__main__":
    main()

What does this code do?

  • The startup banner tells you the monitor is active and how to stop it.
  • observer.schedule(handler, path=".", recursive=True) watches the current directory and all subdirectories for changes.
  • The while True: time.sleep(1) loop keeps the script alive. Without it, the program would exit immediately.
  • The KeyboardInterrupt handler catches Ctrl+C and shuts down the observer cleanly instead of crashing with a traceback.
  • Save monitor.py.

Seeing a syntax error when you save?

  • Make sure you deleted the entire old if __name__ == "__main__": block (all 5 lines). Having two if __name__ blocks won't error, but the old one would run first and ignore the watcher.
  • Check that main() is at the top level (no indentation). It should align with class CodeChangeHandler above it.

Help me fix a syntax error in my monitor.py file watcher

✔️ Awesome, I've got everything!

Great. Double check you have saved monitor.py and that the old sys.argv entry point is gone.

ⓧ I'd like to double check the full code

Your monitor.py should have these sections in order. Scroll up and confirm each one is present:

  • Imports (os, sys, time, Path, load_dotenv, Groq, Observer, FileSystemEventHandler).
  • load_dotenv() and client = Groq().
  • SYSTEM_PROMPT multi-line string (from Step 2).
  • review_file(filepath) function (from Step 2).
  • CodeChangeHandler class with __init__ and on_modified (added this step).
  • main() function with banner, observer, and KeyboardInterrupt (added this step).
  • if __name__ == "__main__": main() at the very end.
Test the auto-trigger

The watcher is built. Time to see it in action.

  • Start the monitor by running:
python monitor.py

You should see the startup banner appear in your terminal:

============================================
   CODE MONITOR - Your Coding Coach
============================================
   Watching for file changes...
   Save a file to get instant feedback!
   Press Ctrl+C to stop.
============================================

The script is now running and waiting for file changes. Before you trigger it, take a guess: do you think the review will be specific to your project, or generic?

  • Open monitor.py in VS Code (it should already be open).
  • Add a blank line anywhere in the file, then save with Ctrl+S (Windows) or Cmd+S (macOS).
  • Switch back to your terminal. Within a few seconds, you should see the AI's review streaming in token-by-token.

The review streams in automatically. You did not run any command. That is the watcher doing its job.

But read the review carefully. The AI gives generic code-quality advice. It does not know what you are building, what other files exist, or what you should do next. It is reviewing one file in a vacuum.

Why is the review generic?

Right now, review_file sends only the single file that changed. The AI has no idea what your project goals are or what other files exist in the directory.

This is the gap you will close in the next step by injecting project context into every review.

  • Press Ctrl+C in your terminal to stop the monitor.

No review appeared after saving?

  • Make sure you saved a file with one of the watched extensions (.py, .js, .ts, etc.). Saving a .env file won't trigger a review.
  • Check that you ran python monitor.py from inside your project folder (the same folder that contains monitor.py).
  • If you see a rate-limit message, wait 60 seconds and save again. The free tier allows about 30 requests per minute.

Help me debug why my file watcher isn't triggering reviews

Your monitor is alive. It detects saves and streams back reviews without you lifting a finger. But the advice is shallow because the AI is reviewing files in isolation. Next up, you will feed it your project goals and file structure so it becomes a real coaching partner.

Add Project Awareness

Your monitor auto-triggers reviews on every save. That is a huge upgrade from running the script manually.

But if you tested it in the last step, you noticed a gap. The AI only sees the single file you just saved. It has no idea what you are trying to build or what other files exist in your project. That makes its advice generic and shallow.

In this step, you will feed the AI two pieces of context: a goals file describing what you want to build, and a live snapshot of your file tree. This transforms generic code reviews into specific coaching that tells you exactly what to do next.

In this step, get ready to:
  • Build two helper functions that gather project context (goals and file structure).
  • Wire the context into every review so the AI sees the full picture.
  • Create a project goals file and see the coaching quality jump.
Build context gathering functions

Your system prompt already tells the AI to expect project goals and a file structure. You set that up in Step 2. Now you need to actually gather and send that context.

  • In monitor.py, find the line that says def review_file(filepath): and add the following function above it:
def get_project_goals():
    """Read PROJECT_GOALS.md if it exists."""
    goals_path = Path("PROJECT_GOALS.md")
    if goals_path.exists():
        return goals_path.read_text(encoding="utf-8")
    return "No PROJECT_GOALS.md found. Create one to help me understand what you're building."

What does this code do?

This function tries to read a file called PROJECT_GOALS.md from the current directory.

If the file exists, it returns the full contents. If it does not exist, it returns a helpful fallback message that the AI will see. The fallback nudges the AI to tell the user to create a goals file.

  • Save monitor.py.
  • Confirm the function works by running this in your terminal:
python -c "from monitor import get_project_goals; print(get_project_goals())"

You should see the fallback message printed: No PROJECT_GOALS.md found. Create one to help me understand what you're building.

Seeing an import error?

Make sure you are running the command from inside your project folder (the one containing monitor.py). If you see ModuleNotFoundError, your terminal is in the wrong directory.

Help me fix my import error when testing get_project_goals.

Now you need a function that maps out the project's file structure. The AI will use this to suggest edits to specific files by name.

  • In monitor.py, add this function directly below get_project_goals() and above def review_file(filepath)::
def get_file_tree(root_path, max_depth=3):
    """Get a simple file tree of the project, excluding common noise."""
    ignore_dirs = {".git", "__pycache__", "node_modules", ".venv", "venv", ".idea", ".vscode"}
    ignore_extensions = {".pyc", ".pyo", ".exe", ".dll", ".so"}

    tree_lines = []
    root = Path(root_path)

    for path in sorted(root.rglob("*")):
        if any(part in ignore_dirs for part in path.parts):
            continue
        if path.suffix in ignore_extensions:
            continue

        relative = path.relative_to(root)
        depth = len(relative.parts)
        if depth > max_depth:
            continue

        indent = "  " * (depth - 1)
        if path.is_dir():
            tree_lines.append(f"{indent}{path.name}/")
        else:
            tree_lines.append(f"{indent}{path.name}")

    return "\n".join(tree_lines[:50])

What does this code do?

  • ignore_dirs and ignore_extensions filter out noisy folders and binary files that would confuse the AI.
  • root.rglob("*") recursively walks every file and folder in the project.
  • max_depth=3 prevents the tree from going too deep into nested folders.
  • tree_lines[:50] caps the output at 50 lines so it does not blow out the AI's token limit.
  • Save monitor.py.
  • Confirm the file tree function works by running:
python -c "from monitor import get_file_tree; print(get_file_tree('.'))"

You should see a small tree listing your project files (monitor.py, .env, etc.) printed in the terminal with indentation.

Seeing an empty output?

If nothing prints, make sure you are running the command from inside your project folder. The "." argument tells the function to scan the current directory.

Help me debug why get_file_tree returns empty output.

Wire context into the review function

Both helper functions work. Now you will update review_file to call them and build a richer message that includes your project goals and file structure alongside the saved file.

  • In monitor.py, scroll to the review_file function.
  • Find this section of code inside it:
    user_message = f"""## File Just Saved: {filepath}
```
{content}
```

Review this file and tell me: what's good, what needs fixing, and what should I do next?"""
  • Replace that entire user_message block with the following code, which adds context calls above it and restructures the message into three sections:
    # Gather project context
    project_goals = get_project_goals()
    file_tree = get_file_tree(".")

    user_message = f"""## Project Goals
{project_goals}

## File Structure
{file_tree}

## File Just Saved: {filepath}
```
{content}
```

Review this file and tell me: what's good, what needs fixing, and what should I do next to move this project forward?"""

What changed here?

The user message now sends three sections to the AI instead of one. It starts with your project goals, then your file tree, then the file content. This gives the AI everything it needs to compare where you are versus where you want to be.

The final question also changed: "what should I do next to move this project forward?" This primes the AI to give forward-looking advice tied to your goals.

  • Also update the docstring of review_file to reflect its new purpose. Find this line:
    """Send the changed file to Groq for review."""
  • Replace it with:
    """Send the changed file to Groq for review with project context."""

Next, you will update main() to print a helpful tip when no goals file exists.

  • In the main() function, find this line:
    handler = CodeChangeHandler()
  • Add the following code directly above that line:
    goals = get_project_goals()
    if "No PROJECT_GOALS.md found" in goals:
        print("[!] Tip: Create a PROJECT_GOALS.md file describing what you're building.")
        print("    This helps me give you better 'what to do next' advice.\n")

What does this code do?

When the monitor starts, it checks whether PROJECT_GOALS.md exists. If it does not, it prints a tip so you know to create one. This is a one-time nudge that disappears once you add the goals file.

  • Save monitor.py.
  • Test the tip by running the monitor:
python monitor.py

You should see the startup banner followed by the tip: [!] Tip: Create a PROJECT_GOALS.md file describing what you're building.

  • Press Ctrl+C to stop the monitor.

Not seeing the tip message?

Make sure you placed the goals = get_project_goals() block above handler = CodeChangeHandler() but below the startup banner print() call in main().

Help me figure out why the PROJECT_GOALS.md tip is not printing.

Test with a real project

The plumbing is done. Now give the AI something to work with by creating a goals file.

  • Create a new file called PROJECT_GOALS.md in your project folder with the following template:
# Project Goals

## What I'm Building
Describe your project here. What is the end result?

## Key Features
- Feature 1
- Feature 2
- Feature 3

## Tech Stack
- Language/framework
- Any libraries

## Current Status
What's done so far and what's left to do.

Make it your own

Replace the placeholder text with a real description of something you want to build. It can be this monitor project itself, a side project, or anything you are working on. The more specific your goals, the better the AI's advice becomes.

  • Save PROJECT_GOALS.md.
  • Start the monitor again:
python monitor.py

This time, the tip message should be gone. The monitor found your goals file.

Before you trigger a review, think about this: what do you expect will be different about the AI's response now that it can see your goals and file tree?

  • Open monitor.py in VS Code, add a blank line anywhere, and save the file.

Watch your terminal. The review now references your project goals, mentions other files in the tree by name, and gives you specific next steps toward completing what you described in PROJECT_GOALS.md.

Why is this so much better?

Before, the AI reviewed a file in isolation. It could only say generic things like "add error handling" or "consider refactoring." Now it knows where you are headed and what other files exist.

It can say things like "Your PROJECT_GOALS.md mentions a database feature, but I do not see a database file yet. Create db.py and start with a connection function." That is the difference between a code linter and a coding coach.

✔️ Awesome, I've got everything!

Great. Double check you have saved both monitor.py and PROJECT_GOALS.md.

ⓧ I'd like to double check the full code

Your monitor.py should now contain these sections in order. Scroll through your file and confirm each one is present:

  • Imports (os, sys, time, Path, load_dotenv, Groq, Observer, FileSystemEventHandler).
  • load_dotenv() and client = Groq() initialization.
  • SYSTEM_PROMPT multi-line string (unchanged from Step 2).
  • get_project_goals() function that reads PROJECT_GOALS.md with a fallback.
  • get_file_tree(root_path, max_depth=3) function that walks the directory and caps at 50 lines.
  • review_file(filepath) function with project_goals and file_tree calls, the three-section user_message, and 429 error handling.
  • CodeChangeHandler class with debouncing and extension filtering (unchanged from Step 3).
  • main() function with the startup banner, the PROJECT_GOALS.md tip check, and the Observer loop.

Your PROJECT_GOALS.md should have headings for What I'm Building, Key Features, Tech Stack, and Current Status.

You now have a coding coach that understands your project. Next up, you will take this tool for a spin on a real project and see just how specific its guidance can be.

Secret mission

Add Conversation Memory

Right now your monitor treats every save as a fresh conversation. The AI repeats itself because it has no idea what it told you 30 seconds ago. Add rolling memory so it builds on previous feedback, acknowledges your progress, and gives genuinely new advice each time.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally and uses Groq's free tier, so there are no ongoing costs. Nothing runs in the background once you close your terminal.

Decide whether to keep your project files for future use or delete them entirely.

Resources you used:

  • Project folder on your Desktop containing monitor.py, .env, and PROJECT_GOALS.md.
  • Python packages installed via pip: groq, watchdog, and python-dotenv.

Keep everything running

No action needed. Choose this if you plan to keep using the code monitor on your projects.

  • Your project folder stays on your Desktop, ready to use anytime.
  • The monitor only runs when you explicitly start it with python monitor.py. It does not run in the background.
  • Your Groq account is free with no credit card on file. There are no charges for leaving it active.
  • To use the monitor on a different project, copy monitor.py and .env into that project's folder and create a new PROJECT_GOALS.md for it.

Pause - I'll come back to this later

There is nothing to pause. The monitor stops the moment you press Ctrl+C or close the terminal window.

  • No background processes remain after you close the terminal.
  • No cloud resources are running. Your Groq account has no recurring charges.
  • When you want to resume, open a terminal in your project folder and run python monitor.py again.

Delete - I don't want to use this again

Remove all project files and uninstall the Python packages to start completely fresh.

  • Delete the project folder by running this command (macOS/Linux):
rm -rf ~/Desktop/code-monitor

On Windows, run:

Remove-Item -Recurse -Force ~\Desktop\code-monitor
  • Uninstall the Python packages by running:
pip uninstall groq watchdog python-dotenv -y
  • Your Groq account is free and has no stored payment information. You can leave it as-is with no impact.

Nice Work!

Nice Work!

You just built a personal AI coding coach that runs in your terminal and reviews your code every time you save. No subscriptions, no IDE plugins, no complex setup.

You've learned how to:

  • Built a live file monitor using watchdog that detects every file save in your project.
  • Connected to Groq's free LLM API and streamed AI responses token-by-token in real-time.
  • Engineered a system prompt that turns a generic LLM into a focused coding coach with project awareness.
  • Secret Mission: Added conversation memory so the coach builds on previous feedback instead of repeating itself.

Ready to quiz yourself?