Git Could Not Tell Me Who Wrote It
Over one weekend in May I shipped a macOS window manager. Forty-one commits, a notarized DMG, a Sparkle update feed, sixty-nine tests. It runs on my ultrawide every day. I am not going to oversell it. It snaps windows into zones. That is the whole app.
Here is the part that gets interesting. Every one of those forty-one commits is authored by me, with no co-author trailer, and not one line of the Swift was typed by me.
Git history alone hides the split entirely. So I went and rebuilt it from the only place it still existed: nineteen Claude Code session transcripts, twenty-eight megabytes of JSONL, sitting in a folder under my home directory. This post is what they said.
The Labor Split
Across the nineteen sessions, the agent made 134 file writes and 325 edits. It ran 742 shell commands, thirty of which were git commits. It spawned twenty-five subagents, asked me twenty-three clarifying questions, and churned through 86 task creations and 168 task updates keeping its own to-do list.
Every Swift source file in the shipped repo, all forty-seven app files and all nine test files, was written to by the agent at least once. Most show many. The largest single write was the layout editor view, 1,306 lines in one call, later edited forty-one times. The only tracked files it never touched were the license, the notice, and sixteen icon assets I made outside its reach.
Thirty of the forty-one commits were made by the agent. The other eleven I ran from a separate shell, which is why they left no trace in the transcripts.
So the honest description is this: the code is agent-authored end to end, with me in the directing seat. The reflex is to hear that as "the agent built it." The transcripts say something more specific about what the directing seat actually involved.
What I Was Doing
Git shows seven real fix commits. The transcripts show a different kind of correction that never became a commit at all. Those are the ones that tell you what the human's job was.
"Let's get rid of the button that collapses the side pane. There is no need for it. It also makes the window title get cut off."
"the add rule button goes away when I'm on the rule ... why don't you just use the same + as for the layouts and just make the user select what they're adding?"
"it worked pretty well, everything on my main screen worked ... windows got mixed up but they all docked. Didn't work on my xenon small display"
"Put a note on that task that it disrupts window placement ... Don't investigate that right now"
"revert everything you just did. trash it"
Read those in a row and a pattern is hard to miss. None of them are about implementation. They are about keeping the UX consistent and the scope small. The single plus button that became a rule across every editor in the app came from the second one. The decision to scope a whole phase to multiple displays came from the third. The fourth is me protecting a release timeline from a rabbit hole. The fifth killed a settings screen and its tests, 164 lines the agent had written minutes earlier, before either file was ever committed. They exist only in one session transcript now.
The implementation calls went the other way. The accessibility attribute toggle that makes some apps cooperate. The resize dance, size then position then size again, lifted from how yabai does it. The live probe through an event tap because the system's own "is this process trusted" call lies. Those came from the agent, after it read other window managers' source, and I accepted them without recorded pushback.
I did not know that was the split until I read the transcripts. My memory of the weekend was that I built a window manager. What I actually did was refuse a collapse button, insist on one plus sign, defer a bug, and throw away a settings page. The agent did the rest, and the parts it did well were the parts where it had prior art to read.
The Corrections Came Fast
Of the seven fix commits, five were fixes to code the agent had written in the cluster right before. Often under two hours later. The drag-to-snap overlay shipped at 10:22 and only worked on the primary display. The multi-display fix landed at 12:15. Workspace auto-restore shipped at 12:36 and fired on every grid snap instead of only on arrangement changes. The fix landed at 13:18, twenty-six minutes before the release commit.
That is the rhythm. Ship, ship, fix, ship. Not ship clean. If you are waiting for the version of this workflow where the agent gets it right the first time, you are waiting for something the transcripts say does not exist. At least not at this pace. What exists is a loop that tolerates and expects the fix. The fix is cheap because the thing that broke was written an hour ago and the context is still warm.
There are zero revert commits in the history. There is one revert in the transcripts. Those are different facts and the second one matters more.
Four Lines
The repo's CLAUDE.md is four lines long. Target Swift 6 idioms. No force unwraps. Sendable across actor boundaries. Notes on SwiftUI modernization.
Each clause traces to something that went wrong on the first pass.
The initial engine commit shipped with force unwraps and unguarded accessibility calls. The very next morning, commit two of the day was a whole pass to remove them. The "no force unwraps" rule was written after that pass, not before it. The Swift 6 hardening got bundled into a later feature commit, because the earlier code was not ready for strict concurrency. So the rule about actor boundaries was also written after the fact.
And the first version of the CLAUDE.md itself was wrong about the project. It described something other than a macOS app on Swift 5.10. It was rewritten five minutes later to match reality. The file that instructs future sessions was, for five minutes, instructing them about a project that did not exist.
Most people write that file first and it reads like a wish list. Mine reads as a list of scars, because that is what it is. There is a longer essay in that. This is the shortest possible version of it: a four-line file, each line a fix commit you can go find.
What Git Recorded
The commit log by itself tells a clean story. Phase 0 engine baseline Sunday night. Phase A through D on Monday: editor, release pipeline, per-app rules, arrangement detection. Phase E and F Tuesday morning: mouse-driven snapping, grid overlay, workspaces. Release commit at 13:44. Thirty-eight and a half hours from baseline to v1.0.0, of which about fifteen were active. The rest I was not at the keyboard.
Clean, and also incomplete in a way I would not have noticed if I had not gone looking. The commit log records the destination. It does not record that I killed a feature, or that the agent got the project description wrong, or that every UX decision in the app came from a one-line message. That record lived in a folder I had never opened until I decided to write this.
I am not sure what to do with that except keep the folder, and stop trusting my memory of weekends. Git is the story we tell about the work. The transcript is the work.
-- Justin Higgins. Software Engineer, Midwest. Shipped a window manager in a weekend and then read what actually happened.
Companion pieces: The Work Looks Like Nothing - why the session log is the first record of judgment that ever existed. The Rules Are Downstream of the Work - the four-line CLAUDE.md, at essay length.
Reactions, disagreements, war stories: jchigg2000.dev@gmail.com