Every week I build things. Products, features, pipelines, automations. Some weeks I ship 50 commits. Some weeks I ship 300. Every week, without exception, I fail to write down what I did.
By Sunday I can name the headline deliverable. Beat the Gaffer went live. Buggy Smart started calling restaurants. The voice clone shipped. But the texture is gone: the dead ends, the small wins, the decision to go left instead of right at 11pm when everything could have gone either way. That information dissolves. Not because it was not worth keeping. Because keeping it requires friction, and friction is fatal to habits that happen after dark.
The obvious fix was automation. If the record writes itself, it gets written.
The first version failed
I set up a Claude Code scheduled task: a cron-style agent that would run on Sunday evenings, pull my commit data from GitHub, and write a structured summary. It worked intermittently. The problem was architectural rather than technical.
Claude Code scheduled tasks require Claude Code to be running. Claude Code runs on my laptop. My laptop is not always on at the scheduled time. If I closed it at 8pm on a Sunday, nothing happened. If it had gone to sleep, nothing happened. If the session had timed out, nothing happened. The task was reliable in theory and unreliable in practice, which in practice means it was unreliable.
The fix was obvious once I had wasted enough Sunday evenings on it: the automation needs to run somewhere that does not have a lid.
Server-side all the way down
GitHub Actions runs on GitHub's servers. It fires at the scheduled time regardless of what my machine is doing. A cron expression in a YAML workflow file: 0 23 * * 0. Sunday at 11pm UTC. Every week.
The workflow fetches commit data across 16 repositories. One detail worth noting: the built-in GITHUB_TOKEN only has access to the repository the workflow lives in. You need a personal access token with repo scope to read commits from other repos. This costs about an hour to discover the first time. The token goes in as a repository secret. From there it is straightforward: a Python script loops through each repo, collects the week's commits, formats them, and passes the full context to the Claude API.
The prompt asks for a structured weekly report: a stats line, three top achievements, a day-by-day account, and a Slack-formatted summary. The report saves as a markdown file in a private GitHub repository. A Slack API call delivers the summary as a direct message.
That all runs on GitHub's infrastructure. My laptop could be off entirely.
The local half
The report now exists on a server. The problem is getting it into Obsidian, where I keep everything, and keeping the portfolio progress page current each week without touching it manually.
That is where launchd comes in. launchd is macOS's system-level job scheduler. Unlike cron, unlike any application-level tool, it runs as a daemon: part of the operating system itself. A plist file in ~/Library/LaunchAgents tells it to run a shell script at 10am every Monday. If the Mac was asleep at 10am, launchd fires as soon as it wakes.
The script fetches the latest report from the GitHub API, checks whether it has already been synced (idempotent by filename, so running it twice does nothing), writes the file locally, prepends it to the Obsidian bible, regenerates the progress page HTML, and deploys to Netlify. All without any application needing to be open. All without any action from me.
Sunday evening: report generates, Slack message arrives. Monday morning: Obsidian updates, progress page deploys. The loop closes itself.
Fifteen weeks
Once the infrastructure existed, I ran a backfill: a Python script that generated reports for every week back to 9 February 2026, the first week I started tracking commits seriously. Fifteen reports. 2,511 commits. Sixteen projects.
The backfill took about twenty minutes to run. It produced fifteen weeks of data that had previously lived only in my head, partially and incorrectly.
Looking at fifteen weeks in sequence produces a different kind of understanding than looking at individual weeks. The shape becomes visible. February was exploratory: low commit counts as I found my footing. A step-change in March when the Buggy Smart voice pipeline went live. An acceleration from mid-April that has not stopped. The best week on record: 18-24 May 2026, 331 commits. Beat the Gaffer, zero to full production product in six days.
The progress page at mikelitman.me/progress-public shows all of this. A commit velocity chart with interactive tooltips and milestone markers for notable weeks. A project Gantt: each row a project, each column a week, coloured cells showing when each thing was alive. Monthly totals. A momentum score: my recent four-week average is 64% above the fifteen-week baseline. A personal best bar in gold.
None of that was the plan when I started. The plan was to stop forgetting what I built.
What this actually is
I came up through culture, media and brand strategy. The products I am shipping now are the first I have shipped end to end, and the only reason I can is that the tools changed fundamentally. I am not a software engineer. I am someone who learned to work with the layer that sits above the code.
The weekly build log system is not particularly complex software. It is a GitHub Actions YAML file, a Python script calling the Anthropic API, a launchd plist, and a shell script. A senior engineer could build it in an afternoon.
What it represents is something different: the ability to identify an infrastructure problem (I am losing the record of my own work), understand the architectural reason it is failing (client-side automation requires the client to exist), redesign the system around the right constraint (server-side generation, daemon-level local delivery), and ship something that actually runs. Then use the output to understand your own patterns.
The progress page is a portfolio artefact. When I share it with a potential collaborator or a hiring manager, it is not a list of things I claim to have done. It is a record. The Gantt shows when each project was alive. The momentum score shows whether I am accelerating. The personal best bar shows what a good week looks like, so I know what I am aiming at.
The thing I built to stop forgetting what I built became the clearest proof that I have been building.