# AI in practice

One feature from plan to review, with Claude Code, Codex, Copilot or Cursor.

Multimedia & Creative Technology · 3.1 Extra Webdev · Self-study · version 0.2.0 · 2026-10-15

Tags: ai, git, productivity

Slides: <https://slides.mctantwerp.be/en/extra-webdev/10-ai-in-practice>

<!-- slide 2 -->

## After this lesson you can

- Explain what a coding agent does that a chat in the browser does not
- Give an agent instructions with AGENTS.md and a skill
- Have an agent ask questions and write a plan to a file before it writes any code
- Build one step at a time, check every step and undo a bad one with a checkpoint
- Review the work of an agent, and have a second session review it too

> **Explanation:** By the end you have built one small feature in the Study planner, from plan to review, and you have a way of working you can repeat for every next feature. The last chapter shows what changes when your project uses git, which every team project does.

<!-- slide 3 -->

## Agenda

1. Getting ready
2. Planning
3. Step by step
4. Reviewing
5. With git

> **Explanation:** Four chapters with an assignment each, and a short fifth one on git. Do them in order: every chapter builds on the previous one. Done early with the whole feature? Start a second one with a new plan instead of adding steps to the first.

<!-- slide 4 -->

## What an agent does

A language model in a loop. Every turn it picks a tool, looks at the result and picks the next one, until the task is done or it has to ask you something.

- **Read**: Open files and search through your project.
- **Edit**: Write and change code, straight in your files.
- **Run**: Run commands in your terminal, with your permissions.
- **Check**: Read the output and decide whether to try again.

