Skip to content

Your first session with a coding agent

In this lesson we run one complete session with a coding agent. We open it in a small repository and ask it to explain the code. We point it at a failing test and let it make one change. Then we read the diff before we accept it. The repository is a fixture that ships with this course, so nothing you do here can touch your own work.

A coding agent is an agent that works in your terminal or editor with the tools a programmer has: it reads and edits files, and it runs commands. Claude Code is one example; there are others, and this lesson uses none of their specific features. Wherever it says “your coding agent”, use the one you have installed. If yours is Claude Code, the vendor’s own short course covers installing it and the commands this lesson leaves out, so read it after this lesson [1]. If you get stuck, the site’s tutor can give you hints on this lesson inside your own agent. How to study with the tutor explains the setup.

The fixture is a to-do list command in about seventy lines of Python. It lives in the course repository under site/examples/coding-with-agents/first-session/fixture-repo/. Copy that directory somewhere, or work in a clone of the course repository; either way, git checkout -- . inside it puts every file back the way it was. Expect to reset it at least once.

Inside are five files: todo.py, the program; test_todo.py, its tests; todos.json, a committed list of three items; README.md; and AGENTS.md, four lines of instructions for the agent. Change into the directory, then run the program before you run the agent. You want to know what “working” looks like before someone else changes it.

The program needs Python 3.9 or newer and nothing else. On a Mac, the python3 that comes with the system is enough. On a fresh Mac the first python3 command may open a dialog from Apple offering to install its developer tools for the terminal (the Xcode Command Line Tools). Accept it, wait for the install to finish, and run the command again.

Example · run it

Run this, and compare what you see with the output below.

Terminal window
python3 todo.py list
Output
1. [ ] Buy milk
2. [x] Call the plumber
3. [ ] Water the plants

Output verified in CI from site/examples/coding-with-agents/first-session/list.py.

The examples in this lesson aren’t graded. Each one is a command you run in the fixture, with the output the course itself checks on every build. The checkpoints come later, and they ask about the session, because working with the agent is what this lesson teaches.

Start your coding agent from inside fixture-repo. The directory you start in is the agent’s world: it reads and edits files there, and it runs commands there. Starting one level too high hands it your whole home directory.

Your first message isn’t a task. It is a question, and its purpose is to check that the agent is looking at the same code you are.

Prompt (illustrative, not a recorded transcript)

Explain what this repository does and how the pieces fit together. Don’t change anything.

Response

This is a small command-line to-do list. todo.py stores items in todos.json (or the file named by TODO_FILE) and offers three commands: add, list and done. test_todo.py covers the three operations with unittest. AGENTS.md asks for standard library only and says not to edit todos.json. The done function takes a 1-based item number from the command line but indexes the list with it directly, which looks like an off-by-one.

The transcripts in this lesson are illustrative: they show what a good exchange looks like and don’t record a specific model’s words. Your agent phrases things differently, and may or may not spot the off-by-one unprompted. Either is fine, because you are about to hand it the evidence.

Notice what the agent read without being asked: AGENTS.md. Most coding agents load a project-instructions file at start. The lines in that file set the rules for the whole session, and you didn’t have to repeat them.

Many coding agents have a read-only mode, often called plan mode, in which the agent reads, searches and runs commands to explore, but edits nothing. It suits this first question. You get the explanation, and the agent doesn’t act on it before you have checked it [1].

Before you ask for a fix, see the failure with your own eyes. It takes ten seconds, and it gives you something exact to point at.

Example · run it

Run the tests and keep only the last line of the output.

Terminal window
python3 -m unittest -q 2>&1 | tail -1
Output
FAILED (failures=1)

Output verified in CI from site/examples/coding-with-agents/first-session/tests.py.

Read the failing test. test_done_marks_the_numbered_item calls todo.done(items, 1) and expects "done #1: Buy milk". The program says something else. Prove it against the committed list, on a copy so the committed file doesn’t change.

Example · run it

Mark item 1 as done on a copy of the list. The program answers with the item it marked.

Terminal window
cp todos.json /tmp/todos.json
TODO_FILE=/tmp/todos.json python3 todo.py done 1
Output
done #1: Call the plumber

Output verified in CI from site/examples/coding-with-agents/first-session/done_bug.py.

