A standalone blog/ folder (not course content) with drafts for jpaul.me: an announcement, a getting-started piece, then a hybrid weekly series — one post per module for Units 1-2 (posts 03-13) and one per unit for the back half (14-16) plus a capstone finale (17). Each post carries WordPress metadata, a [COURSE LINK] placeholder, and [insert screenshot] blocks for Justin to fill before publishing. README.md holds the manifest + checklist. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015EghAChc9UbcF78t55mfdf
15 KiB
Let the AI Edit Your Files (Yes, Really — Here's Why It's Safe)
A few posts back I named the thing that makes building software with a chat window feel like work: you are the integration layer. The AI hands you text, you copy it, you paste it into the right file, you notice it forgot the second file, you fix that by hand. Describe, copy, paste, run, paste the error back, repeat. We called it the copy-paste loop, and the whole point of [The Workflow]([COURSE LINK]) is to dismantle it.
This is the post where we actually do that. Not soften it. Not make the pasting a little faster. End it.
The move is to let the AI out of the browser — to give it the two things it never had in a chat tab: the ability to read your whole project, and the ability to edit the files directly. No pasting, no you-in-the-middle. And the first reaction every sane person has to "let the AI write to my files" is, correctly, that sounds reckless. It would be — except for one thing we already did. Hold that thought; it's the whole post.
What "out of the browser" actually means
In the chat-window world the AI is blindfolded and handcuffed. It can't see a file unless you paste it in, and it can't change anything — it can only print new text and trust you to put it in the right place. That's not an intelligence problem. A smarter model is still blindfolded. It's an access problem.
Getting the AI out of the browser hands it the two capabilities the chat tab withheld:
- Read access to the whole repo — it can open any file, search the project, and see how
tasks.pyandcli.pyfit together, without you pasting a single line. - Write access to the files — it edits those files in place instead of printing a version for you to copy back over your own work.
That's it. Everything else in this post follows from those two. And those two are exactly why we spent a whole module on version control before this one — because write access to your files is only sane when every edit is visible and reversible.
Two shapes it comes in
This tooling shows up in two forms. They overlap, plenty of products do both, but the distinction is worth knowing before you pick — and I'm deliberately not going to crown a winner, because the "best" one changes by the quarter.
Editor-integrated assistants live inside a graphical code editor — a side panel you chat with, inline suggestions, and an "agent" or "edit" mode that proposes changes across files which you accept or reject right there in the editor's diff view. If you already work in a graphical editor, this is the lowest-friction on-ramp: the review surface is sitting right next to your code.
Agentic command-line tools run in your terminal as a standalone program you talk to in plain language. You launch it inside your project folder, 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 whole multi-step thing" — and they don't care which editor you use, because the review surface is git diff itself.
You don't have to choose forever, and you'll probably end up using both. Pick one to learn the loop with. Here's the thing I want to land, though: the loop is identical either way. The tool is swappable. The habit is the skill.
How to choose without overthinking it
Evaluate on properties, not brand. The two that matter most:
- Can it bring its own model? Some tools let you point at whichever provider you want; some bundle one. A tool that lets you swap models is hedging in your favor.
- Does it show diffs before applying, with an approval mode? Non-negotiable. You need to see what it wants to change, and control what it's allowed to do without asking.
A couple of others worth a glance: whether it reads a committed, repo-level instructions file (you'll want that in the next post), and what its data policy is — for work code, know whether your files get used for training and whether there's a self-hosted path. But honestly, don't agonize. Any tool that shows you a diff and asks before it acts is good enough to learn on.
Wiring it up: four steps, any tool
The exact clicks differ per tool and drift constantly, so here's the shape every one of them follows. Four steps and you're connected.
-
Install it. Editor assistants come from your editor's extension marketplace — search, install, reload. Agentic CLIs install as a command-line program (often via
npm/pip/brew) and then exist as a command you run:your-agent --version # confirm it's on your PATH -
Authenticate. First run sends you through a sign-in — usually a browser login that drops a token on your machine, or a paste-in API key. One-time setup. If the tool lets you pick a model here, this is where that choice gets made.
-
Point it at the repo. This is the step with no equivalent in the browser, and it's the entire point. The convention is the current working directory is the project:
cd ~/workflow-course/tasks-app # the repo from earlier modules your-agent # launch from inside the projectFor an editor assistant, the equivalent is just open the project folder — the assistant scopes itself to whatever folder is open. Either way, the tool now treats this directory as its world.
-
Confirm it can actually read. Don't assume — verify. Ask it something only a tool that's 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.pyandcli.pyand listsadd/list/done, pulled from the real files. If it asks you to paste code, or describes a generic to-do app it clearly invented, it is not connected. Stop and fix the wiring — everything downstream assumes it can read.
[insert a screenshot referencing an agentic tool correctly answering the "what does this project do" question by naming tasks.py and cli.py here]
The loop that replaces copy-paste
Connection is half of it. Here's what you actually do once connected — and it replaces the entire copy-paste loop:
-
Describe the change in plain language. Not "here's a file, rewrite it" — "add a command that deletes a task by its index." You let the tool decide which files that touches.
-
The AI edits the files directly. It opens what it needs, makes the changes in place, and tells you what it did. This is the exact moment the worst seam dies: when the change spans
tasks.pyandcli.py, the tool edits both, because it can see both. You are no longer the integration layer holding two files in your head. -
Review the diff. This is the load-bearing step:
git diffRead exactly what changed — every line, across every file it touched. An editor tool shows you the same thing in its diff view. You are reviewing the AI's work, not trusting it. (Spotting the plausible-but-wrong change is a deep skill that gets its own post later. For now just build the reflex: nothing gets committed unread.)
-
Keep it or kill it. If it's right, run it and commit — 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 at 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 me be blunt about it.
Why this is safe (the part the whole post hinges on)
Letting an AI write to your files sounds reckless, and in the copy-paste world — no version control, no checkpoints — it absolutely would be. What makes it safe is not that the AI is careful. It isn't, reliably. What makes it safe is that you committed first, so every edit it makes is a visible, reversible delta from a known-good state.
The safety contract is three lines:
- Before you turn it loose: your work is committed.
git statusis clean. That's your restore point. - While it works: every change is on disk, and
git diffshows you all of it. Nothing is hidden. - If it goes wrong:
git restore .discards every uncommitted edit and drops you back at the checkpoint, zero retyping.
This is the promise version control made, finally cashing out. The reason we installed the safety net before doing anything bold with the AI is this exact moment — the downside of any AI edit is now "throw away a few minutes and re-prompt," never "lose work." That asymmetry is the whole thing. It's what lets you move fast without flinching.
There's one rule that makes it work, and it has teeth: 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.
Do it: one real, reviewed, multi-file change
Enough theory. Wire your tool to the tasks-app repo, confirm it can read (the question above), then make the exact change that broke the copy-paste loop in the first place — the one that needs two files.
First, the one rule:
git status # must say "nothing to commit, working tree clean"
If it's not clean, commit first. Now anything that shows up in the next diff is purely the AI's.
Then ask — in plain language, letting it pick the 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 intasks.pyand wire the command up incli.py. Match the existing code style and update the usage string."
Let it edit the files. Do not copy anything by hand — if you catch yourself pasting, the tool isn't actually wired up. Then review before you trust a line of it:
git diff
Confirm with your own eyes: a new method on TaskList, a new delete branch in cli.py's dispatch, the usage string updated — and nothing touched that shouldn't be. Two files changed, and you didn't merge them by hand. That's the seam, gone. When it looks right, lock it in:
git add .
git commit -m "Add delete command (made via editor/CLI agent)"
You just shipped a reviewed, multi-file change that an AI made by editing your files directly, and the copy-paste loop never entered into it.
Now the part people skip — and shouldn't. You only trust an undo you've actually used. Your tree is clean, so prove the net is under you. Ask for something deliberately awful:
"Rename every variable in
tasks.pyto single letters."
Let it apply, glance at the damage in git diff, then:
git restore .
git diff # empty — the mess is gone, byte for byte
That's the safety net catching a mistake you made on purpose. Internalize how cheap that was, because that cheapness is your whole license to experiment.
[insert a screenshot referencing git diff showing the two-file delete-command change across tasks.py and cli.py here]
A note on permissions
Out of the browser, an agentic tool can do more than edit files — it can run commands: tests, linters, the app, git. Every serious tool has an approval model, roughly: ask before everything (slowest, safest — start here), auto-edit but ask-to-run (a good default once you trust the diff habit), or just go (fast, and appropriate only when the blast radius is contained).
The right setting is a function of your safety net, not your nerve. With a clean commit you can afford a loose setting for edits, because the diff is reversible. Be stingier about letting it run commands unattended — a deleted file is restorable; a command that hits a real database or a live service may not be. Match the leash to what you can actually undo.
Where it breaks
Honesty section, like always:
- Access is not judgment. Reading your whole repo makes the AI informed, not correct. It'll still make confident, plausible, wrong changes — now across several files at once, which is a bigger mess to read. The diff review isn't optional. The tool removed the copy-paste; it did not remove the reviewing.
git restore .only saves you if you committed first. That's the one rule, and it's the one rule for a reason. Turn the AI loose on a dirty tree and restore can't tell your work from its work — it throws away both.- It can do more than edit — watch what it runs. Restore covers versioned files only. A tool that can run commands can delete files outside the repo, hit a network service, mutate a database — things no
git restoreundoes. Keep the run-commands leash tighter than the edit-files leash. - 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.
- The wiring drifts. Install steps, auth flows, approval-mode names — they all change between versions. The four-step shape (install → authenticate → point at repo → confirm it reads) is stable; the exact clicks aren't. When in doubt, the "confirm it can read" test tells you the truth.
Notice what just happened, because it's the thesis in miniature: you didn't get a smarter model. You took the same model, gave it access, and wrapped it in review and revert. The leverage came from the workflow around the model, not the model. Swap the model underneath this loop tomorrow and the loop doesn't change.
You're done when
The AI is wired to your repo and can tell you what the project does from the real files, no pasting. You've watched it write a delete command across both tasks.py and cli.py, reviewed the diff, and committed it. And you've let it make a mess on purpose and erased it with git restore ., watching the diff go empty. If you can explain in one sentence why this is safe — and your sentence mentions the clean commit you start from and the restore you fall back to — you've got it.
When a multi-file change feels like "describe it, read the diff, keep it or restore it," and the browser copy-paste loop feels like something you used to do, this module has done its job.
Next up: now that the AI is operating inside your repo, we 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.
Following along — or fighting with a tool that won't admit it can't read your files? Drop a comment. I read them, and the rough edges you hit are exactly what sharpens the course.