**[Working with AI](https://slides.mctantwerp.be/en/extra-webdev/09-working-with-ai)**: Chapter 1: the loop, the tools and the context window.

> **Explanation:** The difference with ChatGPT in the browser: there you paste code in and copy the answer back. An agent does that itself, in your folder, with your permissions. That is why it asks before it runs a command, and why what it reads matters so much. Chapter 1 of Working with AI explains the loop and the context window in detail.

<!-- slide 5 -->

## The workflow

1. **Planning**: The agent reads your code, asks you questions and writes a plan. You steer until it is right. Not a line of code yet.
2. **Step by step**: One step from the plan, then your check in the browser. Only then the next.
3. **Reviewing**: Every change read in the diff, and a second pair of eyes on the whole.

**[Working with AI](https://slides.mctantwerp.be/en/extra-webdev/09-working-with-ai)**: The reference: permissions, models, MCP, skills and a review exercise.

> **Explanation:** This is the thread of the deck. It is not a new workflow: it is how you would work with a colleague who writes code for you. The difference is that the agent types faster than you read, so you have to set the pace.

<!-- slide 6 -->

**The agent types, you decide.**

Two moments are yours: approving the plan and reading the changes. What sits in between, the agent may type.

> **Explanation:** Hold on to this sentence for the rest of the deck. With every assignment the question comes back: who decided here, you or the agent? If the answer is the agent, and it was about what gets built or what gets kept, slow down.

<!-- slide 7 -->

## The same steps in every tool

|   | Claude Code | Codex | Copilot in VS Code | Cursor |
| --- | --- | --- | --- | --- |
| **Instructions** | `CLAUDE.md` or `AGENTS.md` | `AGENTS.md` | `AGENTS.md` | `AGENTS.md` |
| **Planning** | Shift+Tab to plan mode | `/plan` | The Plan agent | Shift+Tab to Plan |
| **New session** | `/clear` | `/new` | New chat | New chat |
| **Undo** | `/rewind` or Esc twice | A checkpoint, in VS Code | Restore Checkpoint | Restore Checkpoint |
| **Seeing changes** | Every edit as a diff | The diff, in VS Code | The button above the chat | The diff view |

A [checkpoint](https://code.claude.com/docs/en/checkpointing) only restores what the agent edited. What a command did, like `npm install` or moving a file, stays.

> **Explanation:** Use the tool that already works on your laptop. Codex in the terminal has no checkpoints and relies on git for its diff: if you want Codex without git, use it in VS Code, then you get the checkpoints and the diff of VS Code. Claude Code in the terminal shows every edit as a diff before you allow it, as long as you are not in a mode that approves everything. Button names move with every release, so check the docs behind the book icon when something does not match what you see.

<!-- slide 8 -->

## 1. Getting ready

> **Explanation:** Fifteen minutes, and it pays off for everything that follows. You start from the same project as the examples on the slides, so what you see in this deck matches what you see on your own screen.

<!-- slide 9 -->

### The Study planner

*study-planner/*

```bash
index.html     the page, the form and the list
style.css      the styling
script.js      adding, ticking off, saving tasks
AGENTS.md      the agreements for your agent
TASKS.md       what still has to happen
plans/         the plans, one file per feature
```

- A task has a title, a course and a deadline
- Tick it off when it is done, with a checkbox to show or hide finished tasks
- Everything stays saved in `localStorage`, also after a reload
- No framework, no npm, no server: you open index.html in the browser

> **Explanation:** Plain HTML, CSS and JavaScript, so nothing can get stuck on an install: double-click index.html and it runs. The project is small on purpose. A feature fits in an hour, and the diff of one step fits on your screen. Already have a project of your own? You may use it, but then the examples fit less well.

<!-- slide 10 -->

### The starter

*Prompt*

```md
Build a study planner in this folder in plain HTML, CSS and JavaScript.
No framework, no npm, no build step. I open index.html in the browser.

- A form to add a task: title, course, deadline
- A list of the tasks, earliest deadline on top
- Tick off a task, and a checkbox "Show finished tasks"
- Save the tasks in localStorage under the key study-planner-tasks
```

Add three tasks, tick one off, reload. If everything is still there, the starter is done.

> **Explanation:** The agent may build the starter in one go: it is small, there is nothing to break yet, and it is the starting point, not the feature. The feature of this deck, the course filter, only comes in the next chapter. If localStorage does not work, ask the agent to explain the error in the console (F12).

<!-- slide 11 -->

### An AGENTS.md to start with

*AGENTS.md*

```md
# Study planner (HTML, CSS, JavaScript)

## Working
- No framework, no npm, no build step
- I test by opening index.html in the browser

## Agreements
- Tasks live in localStorage under
  study-planner-tasks. Never change that format
  without asking first.
- Text from the user never goes on the page
  through innerHTML.
- After every step, tell me what to check in the browser.
```

Every agent in the table reads this file when it starts. One file, and everyone in your team picks their own tool.

Keep it short. Cut everything the agent would also get right without it. More on [agents.md](https://agents.md).

**[Working with AI](https://slides.mctantwerp.be/en/extra-webdev/09-working-with-ai)**: Chapter 4: what goes in it, rules per folder, and Laravel Boost.

> **Explanation:** On a new project /init has little to read, so write this file yourself. The test per line: would the agent get it wrong without this line? 'No npm' matters most: an agent likes to reach for a package or a build step, and a checkpoint does not undo such a command. The last line turns every step into a check you can do yourself.

<!-- slide 12 -->

### Skills

*.agents/skills/write-plan/SKILL.md*

```md
---
name: write-plan
description: Writes a plan for a feature in plans/.
  Use this when I ask for a plan.
---

1. First read the code that goes with the feature.
2. Ask your questions before you write anything.
3. Write plans/<feature>.md with Context, Decisions,
   Relevant code, Steps (each with a check in the
   browser), Don't and Open questions.
4. Change no code.
```

A folder with a SKILL.md. The agent first reads only the description, and the rest only when your question fits.

Works in every tool in the table: [agentskills.io](https://agentskills.io).

> **Explanation:** The difference with AGENTS.md: that file is always in the context. Of a skill the agent first reads only the name and the description, the rest only when your question fits. So a skill is the place for ways of working you need now and then, like a plan in your format. SKILL.md is an open standard: Claude Code, Codex, Copilot and Cursor read the same file, only the folder differs per tool, see the next slide. Chapter 5 of Working with AI puts skills next to hooks and subagents.

<!-- slide 13 -->

### Where skills go

|   | Claude Code | Codex | Copilot in VS Code | Cursor |
| --- | --- | --- | --- | --- |
| `.agents/skills/` | No | Yes | Yes | Yes |
| `.claude/skills/` | Yes | No | Yes | Yes |

Put your skills in `.agents/skills/`, the folder of the open standard. Claude Code only reads `.claude/skills/`, so there you make a symlink to the same folder.

```console
$ mkdir -p .claude
$ ln -s ../.agents/skills .claude/skills
```

> **Explanation:** Checked in the docs of every tool on 2026-10-15, and this moves. Codex looks for .agents/skills from the folder where you start up to the root of your project. Copilot also reads .github/skills, Cursor also .cursor/skills. A folder like .ai, or anything else you make up, no tool reads. On Windows you make the symlink with mklink /D .claude\skills ..\.agents\skills, with Developer Mode on or as admin. If that fails, copy the folder, but then you have to keep two copies in sync. Personal skills for all your projects go in ~/.agents/skills and ~/.claude/skills, with the same split.

<!-- slide 14 -->

### Task: Get your project ready

Stuck? The prompt on The starter and the file on An AGENTS.md to start with work in every tool.

1. Make an empty folder study-planner and open it in the agent of your choice
2. Have the starter built with the prompt from The starter
3. Add three tasks, tick one off, reload: is everything still there?
4. Write an AGENTS.md with the agreements
5. Extra: make the skill write-plan in .agents/skills, or run git init and make a first commit
6. Done when the Study planner runs and AGENTS.md is in the folder

> **Explanation:** Check that the starter really runs: does index.html open, do the tasks stay after a reload? Stuck on localStorage? Have the agent explain the error in the console. The skill is optional, but if you make it, you can use it right away in the next chapter.

<!-- slide 15 -->

## 2. Planning

> **Explanation:** Most time lost with an agent is lost by starting to build too early. Reading a plan takes two minutes, undoing six hundred lines takes an hour.

<!-- slide 16 -->

### A prompt to plan

#### How it often goes

```md
make a course
filter
```

#### What works

```md
I want a course filter above the list of tasks.
Don't change anything yet.

Read the code that goes with it and ask me your questions first.
Then write a plan in plans/course-filter.md.
```

> **Explanation:** The good prompt is shorter than you would think. You do not have to write the plan yourself, the agent reads the code and does the groundwork. What you add: change nothing yet, ask questions first, and put the plan in a file. A plan in a file survives a new session, a plan in the conversation does not. Made the skill? Then 'write a plan for a course filter' is enough.

<!-- slide 17 -->

### Questions first

#### The agent asks

- Which courses: a fixed list, or the courses in your tasks?
- A dropdown, or a button per course?
- Should the choice stay after a reload?
- What about the checkbox "Show finished tasks"?

#### You answer

- From the tasks, each course once
- A dropdown above the list
- Yes, in localStorage
- It keeps working, together with the filter

> **Explanation:** This is the most useful part of planning. Every question is a place where the agent would otherwise guess, and you only see that guess again in the diff. Getting no questions? Ask explicitly: what do you not know yet? A second round of questions after your answers is normal.

<!-- slide 18 -->

### How it often goes

The same course filter, built the quick way. Almost every message below has something wrong with it.

**You:** make a course filter

_Reads script.js_

**Agent:** I will move the project to Vite with React, so you can easily add filters and other features later.

_npm create vite@latest . -- --template react_
node_modules, package.json and 14 other files

_Edits index.html, src/App.jsx, src/Filter.jsx, src/storage.js_
+ Tasks saved under tasks instead of study-planner-tasks
+ The checkbox "Show finished tasks" left out
+ Course filter with a fixed list of courses

**Agent:** Done! The filter works. Start the app with npm run dev.

**You:** where are all my tasks?? and opening index.html does nothing any more

**Agent:** You are absolutely right, sorry! I will fix it right away.

**You:** put everything back

**Agent:** I restored the checkpoint. node_modules and package.json stay: they came from a command, not from an edit.

> **Explanation:** Look for what goes wrong in each message: a framework nobody asked for, an npm command no checkpoint undoes, the storage that gets another key so all tasks seem gone, the checkbox that disappears, and an agent that says everything works without ever opening the page. It ends with a folder full of files nobody reads any more.

<!-- slide 19 -->

### What works

The same feature again. Watch the rhythm: the agent reads, asks, and writes every answer into the plan.

**You:** I want a course filter above the list of tasks. Don't change anything yet. Read the code that goes with it and ask me your questions first. Then write a plan in plans/course-filter.md.

_Reads AGENTS.md, index.html, script.js, style.css_

**Agent:** The list is built in render() in script.js, the checkbox for finished tasks already filters there. Before I plan further:
1. Which courses: a fixed list, or the courses in your tasks?
2. Should the choice stay after a reload?
3. What if the saved course has no tasks any more?

_Creates plans/course-filter.md_
+ Context and relevant code
+ Open questions: 3

**You:** The courses from the tasks, each once, alphabetical. And an option All courses on top.

_Updates plans/course-filter.md_
+ Decision: courses from the tasks, alphabetical, with All courses

**You:** Yes, remember it in localStorage, but under a key of its own. If that course has no tasks any more, show everything.

_Updates plans/course-filter.md_
+ Decision: choice under study-planner-course
+ Decision: unknown course, then All courses

**You:** The checkbox for finished tasks has to keep working, together with this filter. And leave the storage of the tasks alone.

_Updates plans/course-filter.md_
+ Step 2: course filter and checkbox together in render()
+ Don't: change study-planner-tasks

**Agent:** The plan is ready: four steps, each with a check in the browser. One open question left: should a course ignore capitals, so Webdev and webdev are one course? I assumed yes.

**You:** Yes. I will read the plan.

> **Explanation:** Context goes in small messages, the way you would tell a colleague. What you forget, the agent hopefully asks. What it does not ask, it guesses. The next slide shows the file this conversation produced.

<!-- slide 20 -->

### The plan

*plans/course-filter.md*

```md
# Plan: course filter in the Study planner

## Context
The list of tasks is built in render() in script.js,
earliest deadline on top. The checkbox "Show finished
tasks" already filters there. The tasks live in
localStorage under study-planner-tasks.

## Decisions (from the conversation)
- The courses come from the tasks, each once,
  alphabetical. All courses sits on top.
- Capitals do not count: Webdev and webdev are one course.
- The choice stays after a reload, in localStorage
  under study-planner-course.
- If the saved course has no tasks any more, we show
  All courses.
- The filter and the checkbox work together.

## Relevant code
- index.html
  The form #new-task, the list #tasks and the
  checkbox #show-finished.
- script.js
  tasks is loaded from localStorage, render() builds
  the list, save() writes the tasks away.
- style.css
  The style of the form, we follow it for the
  dropdown.

## Steps

- [ ] 1. The dropdown
  A <select id="course-filter"> above #tasks, filled with
  All courses and the courses from the tasks. Options
  made with new Option(), not with innerHTML.
  Check: the dropdown shows each course once, alphabetical.

- [ ] 2. Filtering
  In render(): first the checkbox, then the course.
  Check: pick a course, only its tasks stay. Toggle the
  checkbox, the filter still applies.

- [ ] 3. Remembering
  Save the choice under study-planner-course and set it
  back on load. Unknown course: All courses.
  Check: a reload keeps the choice. Tick off the last task
  of a course and hide finished tasks: All courses.

- [ ] 4. Cleaning up
  No errors in the console, the old tasks are still there.

## Don't
- No framework, no npm, no new files.
- Nothing on study-planner-tasks or on save().
- Don't rewrite the checkbox, even if it fits nicer
  in a new function.

## Open questions
- Should the filter also be in the url?
  Assumed: no, localStorage is enough.
```

- Context and decisions: everything that was decided in the conversation
- Relevant code: where it lives, and what already exists to copy
- Steps, each with a check in the browser
- Don't and open questions. Read those first.

Long, and it should be. A new session or a smaller model starts with this file and nothing else.

> **Explanation:** This is what a plan from Claude Code or Codex really looks like: long, with the decisions from the conversation and the code that already exists. Read Don't and Open questions first, that is where you see fastest whether the agent understood you. There are no tests in this project, so every check is something you do in the browser. The copy button on the code block grabs the full text, if you want to use it as a template.

<!-- slide 21 -->

### Is the plan right

- Can someone who did not see the conversation, or a smaller model, start on step 1?
- Does every step have a check you can do in the browser?
- Something unclear? Ask, and have the answer put in the context.
- A step nobody asked for, like a refactor or a package: cut it.

> **Explanation:** The test for every plan: open a new session with a smaller model, give it only the plan, and see whether it can start on step 1 without questions. A classmate works too. Iterating is just talking on: 'split step 2', 'cut step 4', 'put in the context that a task can have no course'. The agent updates the file itself.

<!-- slide 22 -->

### A TASKS.md

*TASKS.md*

```md
# Tasks

## Doing
- [ ] Course filter, see plans/course-filter.md (step 2 of 4)

## To do
- [ ] Sort on course
- [ ] Overdue tasks in red
- [ ] Bug: an empty title gets saved

## Done
- [x] Starter of the Study planner
```

Everything that still has to happen, in one list. A task you start gets a plan, and the list points to it.

*AGENTS.md*

```md
- Read TASKS.md when you start.
- Update it after every step.
```

> **Explanation:** A plan is for one feature, TASKS.md for the whole project. An idea or a bug goes into To do right away, the plan you only write when you start on it. That way nothing gets lost in an old chat, and a new session sees in one file where you are. The line in AGENTS.md means you do not have to repeat that in every prompt: 'do the next task' is enough. Keep the list short, what is done may go after a while.

<!-- slide 23 -->

### Task: Have a plan written

In the Study planner, for the course filter. Stuck? The prompt on A prompt to plan works in every tool.

1. Switch plan mode on, or start your prompt with "Don't change anything yet"
2. Ask for a course filter, and have the agent ask questions first
3. Answer them. New questions? Another round.
4. Have the plan written in plans/course-filter.md, and put the feature in TASKS.md pointing to it
5. Give it to a new session with a smaller model, or to a classmate. Can they start on step 1 without asking you anything?
6. Done when the plan is in the folder and they could start

> **Explanation:** The most common problem: the context section is empty and everything is still in the conversation. A new session without your chat history shows that right away. No plan mode in your tool? 'Don't change anything yet' in the prompt works everywhere, but check whether the agent sticks to it.

<!-- slide 24 -->

## 3. Step by step

> **Explanation:** This is where it goes wrong most in practice: the agent gets the whole plan at once, and you get back a change of six hundred lines nobody reads any more.

<!-- slide 25 -->

**One step, then your check.**

A change of forty lines, you read. A change of six hundred lines, you scroll through.

> **Explanation:** One step at a time also means you undo a bad step with one checkpoint, without losing the good ones.

<!-- slide 26 -->

### Doing one step

Only step 1, what to check, and a stop. Then you read the changes.

**You:** Do step 1 of plans/course-filter.md. Only step 1. Tick off the step, tell me what to check and stop.

_Reads plans/course-filter.md, index.html, script.js_

_Edits index.html and script.js_
+ <select id="course-filter"> above #tasks
+ fillCourses(): All courses and the courses from the tasks, with new Option()

_Updates plans/course-filter.md_
+ [x] 1. The dropdown

**Agent:** Step 1 is done. Check for you: reload index.html. The dropdown shows All courses and each course once, alphabetical. It does not filter yet, that is step 2. I stop here.

**You:** Great. I will read the changes and check it.

> **Explanation:** 'Only step 1' and 'stop' are the most important words: without them an agent happily carries on with step 2 and 3, because the plan is there anyway. The agent cannot see the page, so it tells you what to check. The plan lives in a file, so a new session per step costs nothing, and an empty context window works better than a session that has been running for an hour. With a plan that carries its own context, a faster and cheaper model can do the steps: Haiku or Sonnet instead of Opus, a mini model in Codex.

<!-- slide 27 -->

### After every step

1. **Read the changes**: In the diff of your tool, file by file. A file that was not in the step is your first question.
2. **Do the check**: The check from the plan, in the browser, with the console open.
3. **Not right?**: Back to the checkpoint from before the step, and again with a better prompt.
4. **Right?**: A new session, or /clear, for the next step.

> **Explanation:** A file in the changes you did not expect is your first question. Open the console (F12) with every check: a red error that does not break the page, you otherwise only notice much later. A checkpoint belongs to one session. With git you commit after every good step, that is the last chapter. Without git you can copy the folder after every good step, study-planner-step-1 and so on.

<!-- slide 28 -->

### Connectors

So far the agent only knows your folder. A connector gives it tools in other software, through [MCP](https://modelcontextprotocol.io).

- **A browser**: Open the page, click and read the console.
- **Figma**: Read the design you have to build.
- **Notion or Drive**: The assignment or the notes of the client.
- **GitHub**: Read issues and open pull requests.

The difference with an API: there you write the code that calls an endpoint. With MCP the agent reads what each tool does, and picks one itself.

> **Explanation:** The difference with an API: with an API you read the docs and write the code that calls an endpoint. With MCP the model reads the description of each tool and picks itself when to call one. An MCP server is often a thin layer around an API that already exists. For the Study planner the browser is the most useful one: the agent then opens the page itself and reads the console. Two caveats: every connector costs context, and what the agent reads through a connector can contain instructions that do not come from you. So only install the ones you really use.

<!-- slide 29 -->

### When it goes wrong

#### Don't

- Five times "no, differently" in the same session. Every wrong attempt stays in the context.
- Letting the agent search until it works, whatever it takes
- Carrying on in a session that starts forgetting the plan

#### Do

- Back to the checkpoint, and again with a better prompt
- Making the step in the plan smaller
- A new session that reads the plan again

> **Explanation:** The most important point: after steering twice, a fresh start with a better prompt is nearly always faster than a third attempt. A checkpoint restores the files the agent edited. What a command created, like node_modules, you delete yourself.

<!-- slide 30 -->

### What do you do now

Pick what you would do in each situation, then read why.

**1. Step 2 of your plan. The agent reports it is done, and also changed style.css and save().**

- Keep it, it works
- **Back to the checkpoint, and make the step sharper** ✓
- Ask if it can clean it up a bit

save() is in Don't, and style.css does not belong to this step. Restore the checkpoint and say in your prompt which files it may touch. Cleaning up in the same session only makes the change bigger.

**2. Third attempt, the dropdown stays empty. The agent suggests moving the project to React.**

- Let it, React is better
- Switch to another model
- **Stop and look in the console yourself why** ✓

A rewrite is the longest detour to "it works", and an error in the console often tells you in one line what is wrong. Maybe another approach really is needed, but you decide that after reading.

**3. The agent reports: done, everything works. It never opened the page.**

- **Do the check from the plan in the browser yourself** ✓
- Believe it, it read the code
- Start the next step right away

If nobody opened the page, "everything works" is a guess. That is why every step prompt asks what you should check.

**4. You restore a checkpoint, but a node_modules and a package.json are still in your folder.**

- The checkpoint is broken
- **They came from a command: delete them yourself** ✓
- Leave them, they do no harm

A checkpoint only restores what the agent edited. What npm created stays. Delete it, and "no npm" in AGENTS.md prevents it next time.

> **Explanation:** The question behind every situation is the same: who decides here, you or the agent? Read the explanation after every answer, also when you got it right.

<!-- slide 31 -->

### Task: Build step by step

The longest assignment. Stuck on a step? When it goes wrong and What do you do now cover most situations.

1. Step 1 of your plan, with one prompt per step: only this step, tell me what to check, stop
2. Read the changes in the diff and do the check in the browser
3. A new session, or /clear, for the next step
4. A step goes wrong: back to the checkpoint and make the step smaller
5. Done when the filter works and you can explain every step without rereading the chat

> **Explanation:** No step ticked off after twenty minutes means the step is too big. Split it in the plan and start the step again. Done with the whole feature? Start a second one, with a new plan: sorting on course, overdue tasks in red, a counter per course.

<!-- slide 32 -->

## 4. Reviewing

> **Explanation:** So far you read every step on its own. Now you look at the whole, with fresh eyes, and you let a second agent look too. They catch different things.

<!-- slide 33 -->

**It works, but is it right?**

An agent that has to get something working finds the shortest road. Sometimes that is the solution, sometimes a detour you only feel later.

> **Explanation:** The agent is told to get something working, and it finds the shortest road. That is why you do not only look at whether the changes of an agent work, but also at how.

<!-- slide 34 -->

### What you look for

| What | Why it happens |
| --- | --- |
| Files or functions that were not in the plan | The model improves whatever it runs into along the way |
| Another key or another format in `localStorage` | The agent does not see your existing data |
| A framework, a script from a CDN, or npm | A package feels like a solution |
| `innerHTML` with text from the user, a `catch` that swallows everything | It did not work right away, so it went around it |

**[Working with AI](https://slides.mctantwerp.be/en/extra-webdev/09-working-with-ai)**: Chapter 10: the review exercise, with five mistakes in one pull request.

> **Explanation:** The innerHTML line matters most for a web project: a course like <img src=x onerror=alert(1)> runs code as soon as it lands on the page. Working with AI has the same list, plus the review exercise with five mistakes in four files: do it now if you skipped it.

<!-- slide 35 -->

### A second pair of eyes

A new session that did not write the code, told not to change anything.

**You:** Read plans/course-filter.md and the code in this folder. You did not write this code. Report what you would not approve, what goes against the plan, and what happened that is not in the plan. Change nothing yourself.

_Reads plans/course-filter.md, AGENTS.md, index.html, script.js, style.css_

**Reviewer:** Three things:
1. script.js, line 48: the tasks themselves go into the list through innerHTML. A title like <img src=x onerror=alert(1)> runs code. Use textContent.
2. A saved course without tasks gives an empty list, against the decision in the plan.
3. Not in the plan: style.css got a new colour for all buttons.

**You:** I will have 1 and 2 fixed in a new session, as step 5 in the plan. The colour I put back myself.

> **Explanation:** A new session has not seen the reasoning that led to the code, and that makes it stricter than the session that wrote it. Without git there is no diff of everything together, so the reviewer puts the files next to the plan itself. For a project of three files that works fine. 'Change nothing yourself' matters: otherwise the reviewer starts fixing and you have more changes to read. Remark 1 was already in the starter, built before AGENTS.md existed: a reviewer reads everything, not only the last step. It does not replace your review: it does not know what the client asked. What you do with every remark, you decide.

<!-- slide 36 -->

### Task: Review your work

Best after a break, so you read the code instead of remembering it. Stuck? What you look for has the list.

1. Read your plan and all your code again, and try the filter in the browser
2. Find one line you would not approve, and write down why it is there
3. Then have a new session review it with the prompt from A second pair of eyes
4. Compare: what did you find, what did the agent find? A classmate as a third pair of eyes is a bonus.
5. Done when every remark is fixed as a new step in the plan, or deliberately ignored

> **Explanation:** You first, then the agent. If the agent reviews first, you only read its list afterwards and stop looking yourself. Keep a note of what the agent found and you did not, and the other way round: after a few features you know where your blind spots are.

<!-- slide 37 -->

## 5. With git

> **Explanation:** For the Study planner git is optional, for every project with a team it is not. The workflow stays the same. What changes: a commit replaces the checkpoint, and a pull request is the moment someone else looks along. Working with AI has the details.

<!-- slide 38 -->

### A commit per step

```console
$ git switch -c course-filter
$ git diff --stat
 index.html             |  4 ++++
 plans/course-filter.md |  2 +-
 script.js              | 18 ++++++++++++++++++
$ git add -p
$ git commit -m "Dropdown for the course filter"
```

A commit replaces the checkpoint. It survives every session, and `git status` also shows what a command created.

Rather click than type? [GitHub Desktop](https://docs.github.com/en/desktop/making-changes-in-a-branch/committing-and-reviewing-changes-to-your-project-in-github-desktop) leaves a single line out of a commit with one click on its line number.

> **Explanation:** A clean git status before you start, so every change of the agent shows up separately in the diff. A branch per feature gives you a pull request to review later. git add -p shows every piece of the diff separately: y to take it, n to leave it, s to split it further. What you did not read does not go into a commit that way. git restore . puts back the files git already knew, git clean -n shows what a command created.

<!-- slide 39 -->

### Reviewing commits

```console
$ git log --oneline main..HEAD
e7d2b19 textContent for tasks, All courses for an unknown course
c41e9a2 Remember the course filter in localStorage
8b07d13 Filter on course in render()
2f5a6e0 Dropdown for the course filter
a91c3d4 Plan for the course filter
```

*Prompt for a new session*

```md
Review my commits with git diff main...HEAD. You did not write this code.
Report what you would not merge and what is not in plans/course-filter.md.
Change nothing yourself.
```

> **Explanation:** With git the reviewer gets a diff of everything together instead of the whole folder. main...HEAD is everything that happened on your branch since you left main. In Codex, /review does the same, with a choice of base branch. Fix every remark in a commit of its own, then the next reviewer sees what changed after the review.

<!-- slide 40 -->

### A pull request

*Pull request*

```md
## What
Course filter above the list, remembered after a reload.
Works together with "Show finished tasks".

## How it was tested
In the browser: every course, with and without finished tasks, a reload.

## AI
Plan and all steps by the agent, see plans/course-filter.md.
After review: textContent and an unknown course in step 5,
the colour of the buttons put back myself.
```

You push and open the pull request yourself: `git push -u origin course-filter`, then `gh pr create --fill --web`.

> **Explanation:** Push and open the pull request yourself: in Claude Code you put git push as an ask rule in .claude/settings.json, in Codex a push to the network asks for permission by default. Never --force on a branch someone else uses. Leave the Co-Authored-By line that Claude Code and other tools put under a commit: that way git log shows later which code came from an agent. The AI section is the most useful one for a reviewer, it says where to look extra carefully. gh pr create --fill takes the title and the body from your commits, you fill them in afterwards.

<!-- slide 41 -->

### Worktrees

A second working folder of the same repo, on another branch. An agent works in one folder, you or a second agent in the other.

- **Useful**: Two tasks at once that touch different files. A hotfix in between, without stashing your work.
- **Not useful**: Tasks that touch the same files. More agents than diffs you can read.

**[Working with AI](https://slides.mctantwerp.be/en/extra-webdev/09-working-with-ai)**: Chapter 9: worktrees per tool, what they leave behind, and when they are worth it.

> **Explanation:** You will rarely need this at first. The bottleneck is you with the plan and the review, and two agents at once means two diffs to read. Want to try it? claude --worktree in Claude Code, /worktree in Codex, and T3 Code does it per thread. Mind .env, vendor and node_modules and the database: a worktree does not take them along. Chapter 9 of Working with AI works it out per tool.

<!-- slide 42 -->

### After step 3 the agent reports: done, everything works. What do you do first?

- A. Start step 4 in the same session
- B. Read the changes and do the check from the plan
- C. Ask whether it is sure
- D. Commit right away

**Answer:** B. Read the changes and do the check from the plan

A file that did not belong to the step, or another key in localStorage, only shows up in the changes. And whether it works, you only know once someone opened the page. The agent says it is sure, even when it is wrong.

> **Explanation:** Back to the start of the review chapter: it works is the minimum, not proof.

<!-- slide 43 -->

### What does a checkpoint not undo?

- A. A line the agent changed in script.js
- B. A new file the agent wrote itself
- C. What npm install put in your folder
- D. A tick the agent put in the plan

**Answer:** C. What npm install put in your folder

A checkpoint only knows the edits of the agent itself. What a command in the terminal did, like npm install or moving a file, stays after the restore.

> **Explanation:** This is why 'no npm' is in AGENTS.md.

<!-- slide 44 -->

### Why do you put the plan in a file and not only in the conversation?

- A. An agent follows a file more strictly than a prompt
- B. That way it does not count towards the context window
- C. A new session can read it, an old conversation not
- D. Plan mode only works with a file

**Answer:** C. A new session can read it, an old conversation not

With the plan in a file you start every step in a fresh session, with an empty window, and the agent still knows where you are. It does count towards the context as soon as it reads it, and an agent does not follow it more strictly: it is just text that stays around.

> **Explanation:** This is why the plan lives in plans/ and not only in the chat.

## Glossary

- **Agent**: A language model in a loop with tools: it reads files, runs commands, edits code and looks at the result, until the task is done. (slide 4)
- **Checkpoint**: A snapshot your tool takes before the agent changes something. Restoring it undoes the edits of the agent, not what a command in the terminal did. (slide 7)
- **Plan mode**: A mode in which the agent reads your code and asks questions, but changes nothing yet. Shift+Tab in Claude Code and Cursor, /plan in Codex. (slide 16)
- **Skill**: A folder with a SKILL.md: a name, a description and instructions. The agent only loads the instructions when the description fits what you ask. (slide 12)
- **Connector**: A link through MCP between your agent and other software, like a browser, Figma or Notion. The agent gets extra tools it picks itself. (slide 28)
- **MCP**: Model Context Protocol: the agreements an agent uses to discover and call tools of other software. Often a thin layer around an API that already exists. (slide 28)
- **Worktree**: A second working folder of the same repo, on another branch. An agent works in one folder, you or a second agent in the other. (slide 41)
- **TASKS.md**: One list of everything that still has to happen in your project, pointing to the plan of what is in progress. Mention it in AGENTS.md, then the agent reads it every time it starts. (slide 22)
- **Diff**: What changed in a file: the lines that were added and the lines that are gone, side by side. (slide 27)

## Links and sources

### In the deck

- [Claude Code: checkpointing](https://code.claude.com/docs/en/checkpointing) (slide 7): What /rewind undoes and what it does not
- [AGENTS.md](https://agents.md) (slide 11)
- [Agent Skills](https://agentskills.io) (slide 12): The open standard behind SKILL.md
- [Model Context Protocol](https://modelcontextprotocol.io) (slide 28)
- [GitHub Desktop: committing and reviewing changes](https://docs.github.com/en/desktop/making-changes-in-a-branch/committing-and-reviewing-changes-to-your-project-in-github-desktop) (slide 38): Leaving single lines out of a commit

### Sources

- [Claude Code: best practices](https://www.anthropic.com/engineering/claude-code-best-practices): Explore, plan, code
- [Claude Code: permission modes](https://code.claude.com/docs/en/permission-modes): Plan mode and Shift+Tab
- [Codex CLI: slash commands](https://developers.openai.com/codex/cli/slash-commands): /plan, /review, /new and /init
- [VS Code: checkpoints and editing](https://code.visualstudio.com/docs/copilot/chat/chat-checkpoints): Restore Checkpoint and the diff above the chat
- [Cursor: checkpoints](https://cursor.com/docs/agent/chat/checkpoints)
- [Cursor: Plan Mode](https://cursor.com/docs/agent/planning)
- [GitHub CLI: gh pr create](https://cli.github.com/manual/gh_pr_create)