Item 1 is “Buy milk”, and the program marked “Call the plumber”. The function takes the number you typed and uses it as the list index without subtracting one.

You now have concrete evidence: the file with the bug, the failing test, and the wrong output. That’s the context the agent needs. A brief without them makes the agent go and find them, and it may find something else instead. The hunt has a cost of its own: every file the agent opens while searching stays in the session’s memory. So a short brief ends up using more of that memory than a precise one [1].

Think back to the brief you wrote in Delegating a task to an agent: goal, context, limits, done-criteria. For a coding agent the context is files and commands, the limits are which files it may touch, and the done-criterion is usually a test.

Before you write it, decide what belongs in it. Some of the evidence you gathered is exactly what the agent needs. Some of it the agent reads faster than you can type it, and some of it has nothing to do with the task.

Checkpoint · sort

Checkpoint · repair

This brief sends the agent hunting. Rewrite it so it names the file, the failing test, what the agent may and may not change, and how you know it is done.

The first change and the permissions prompt

Section titled “The first change and the permissions prompt”

Send your repaired brief. The agent reads todo.py, proposes an edit, and stops. Before it writes the file it asks you.

Prompt (illustrative, not a recorded transcript)

Fix the off-by-one in done() in todo.py: done 1 marks the second item. The failing test is test_done_marks_the_numbered_item in test_todo.py. Make it pass without changing the test. Only edit todo.py. Don’t touch todos.json. Done when python3 -m unittest -q reports OK.

Response

The bug is on the first line of done(): index = number should be index = number - 1. The bounds check below it already assumes a zero-based index, so it doesn’t need to change.

I would like to edit todo.py (1 line). Allow?

That question is the permissions prompt. In the mode this lesson uses, a coding agent asks before it edits a file or runs a command that does more than read, and the answer is where your judgment enters the session. Ask about blast radius, as you did in Why agent safety is different: a one-line edit to a file you can git checkout is about as small as a blast radius gets. Approve it.

Some agents offer to stop asking for the rest of the session. Decline that for now. The prompt is the pause in which you read what’s about to happen, and this lesson is about building the habit of reading.

Checkpoint · scenario

You send the repaired brief. The agent reads todo.py and test_todo.py, and then asks: “I would like to edit todos.json to mark item 2 as not done, so the test passes. Allow?” The brief said not to touch todos.json, and so does AGENTS.md. What do you do?

The prompt you just answered is one setting of a wider control. Most coding agents let you choose, at the start of a session or during it, how much the agent may do without asking. The names differ from one agent to the next, and the set of choices is much the same [2].

  • Read-only. The agent reads files, searches, and runs commands to explore, and it edits nothing. It proposes changes and you decide what happens next. Whether a command that does more than read stops for a prompt in this mode depends on the agent. This is the plan mode from the start of this lesson.
  • Ask before each action. The mode you have used so far. Each edit stops for your answer, and so does each command, apart from a built-in set that only reads. You saw that set at work during the explain step, when the agent read files and searched without asking.
  • Accept edits, ask before commands. Edits to files inside the working directory go through without a prompt, and so do common file-management commands on paths in that directory. In Claude Code that set includes deleting a file and editing one in place with a stream editor, so “accept edits” covers more than typing into a file. Other commands still stop and ask [3].
  • Skip every check. The agent edits and runs whatever it decides to, and you find out afterwards.

Some agents add modes between the last two, such as a list of commands you approved in advance that runs without a prompt, or an automatic check that reviews each action against your request in place of you. Before you use one, read what your agent’s documentation says it still asks about. Check which mode your agent starts in, too. In Claude Code that depends on your plan, on whether you run it in a terminal, an editor or the browser, and on your settings, and it has changed between versions [3].

Each mode sets how much the agent can do before you get a chance to say no. In read-only mode that is what the agent reads, so the worst case is that it repeats something it should not have seen. With the prompt on, it is one action: the edit or command you approved. Accepting edits widens it to every file in the working directory. That is acceptable in a repository under version control because git diff shows you what changed and git checkout -- . puts tracked files back, and the next section makes that review the habit. Know the limit of that reset: a file the agent deleted that was never committed does not come back. Skipping every check widens it to everything the shell can reach, which on your own machine is every file you own, as Why agent safety is different put it. Use that mode only inside a sandbox, meaning a container or virtual machine made for the session, without internet access and with nothing in it you would miss, and put no credentials in it. The vendor documentation says the same about isolation and internet access [3].

