Files
ai-workflow-course/modules/04-getting-the-ai-out-of-the-browser/README.md
T
claude 9835dba566 fix(modules-4,7,14): make the git demos/labs actually do what the prose claims
- M4 Part C now commits the reviewed `delete` change as the checkpoint, so
  Part D's `git restore .` returns to a delete-containing state (was wiping it).
- M7 'watch it break': switch to an existing divergent branch so the
  "would be overwritten by checkout" refusal actually fires (git switch -c never did).
- M7 Part C: demonstrate worktree isolation with existing add/list and distinct
  per-worktree data; move the new clear/count commands to after they exist.
- M14 Part C: recover with `git revert HEAD` (Module 12, which precedes M14) so
  CI legitimately goes green; drop the wrong "Module 2's safety net" attribution.

Closes #2
Closes #3
Closes #4
Closes #12

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TfzV5QvtPDz8LJS3Pu5VLT
2026-06-22 14:52:20 -04:00

444 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Module 4 — Getting the AI Out of the Browser
> **The copy-paste loop from Module 1 ends here.** You stop being the integration layer between a
> chat tab and your files — the AI reads the whole repo and edits the files directly, and you review
> what it did as a diff. This is the literal answer to Module 1, and it's safe *only* because of the
> net you built in Module 2.
---
## Prerequisites
- **Module 1** — you have the `tasks-app` project, an editor, and a terminal, and you've felt the
three seams where copy-paste breaks. This module closes seam 1 (more than one file) for good.
- **Module 2** — this is the load-bearing prerequisite. You have a Git repo with commits, and you've
personally watched `git diff` show you a change and `git restore` throw one away. **Do not do this
module without that.** Letting an AI edit your real files directly is only sane because you can see
and revert exactly what it did. The safety net comes first; the trapeze act comes second.
- **Module 3** is helpful but not required — you've already practiced the branch / diff / review /
commit rhythm on low-stakes documents. Here you point that same rhythm at code, with the AI doing
the editing.
---
## Learning objectives
By the end of this module you can:
1. Name the two categories of "AI out of the browser" tooling — editor-integrated assistants and
agentic command-line tools — and choose between them on criteria that don't depend on a vendor.
2. Install, authenticate, and point one of them at a real repository, then confirm it can actually
read the project.
3. Run the agentic edit → review → iterate loop: let the AI change real files, read the change as a
`git diff`, and either keep it or revert it.
4. Set the tool's permissions deliberately — what it may read, edit, and execute without asking.
5. Explain precisely why this is safe, in terms of Module 2's `restore`.
---
## Key concepts
### What "out of the browser" actually means
In the browser-chat loop, the AI is blindfolded and handcuffed. It can't see your files unless you
paste them in, and it can't change them — it can only hand you text to copy back. *You* are the
integration layer: you decide which files it sees, you apply its output, you are the one who notices
it forgot to update the second file. That's seam 1 from Module 1, and no smarter model fixes it,
because it isn't an intelligence problem — it's an *access* problem.
Getting the AI out of the browser means giving it two things it never had in the chat tab:
1. **Read access to the whole project** — it can open any file, search the repo, and see how the
pieces fit, without you pasting anything.
2. **Write access to the files** — it edits `tasks.py` and `cli.py` directly, in place, instead of
printing a new version for you to paste.
Everything in this module follows from those two capabilities. They're also exactly why Module 2 had
to come first: write access to your files is only acceptable when every edit is visible and
reversible.
### The two categories
There are two shapes this tooling comes in. They overlap, and plenty of products do both, but the
distinction is real and worth understanding before you pick.
**Editor-integrated assistants.** These live *inside* a code editor (the graphical kind — VS Code and
its forks, the JetBrains IDEs, and others). They show up as a side panel you chat with, inline
suggestions as you type, and — the part that matters here — an "agent" or "edit" mode that proposes
changes across files, which you accept or reject in the editor's own diff view. The win is that the
review surface is right there: the editor highlights every changed line, and accepting a change is a
click. If you already work in a graphical editor, this is the lowest-friction on-ramp.
**Agentic command-line tools.** These run in your terminal as a standalone program you talk to in
plain language. You launch the tool *inside* your project directory, and it reads files, runs
commands, and edits files on its own, reporting back what it did. They tend to be more autonomous —
better at "go do this multi-step thing" — and they're editor-independent, so they work the same
whether you use a graphical editor, a terminal editor, or none. The review surface is `git diff`
itself (Module 2), which is the same review surface you'll use for everything else in this course.
| | Editor-integrated assistant | Agentic CLI tool |
|---|---|---|
| **Lives in** | Your graphical editor | Your terminal |
| **Review surface** | The editor's diff view (and `git diff`) | `git diff` |
| **Best at** | Tight inline edits, in-editor review | Multi-step, multi-file, autonomous work |
| **Tied to** | A specific editor | Nothing — works anywhere |
| **On-ramp if you…** | Already live in a graphical editor | Live in the terminal, or run agents headless later |
You do not have to choose forever, and you'll likely end up using both. Pick one to learn the loop
with. The rest of this course is written to work with either.
### How to choose (without crowning a winner)
This space moves fast and the "best" tool changes by the quarter, so evaluate on properties, not
brand:
- **Bring-your-own-model vs. locked model.** Some tools let you point at whichever model/provider you
want; some bundle one. The course thesis applies directly — *the model is the swappable part* — so
a tool that lets you swap models is hedging in your favor. (You may still pick a bundled one for
other reasons; just know what you're trading.)
- **Reads a committed, repo-level instructions file.** You'll want this in Module 5. Most serious
tools read a project-level instructions file from the repo root. A tool that supports this lets you
version your AI's configuration like code.
- **Shows diffs before applying, and has an approval mode.** Non-negotiable. You need to see what it
wants to change and control what it's allowed to do without asking (next section).
- **Works with your editor / OS / shell.** Obvious, but check. Agentic CLIs are the most portable.
- **Cost and where your code goes.** Read the tool's data policy. For work code, know whether your
files are used for training and whether a self-hosted or local-model path exists (a real concern
for this audience; it returns in later units).
Don't agonize. Any tool that shows diffs and has an approval mode is good enough to learn the loop.
The loop is the durable skill; the tool is swappable, same as the model.
### Wiring it up: from browser to repo
The exact clicks differ per tool and drift over time, so here is the shape every one of them
follows. Do these four steps and you're connected.
**1. Install it.** Editor-integrated assistants install from your editor's extension/plugin
marketplace — search, install, reload. Agentic CLIs install as a command-line program (commonly via a
package manager like `npm`/`pip`/`brew`, or a download) and then exist as a command you run, e.g.:
```bash
your-agent --version # confirm the tool is on your PATH
```
**2. Authenticate.** On first run the tool will send you through a sign-in — usually a browser-based
login that drops a token back onto your machine, or a paste-in API key from your provider account.
This is a one-time setup; the credential is stored locally for next time. If the tool lets you choose
a model/provider here, this is where the BYO-model choice from above gets made.
**3. Point it at the repo.** This is the step that has no equivalent in the browser, and it's the
whole point. The convention is **the current working directory is the project**:
```bash
cd ~/workflow-course/tasks-app # the repo from Modules 12
your-agent # launch it from inside the project
```
For an editor-integrated assistant, the equivalent is **open the project folder** (`code .` or
File → Open Folder), exactly as you did in Module 1 — the assistant scopes itself to the folder
that's open. Either way, the tool now treats this directory as its world: it can see every file in
it without you pasting a thing.
**4. Confirm it can actually read the project.** Don't assume — verify, the same instinct you'd apply
to any new integration. Ask it a question only something that has read your files could answer:
> *"What does this project do, which files is it split across, and what commands does the CLI
> support?"*
A correct answer names `tasks.py` and `cli.py`, describes the task app, and lists `add` / `list` /
`done` — pulled from the actual files, not guessed. If it asks you to paste code, or describes a
generic to-do app it clearly invented, it is **not** connected to the repo. Stop and fix the wiring
before going further; everything downstream assumes it can read.
A power move you already know from Module 2: ask it to read the *repo's* state, not just the files —
*"run `git log`, `git status`, and `git diff` and tell me where this project is."* An agentic tool
can run those itself. Now its first act is reading the durable memory you've been building, which is
exactly the "where were we?" reconstruction from Module 2, except the AI does the reading.
### Operating it: the edit → review → iterate loop
Connection is half the module. The other half is what you actually *do* once connected, and it
replaces the entire copy-paste loop with this:
1. **Describe the change** in plain language. Not "here's a file, rewrite it" — *"add a command that
deletes a task by its index."* The tool decides which files that touches.
2. **The AI edits the files directly.** It opens what it needs, makes the changes in place, and tells
you what it did. No copying, no pasting, no you-as-integration-layer. This is the moment seam 1
dies: when the change spans `tasks.py` *and* `cli.py`, the tool edits both, because it can see
both.
3. **Review the diff.** This is the load-bearing step, and it's the Module 2 habit, unchanged:
```bash
git diff
```
Read exactly what changed — every line, across every file it touched. An editor-integrated tool
shows you the same thing in its diff view. You are reviewing the AI's work, not trusting it. (The
deep version of this skill — spotting the plausible-but-wrong change — is Module 10. Here, just
build the reflex: *nothing gets committed unread.*)
4. **Iterate or revert.**
- If it's right: run it, then commit (`git add . && git commit -m "…"`). New checkpoint.
- If it's *close*: tell the AI what to fix and loop back to step 2. It already has the context.
- If it's wrong: **`git restore .`** and you're back to your last checkpoint, byte for byte. The
mess is gone. Try a different prompt.
That fourth step is the entire reason this is safe, so let's be explicit about it.
### Why this is safe: the Module 2 hinge
Letting an AI write to your files directly *sounds* reckless, and in Module 1's world — no version
control, no checkpoints — it would be. The thing that makes it safe is not that the AI is careful.
It isn't, reliably. The thing that makes it safe is that **you committed first, so every edit it
makes is a visible, reversible delta from a known-good state.**
Concretely, the safety contract is:
- **Before you let it loose:** your work is committed (`git status` is clean). That's your restore
point.
- **While it works:** every change is on disk, and `git diff` shows you all of it. Nothing is hidden.
- **If it goes wrong:** `git restore .` discards every uncommitted edit it made and you're back at
the checkpoint, with zero retyping. Module 2's "undo for the AI," now pointed at an AI that edits
files itself.
This is the promise Module 2 made cashing out. Module 2 said *every later module asks you to let the
AI do something bolder, and you can say yes because you can always get back to a checkpoint.* This is
the first of those bolder things. The downside of any AI edit is now "throw away a few minutes and
re-prompt" — never "lose work" — and that asymmetry is what lets you move fast.
> **The one rule:** start from a clean commit. If `git status` shows uncommitted work before you turn
> the AI loose, you've blurred the line between *your* work and *its* work — and `git restore .` will
> throw away both. Commit your stuff first. Then the diff is purely the AI's, and restore is purely an
> undo of the AI.
### Permissions: what it may do without asking
Out of the browser, the AI can do more than edit files — an agentic tool can also *run commands*
(tests, linters, the app itself, git). That's powerful and worth controlling. Every serious tool has
an approval model, usually some version of:
- **Read-only / ask-first** — it proposes every edit and command and waits for your yes. Slowest,
safest. Start here while you learn a tool's behavior.
- **Auto-edit, ask-to-run** — it edits files freely (you'll review the diff anyway) but asks before
running commands. A good default once you trust the diff-review habit.
- **Full auto / "just go"** — it edits and runs without asking. Fast, and appropriate only when the
blast radius is contained — a clean commit to restore to, and ideally an isolated branch (Module 6)
or a sandbox (Module 16) for anything you don't fully trust.
The right setting is a function of your safety net, not your nerve. With a clean commit you can
afford a looser setting for edits, because the diff is reversible. Be more conservative about letting
it *run* commands unattended — a deleted file is restorable; a command that hits a real external
system may not be. Match the leash to what you can undo.
---
## The AI angle
This module *is* the AI angle of Unit 1 — it's where the whole "get out of the chat window" premise
pays off. Map it straight back to Module 1's three seams:
- **Seam 1 (more than one file) — solved here.** The tool reads the whole repo, so a change that
spans `tasks.py` and `cli.py` gets made in both. You are no longer the integration layer holding
two files in your head.
- **Seam 2 (more than one day) — solved by Module 2, *used* here.** A fresh agentic session
reconstructs "where were we?" by reading `git log` / `status` / `diff` itself — the durable-memory
reframe from Module 2, now executed by the AI instead of pasted by you.
- **Seam 3 (no undo) — solved by Module 2, *required* here.** Direct file edits would be reckless
without `git restore`. The safety net isn't a nice-to-have for this module; it's the precondition.
The deeper point: notice that *none of this is model-specific.* You didn't get a smarter model. You
gave the same model **access** and wrapped it in **review and revert**. That's the course thesis in
miniature — the leverage came from the workflow around the model, not the model. Swap the model
underneath this loop and the loop is unchanged.
---
## Hands-on lab
**Lab language:** shell + a small Python change *made by the AI, not by you*. You'll drive an agentic
tool; the tool writes the Python.
The goal: wire an agentic editor or CLI tool to the `tasks-app` repo, confirm it can read the
project, and make one **real, reviewed, multi-file** change with it — the exact change that broke the
copy-paste loop back in Module 1, now done right.
**You'll need:**
- The `tasks-app` repo from Modules 12, as a Git repo with at least one commit.
- One AI-out-of-the-browser tool of your choice — either an editor-integrated assistant or an agentic
CLI. Use the "How to choose" criteria above; any tool that shows diffs and has an approval mode is
fine.
- Your model/provider credentials for that tool.
- The verify script in this module's `lab/verify.sh`.
### Part A — Wire it up and confirm it can read
1. Install the tool and authenticate it (steps 12 in "Wiring it up").
2. Point it at the repo (step 3): `cd ~/workflow-course/tasks-app` and launch the agentic CLI from
there, **or** open that folder in your editor and open the assistant's agent panel.
3. **Confirm read access** (step 4). Ask:
> *"What does this project do, which files is it split across, and what commands does the CLI
> support?"*
You're connected only if it names `tasks.py` and `cli.py` and lists `add` / `list` / `done` from
the real files. If it asks you to paste code, fix the wiring before continuing.
### Part B — Start from a clean checkpoint
4. This is the one rule. Make sure your work is committed so the AI's change is the *only* thing in
the next diff:
```bash
git status # must be clean ("nothing to commit, working tree clean")
```
If it isn't clean, commit your current work first (`git add . && git commit -m "…"`). Now you have
a known-good restore point, and anything that appears in `git diff` next is purely the AI's.
### Part C — Make a real multi-file change
5. Ask the tool — in plain language, letting *it* decide which files to touch — for the change that
needs both files:
> *"Add a `delete <index>` command to the task app that removes the task at the given index. Put
> the removal logic in the TaskList class in `tasks.py` and wire the command up in `cli.py`. Match
> the existing code style and update the usage string."*
Let it edit the files directly. Do **not** copy anything by hand — if you find yourself pasting,
the tool isn't actually wired to the repo (back to Part A).
6. **Review the diff before you trust a line of it:**
```bash
git diff
```
Confirm with your own eyes: a new method on `TaskList` in `tasks.py`, a new `delete` branch in
`cli.py`'s command dispatch, the usage string updated — and **nothing touched that shouldn't be.**
This is the review reflex. Two files changed, and you didn't merge them by hand. That's seam 1,
gone.
7. **Verify it runs.** Use the provided script, which exercises the new command end to end across
both files:
```bash
bash lab/verify.sh
```
It should add tasks, delete one by index, and confirm the right task remains. If it fails, don't
hand-fix it — tell the AI what broke and let it iterate (step 4 of the loop), then re-run.
8. **Commit the reviewed change — this is your new checkpoint.** It passed your own eyes and it
passes the check, so lock it in:
```bash
git add .
git commit -m "Add delete command (made via editor/CLI agent)"
git log --oneline
```
You just shipped a reviewed, multi-file change made by an AI editing your files directly — and the
copy-paste loop never entered into it. This commit is now the clean state `git restore .` falls
back to in the next part.
### Part D — Practice the revert (do this even though it works)
9. You only trust an undo you've used. Your tree is clean — you just committed in Part C, which is
exactly the safe setup the one rule demands. Prove the net is under you: ask the tool for a
deliberately throwaway change —
> *"Rename every variable in `tasks.py` to single letters."*
— let it apply it, glance at `git diff` to see the damage, then throw it away:
```bash
git restore .
git diff # empty — the AI's mess is gone, byte for byte
bash lab/verify.sh # still passes — you're back at your good state
```
That's the Module 2 safety net catching a Module 4 mistake. Internalize how cheap that was.
### Part E — Confirm you're back at your good state
10. Nothing left to commit — the `delete` feature went in back in Part C, and Part D's throwaway is
already gone. Confirm the reviewed multi-file commit is your latest and the tree is clean:
```bash
git log --oneline # "Add delete command…" is the latest commit
git status # clean — the throwaway left no trace
```
That's the whole loop closed: a reviewed, multi-file change the AI made across both files is
committed, and the mess you made on purpose vanished without touching it.
---
## Where it breaks
Be honest about the limits of working this way:
- **Access is not judgment.** The AI reading your whole repo makes it *informed*, not *correct*. It
will still make confident, plausible, wrong changes — now across multiple files at once, which is a
bigger mess to read. The diff review in step 3 of the loop is not optional, and the deep version of
that skill is a whole module of its own (Module 10). The tool removed the copy-paste; it did not
remove the reviewing.
- **`git restore .` only saves you if you committed first.** This is the one rule for a reason. If
you let the AI loose on a dirty tree, restore can't tell your work from its work and throws away
both. The discipline that makes this module safe is *commit before you turn it loose* — the same
"commit often" lesson from Module 2, now with teeth.
- **It can do more than edit — watch what it runs.** An agentic tool that can run commands can do
things `git restore` cannot undo: delete files outside the repo, hit a network service, mutate a
database. Restore covers *versioned files only* (Module 2's honest limit, still true). Keep the
run-commands leash tighter than the edit-files leash until you've built the heavier isolation later
(branches in Module 6, containers in Module 16).
- **Big autonomous changes outrun your review.** A tool set to "just go" can produce a 12-file diff
faster than you can read it, and an unread diff is just copy-paste with extra steps. Keep changes
small enough to actually review. Scoping work into small, reviewable pieces is a skill the rest of
the course leans on hard.
- **The wiring drifts.** Install steps, auth flows, approval-mode names, and model pickers change
between tool versions. The four-step *shape* (install → authenticate → point at repo → confirm it
reads) is stable; the exact clicks are not. When in doubt, the "confirm it can read" test tells you
truthfully whether you're connected.
---
## Check for understanding
**You're done when:**
- An agentic editor or CLI tool is wired to your `tasks-app` repo and correctly answers "what does
this project do and which files is it in?" from the actual files — no pasting.
- You have a committed `delete` command that you watched the AI write across **both** `tasks.py` and
`cli.py`, that you reviewed with `git diff` before committing, and that `bash lab/verify.sh` passes.
- You have, on purpose, let the AI make a change and then erased it with `git restore .`, watching
`git diff` go empty.
- You can explain, in one sentence, why letting an AI edit your files directly is safe — and your
sentence mentions the clean commit you start from and the `restore` you can fall back to.
When making a multi-file change feels like "describe it, read the diff, keep it or restore it" — and
the browser copy-paste loop feels like a thing you used to do — you've got it. Module 5 takes the next
step: now that the AI is operating *in* your repo, you commit its *configuration* into the repo too,
so the setup you just did becomes a durable, shared, reviewable artifact instead of something every
teammate re-tunes by hand.
---
## Verify-before-publish
This is durable-core, but the wiring instructions touch tool surfaces that drift. Re-check at build
time:
- [ ] The two categories (editor-integrated assistants; agentic CLI tools) still describe the market,
and no single tool has become so dominant that "agnostic" reads as evasive — if so, name it as
*the common default* the way the syllabus treats GitHub in Module 8, without crowning it.
- [ ] The four-step wiring shape (install → authenticate → point at repo → confirm it reads) still
matches how current tools onboard; update the install-command examples if package-manager
conventions have shifted.
- [ ] The approval/permission model still maps to roughly read-only / auto-edit / full-auto across
current tools; update the labels if the common terminology has moved.
- [ ] `lab/verify.sh` still passes against the Module 1 `tasks-app` after an AI implements `delete`.