02 · Your first session
The loop that everything else in this course is built on: ask, review, approve, test, commit. By the end of this module the blog project exists and has its first checkpoint.
Before you start
- You will be able to
- Get Claude to create and change files in a project you control, read the diffs, test the result in a browser, and save a checkpoint you can return to.
- You need
- A working desktop install from module 1
- Git installed. Check by asking Claude is git installed, and what version? — if not, it will tell you where to get it
- A browser
- Starting state
- The
claude-coursefolder from module 0, containinghello.html. This module createsclaude-course/my-blog, which every later module uses.
Set up the project and a way back
Start a new session — Cmd+N on a Mac, Ctrl+N on Windows, or the new-session control at the top left. Shortcuts drift between releases, so if that does nothing, open the app's own keyboard-shortcuts list; the current set is also in the desktop documentation.
Point the session at your claude-course folder, and check the permission mode is the one that asks before acting. Then:
Create a folder called my-blog inside this project, initialise a git repository in it with main as the branch name, and make an empty first commit so I have a starting point.
You will get permission prompts for the git commands. Read the first few rather than clicking through them: the command text is right there, and it is a fast way to learn what git actually does.
Asking for a checkpoint before there is anything to lose feels like ceremony. It is the opposite: it is the only cheap moment to do it.
Ask for something real
In my-blog, create index.html: a personal blog homepage with a header containing the title "My Adventures" and a nav menu, a short welcome paragraph, and a grid of 3 post previews with placeholder titles and excerpts. Plain HTML and CSS, no frameworks. Put the CSS in styles/main.css and link it. Ask me at most 3 questions if anything is genuinely ambiguous.
Notice how much of that is decisions rather than description. Plain HTML, no frameworks, CSS in its own file — those are choices you are making, and making them explicitly is most of the difference between a useful result and a surprising one.
Claude may ask a couple of multiple-choice questions. They will not be the same questions every time, so do not expect to match anything you have seen in a screenshot. If an option list does not contain what you want, there is always a free-text choice, and asking what the options mean is a perfectly good use of it.
The approval prompts
As Claude works, files appear in preview and permission prompts interrupt the flow. Broadly you get three answers, and they do not all last the same length of time:
| Answer | Meaning | How long it lasts |
|---|---|---|
| Deny | No. Claude finds another way, or stops and asks. | This once |
| Allow once | Yes, this one action. | This once |
| Don't ask again | Yes, and stop asking about this. | Depends what you approved. A file edit: the rest of this session. A shell command or a web domain: written to .claude/settings.local.json in this repository, so it holds for future sessions too. |
That last column is the one to internalise now, because "don't ask again" is not always the small, temporary convenience it sounds like. Module 7 shows you exactly where those saved decisions land and how to read them back. Until then, prefer Allow once for anything that writes, and save the standing approvals for things like creating a directory.
The exact wording and number of buttons depends on the release and on the rules already in effect. Treat the prompts in this course as illustrations of the kinds of answer available, not as a script of what your screen will say.
Look at what you got
Open my-blog/index.html in a browser — right-click it in the file list and choose Open in browser, or find it in Finder or File Explorer and double-click it.
A working homepage from one instruction, and almost certainly some things you now want to change. That is the point of looking rather than reading.
Changing what you built
Now ask for something you could not have specified up front, because you had not seen the thing yet.
Warm the background up to a cream tint, and give the post cards a soft shadow that lifts slightly on hover. Show me the diff before applying it.
Reading a diff
Claude now shows you a change rather than a file, which is the format you will be reading for the rest of your time with this tool:
- Red lines are being removed.
- Green lines are being added.
- Grey lines are unchanged, and are only there so you can see where in the file you are.
Two questions are worth asking of every diff: is it touching only the file I expected, and is it bigger than the request. A three-line request that produces a sixty-line diff is not necessarily wrong, but it is always worth a sentence of explanation before you accept it.
If a diff does not make sense to you, ask. Explain what this change does and why is a normal thing to say, and the answer will refer to the actual lines in your actual file.
There is a mode that applies edits without asking. It is genuinely useful — for a mechanical change you have already agreed to, stopping at every file is pure friction. It is not a way to skip review; it moves the review from before each edit to after the batch. If you turn it on, the diff still gets read, just later. Module 4 covers where it belongs in the cycle.
Test it, then commit it
Refresh the browser and check the change actually happened. Then:
Commit everything in my-blog with a message describing what changed, then tag this commit module-02.
The tag is a named checkpoint. Every module in this course ends with one, so any later exercise can tell you exactly where to start from — and so you can always get back:
Show me the difference between my working files and the tag module-02, then put the project back to that tag. Tell me what would be lost before you do it.
At the end of every module from here to the end of the course: commit, then tag the commit module-NN, using that module's number. You have just made module-02. Module 3 ends with module-03, and so on. It takes five seconds and three later modules stop working without it.
- Every module's Starting state names a tag. That is how an exercise can tell you exactly where to begin, and how you get back if a module goes badly.
- Module 9 builds a skill that reads the commits since your last tag. With no tags, it reads nothing and writes a confident summary of nothing.
- Module 12 has you find which change broke something by comparing against a tag.
If you skip a module, tag anyway at the point you stop. A missing tag is not an error you will see straight away — it is one that surfaces four modules later, which is the worst kind.
Asking instead of instructing
Not every message has to be a job.
Explain how the CSS in styles/main.css works. Assume I have not written CSS before.
Claude reads the file and explains it against your own code rather than in the abstract. Building something and then asking how it works is a faster way to learn a language than reading about it first.
Sessions
Everything you have said so far is in one session. Within it, Claude remembers earlier instructions and the thread of what you were doing stays intact. A new session is a clean slate: the previous context is gone and you choose a directory again.
That is not a limitation to work around; it is a control. Module 13 is about using it deliberately.
Writing instructions that work
| Instead of | Say |
|---|---|
| Make a website | Create index.html: a blog homepage with a header, a welcome paragraph and three post previews. Plain HTML and CSS. |
| Add a button | Add a header with the title "My Adventures" and warm the background to a cream tint. |
| Fix the bug | The hover shadow stopped appearing after the last change. Explain why, then fix it. |
And go one step at a time. Small change, look at the result, next change. Claude picks up your corrections within a session, so the third request already reflects what you pushed back on in the first.
One caveat worth stating plainly: phrasing helps a lot, and it is not the only variable. A request can be perfectly worded and still go wrong because a file was not where Claude expected, a tool was missing, or the task was ambiguous in a way neither of you noticed. When something fails, "I must have phrased it badly" is one hypothesis, not the explanation.
Where you are now
A project with a git history, a page you can open, one reviewed change, and a checkpoint. Module 3 turns it into a small site.
You have finished when
my-blog/index.htmlexists and opens in a browser showing a heading and three post cards- You changed the page a second time and read the diff before accepting it
git logshows at least two commits, and the tagmodule-02points at the last one- You can say what your permission mode is set to and what it does
If it goes wrong
| What you see | What to do |
|---|---|
| Claude edits a file you did not expect | Reject the change and say which file you meant. Then check the folder shown in the session — a session opened one level up will happily create files beside your project instead of inside it. |
| The browser shows a blank page | Check you opened my-blog/index.html and not the folder. If the file is right and the page is still blank, ask Claude: this page renders blank in the browser. Find out why before changing anything. |
| Git commands are refused | The prompt for a git command is normal the first time. If you denied it, ask again — and read module 7, which is about deciding these once instead of every time. |
On your own
Ask for one more visible change — a footer with the current year, say — but this time predict the diff before you look at it: which file, roughly how many lines, added or changed. Then compare. Being wrong is useful information about how well you understood the request you just made.
Before you start
- You will be able to
- Get Claude to create and change files in a project you control, read the diffs, test the result in a browser, and save a checkpoint you can return to.
- You need
- A working CLI install from module 1
- Git installed:
git --versionshould print a number - A browser
- Starting state
- The
claude-coursefolder from module 0, containinghello.html. This module createsclaude-course/my-blog, which every later module uses.
Set up the project and a way back
All of this is in your shell, before any session starts:
$ cd ~/Documents/claude-course $ mkdir my-blog && cd my-blog $ git init -b main $ git commit --allow-empty -m "Start of the project"
git init -b main names the branch explicitly. Do not assume it: what a fresh repository calls its first branch depends on your git version and configuration, and module 6 has you switching branches by name. If your git is too old for -b, use git init followed by git branch -M main.
The empty commit gives you a point to return to before anything exists. It costs nothing and it is the only cheap moment to make it.
If git complains that it does not know who you are, set that once per machine:
$ git config --global user.name "Your Name" $ git config --global user.email "you@example.com"
Open a session
$ pwd # should end in claude-course/my-blog $ claude
From here the blocks marked inside the session use >. Everything marked your shell uses $ and only works after you have left the session with /exit. Getting these two mixed up is the most common stumble on this track, which is why they look different on this site.
Ask for something real
> Create index.html: a personal blog homepage with a header containing the title "My Adventures" and a nav menu, a short welcome paragraph, and a grid of 3 post previews with placeholder titles and excerpts. Plain HTML and CSS, no frameworks. Put the CSS in styles/main.css and link it.
Notice how much of that is decisions rather than description. Plain HTML, no frameworks, CSS in its own file — stating those explicitly is most of the difference between a useful result and a surprising one.
Claude prints what it intends to write and waits for you to approve it. The exact wording of that prompt depends on the release and on any rules already in effect; what is constant is that nothing lands on disk until you say so.
[File: index.html] <!DOCTYPE html> <html lang="en"> ... </html> Create this file? (y/n)
Look at what you got
Leave the session for a moment — or better, use a second terminal window so you do not lose your place:
$ ls -R $ open index.html # macOS $ start index.html # Windows, Git Bash $ xdg-open index.html # Linux
Changing it, and reading the diff
> Warm the background up to a cream tint, and give the post cards a soft shadow that lifts slightly on hover.
--- styles/main.css
+++ styles/main.css
@@ -8,7 +8,8 @@
body {
font-family: Arial, sans-serif;
- background-color: #f5f5f5;
+ background-color: #f5f0e8;
}
+ .card:hover {
Apply these changes? (y/n)
How to read it
-at the start of a line: that line goes away.+at the start of a line: that line arrives.@@ -8,7 +8,8 @@: line numbers. Ignore them until the day you need them.
Two questions for every diff: is it touching only the file you expected, and is it bigger than the request. A three-line request that produces a sixty-line diff is not necessarily wrong, but it always deserves a sentence of explanation first.
Saying no costs nothing
> Make the background hot pink.
Answer n and the file is untouched. There is no half-applied state to clean up, which is what makes it reasonable to try things.
Test it, then commit it
Refresh the browser first — approving a diff proves the change was written, not that it works. Then leave the session and commit:
> /exit
$ git status $ git add . $ git commit -m "Add blog homepage with cream background and card hover" $ git tag module-02
The tag is a named checkpoint. Every module in this course ends with one, so a later exercise can say exactly where to start — and so you can always get back:
$ git status # check what you would lose first $ git stash # keep it, if there is anything $ git checkout module-02
At the end of every module from here to the end of the course: commit, then tag the commit module-NN, using that module's number. You have just made module-02. Module 3 ends with module-03, and so on. It takes five seconds and three later modules stop working without it.
- Every module's Starting state names a tag. That is how an exercise can tell you exactly where to begin, and how you get back if a module goes badly.
- Module 9 builds a skill that reads the commits since your last tag. With no tags, it reads nothing and writes a confident summary of nothing.
- Module 12 has you find which change broke something by comparing against a tag.
If you skip a module, tag anyway at the point you stop. A missing tag is not an error you will see straight away — it is one that surfaces four modules later, which is the worst kind.
$ git add . && git commit -m "what changed" $ git tag module-02 # the number of the module you just finished $ git tag # confirm it is there
Composing with the rest of your tools
Claude Code is a normal command-line program, but only in one-shot mode. Use -p whenever the output is going into a pipe, a file, or another program — without it you are opening an interactive session with a pipe attached, and it will not behave the way you expect.
$ claude -p "Explain how this page is structured" > notes.md $ git diff | claude -p "Review these uncommitted changes"
Two things to know about -p runs. There is nobody there to answer a permission prompt, so anything not already permitted fails rather than pausing — module 7 is about pre-deciding that. And a -p run is its own conversation: it does not inherit the session you had open.
Continuing a conversation
$ claude -c # continue the last session here $ claude --resume # pick from a list
A new terminal window in the same directory is not automatically the same conversation. -c is what makes it one.
Small things that add up
- Up arrow in your shell recalls the last command; inside a session it recalls your last message.
- Two terminal windows — one holding a session, one for git — save more time than any alias.
- An alias for the commit dance:
alias gc="git add . && git commit -m"in your~/.zshrcor~/.bashrc.
Where you are now
A project with a git history, a page you can open, one reviewed change, a tagged checkpoint, and a clear sense of when you are talking to Claude and when you are talking to your shell. Module 3 turns this into a small site.
You have finished when
my-blog/index.htmlexists and opens in a browser showing a heading and three post cards- You changed the page a second time and read the diff before accepting it
git logshows at least two commits, and the tagmodule-02points at the last one- You can say what your permission mode is set to and what it does
If it goes wrong
| What you see | What to do |
|---|---|
You type git status and Claude answers instead of your shell | You are still inside the session. Leave it with /exit, or open a second terminal window and use that for git. |
| The browser shows a blank page | Check the path you opened. Then, inside a session: this page renders blank in the browser. Find out why before changing anything. |
git commit refuses with a message about identity | Git needs a name and an email once per machine: git config --global user.name "Your Name" and git config --global user.email "you@example.com". |
On your own
Ask for one more visible change — a footer with the current year, say — but this time predict the diff before you look at it: which file, roughly how many lines, added or changed. Then compare. Being wrong is useful information about how well you understood the request you just made.
Kept in this browser only. Nothing is sent anywhere.