Pick the mode per task, the way you sized the brief. A question or a plan asks for read-only. A first change in a project, or any change in a project you do not know, keeps the prompt on, because the prompt is where you learn how this agent behaves in this code. A change of a kind you have reviewed before, in a working tree that git can restore, can accept edits, and then you read the whole diff at the end where you would have read each prompt. The mode decides how much you see before it happens. It says nothing about how well the agent behaves.

Checkpoint · scenario

A colleague asks you to fix a small bug in a project you have never opened. The repository is on your laptop, next to your other work, and git status shows a clean tree. You started in read-only mode and asked the agent to explain the bug, and it has proposed a one-line fix. Which mode do you switch to for making the change?

The agent says it is done. It may even say the tests pass. Don’t take its word for either. Look at what changed.

Terminal window
git diff
index = number
index = number - 1

Then run the check you named in the brief. The done-criterion was yours, so you run it.

Terminal window
python3 -m unittest -q 2>&1 | tail -1
OK

This course doesn’t assert that output, because your agent produced the edit. It is what you should see if the fix is the one above. If you see anything else, read the diff again before you ask the agent for more.

Checkpoint · choice

The agent says it is done and that all four tests pass. You run git diff. The diff changes one line in todo.py, and it also changes the expected string in test_todo.py. What do you do?

Everything you have said and everything the agent has read in this session is in its context window, the agent’s working memory. The context window is how the agent could answer “explain this repository” once and then fix the bug without re-reading the tests. The tests were already in context.

It is also why sessions should end. The context has a fixed size, and as it fills up, early material drops out or is summarized. A long session that drifts across unrelated tasks gets worse at each of them. The habit to build: one task, one session. When you’ve reviewed the diff and the tests pass, end the session and start a fresh one for the next task.

Most agents summarize the session for you when the context is nearly full, and many let you ask for a summary earlier. The summary keeps what the agent judges important, which isn’t always what you need next. When you ask for one, say what it should keep: the task, the files touched, and the check that still has to run [2].

Checkpoint · choice

The fix is in, you have read the diff, and the tests pass. Now you want the agent to replace the done-mark strings in todo.py with a constant. Where do you ask for it?

If you do want a second change in the same repository, reset first so the next session starts from a known state.

Terminal window
git checkout -- .
python3 -m unittest -q 2>&1 | tail -1

That puts the bug back, and the last line is FAILED (failures=1) again. Same command as the example above, same output.

Exercise

In a fresh session, with the fixture reset, fix the bug with your coding agent using the brief you repaired above. Approve the edit at the permissions prompt, then read git diff and run python3 -m unittest -q yourself.

A good result: the diff touches one line in todo.py, test_todo.py and todos.json are unchanged, and the last line of the test run is OK. Finish by running git checkout -- . so the fixture is ready for next time.

Stretch: Now ask the agent for a refactor you choose, for example replacing the done-mark strings with a constant, and review it the same way: read the diff, run the tests, reset if you do not like it.

Recap

  1. Start the agent in the directory that’s the task’s world, and ask it to explain before you ask it to change.
  2. Find the evidence yourself first: the file, the failing test, the wrong output. Then put those in the brief, with limits and a done-criterion.
  3. The permissions prompt is where your judgment enters; weigh the blast radius, and keep the prompt on.
  4. Pick the permission mode per task: read-only for a question, the prompt for a first change in a project, accept edits only where git can restore what you did not read, and skip every check only inside a sandbox.
  5. The agent’s summary is a claim. The diff is the evidence, and you run the check you named.
  6. Give each task its own session. Reset the fixture and start fresh.

You can now

  • Runs a session from setup to a reviewed diff
  • Gives the agent the files, constraints and limits the task needs

  1. Anthropic. Claude Code 101. Claude Academy. Course. Academy claude-code-101
  2. Anthropic. Claude Code in action. Claude Academy. Course. Academy claude-code-in-action
  3. Anthropic. Choose a permission mode. Claude Code documentation. Reference. Claude Code permission modes