The data annotator in the gym
Not anti-patterns: a way to validate a product on paper before building the version that scales. Laser focus on the part only you can build; the rest is a template away.
For the first week, I logged every set by hand in Apple Notes.
A commercial gym, machines only. Each line was the exercise, the weight, the reps, and then the part most apps throw away: the machine itself. The seat number. Which hole the ankle pad sits in. Which leg extension machine I was on. I wrote all of it down because I wanted a baseline, and a baseline without the machine settings is not a baseline. Move the seat one notch and the number means something else.
By the end of that week I had a sentence for what I was doing: I'm literally a data annotator in the gym. There are thousands of fitness apps. None of them are built to reduce the friction of taking logs.
I am not recommending anti-patterns here. I am recommending a way to validate a product before you build the version that scales to a million users. Hand-log a baseline. Then a template. Then the app. That sequence converges on what the product actually is, very fast, and it costs almost nothing. Once you have that, use agents aggressively.
The rest, the auth, the database, the deployment, the thing that scales, is a solved problem. Claude Code and a thousand templates will build it on demand. It is not what I worry about, and it sits at the bottom of my list. What nobody can template is the part that is only yours, and the whole point of three weeks on paper is finding out what that is.
Converge before the agents touch it
Week two, I dumped the notes into ChatGPT and asked for a pre-filled template for the week ahead. Every exercise, every setting I had already written down, and a dash wherever something was not going to change. My job in the gym shrank to filling in the blanks.
It also forced me to write the rules down. Clean reps first. 120 seconds of rest on compounds. Write the actual number over the blueprint, never next to it. Two weeks of that discipline gave the later analysis real signal, which I would not have predicted from a document.
Week three, the template stopped making sense. Every week it needed regenerating, every correction lived in two places, and the timestamps were whatever I typed, which is to say approximate.
I also wanted sleep, resting heart rate, HRV and steps next to the lifting data, and Apple gives you no API to fetch your own Health data from anywhere but the phone itself. An app that reads HealthKit was the only clean path. The alternative was doing RPA on my own body.
So: let's make an app. It is called Pin, it is built for exactly one user, and I am not turning it into a startup. But by the time I wrote the first line of code, I already knew what it was for. Three weeks of paper had told me.
The 99 dollars
The Apple Developer Program is USD 99 a year, and TestFlight needs it. That felt like a bummer for an app with one user.
The free option is Personal Team signing: the app stops opening seven days after its profile was created. I was shipping a new build every three or four days anyway, so it never mattered. Re-signing became a line item in the Sunday retro and never once bit me. HealthKit works on the free team too, which I checked in the first spike, before the app had a real screen.
What I decided before the code
There is no server. No account, no cloud database. The phone keeps JSON files, one per finished workout, plus a snapshot of the running workout rewritten after every tap, so the app being killed is a non-event. The Mac pulls the files over Wi-Fi whenever it wakes up. Nothing needs to be online at the gym.
The plan is data. Plans are JSON, validated on both sides, and the app never hard-codes a workout. A bad plan is rejected with a reason and the current plan stays.
Timestamps are canonical. Each set records a start and a finish. Rest and duration are derived, never typed, never edited. Fixing a typo in the reps cannot corrupt time, which is exactly what used to happen in Notes.
The raw export is the durable record. Every file the phone ever sent is kept byte for byte. SQLite is rebuilt from it and ingest is idempotent, so a schema change is a rebuild, not a migration.
The coach never runs inside the app. The app makes no AI calls. Software on the Mac computes every fact. A model proposes a plan, and then software fixes the IDs, the week, the numbering, merges the machine settings back in, validates, and rejects on any problem. The model can change a seat setting. It can never drop one.
Then let the agents run
Once those decisions were made, I stopped being careful about speed. The agents write the code, and they live under a short law. Screenshot every screen in light, dark, and at a large text size. Only system components.
A smaller model drives the real screens from goals, not steps, and I read its trace rather than its verdict. On one run it reported that a note "didn't take". The data showed it had saved. The field just did not show the draft after a re-render, and that was a real bug I would not have found myself.
That is what aggressive looks like when the target is fixed. The agents are fast because they are not deciding what the product is.
The queue
Not every product idea needs to be shipped to production.
I keep a product queue. If I feel an idea is amazing, I sleep on it, or I get a model to roast it. Then I prioritise it the next morning instead of asking an agent to build it. Bugs get fixed right away. Features wait, with my own words attached, and nothing gets built on the spot.
The reason is simple. With AI, building is cheap. In the realm of token maxing, it is very easy to build an application you never even wanted, or to dilute the one thing that made it worth building. When building costs almost nothing, the scarce resource is laser focus on the few things that really matter. The question I keep asking is whether I will actually use this between sets, with my hands shaking.
Keep the differentiation at the centre
Pin is different in a few specific ways, and I keep those at the core.
Every set has a timestamp. There is no start and stop button to mash; the set has a start and a finish, and the app records both from the taps I was already making.
The machine setup is on the screen. My first instinct hid the settings in small gray chips I could not read between sets. They came back in the first redesign as big tiles, editable mid-workout.
There is no server. And code owns every number. The daily note computes my usual from the last 28 days of my own data. Fixed rules decide green, amber or red against it. A red day trims one set per exercise, same weights, today only, and the rules can never add load. The same rules exist in Python on the Mac and in Swift on the phone, pinned by one shared fixture. The model's only job is to rewrite the words.
Everything else is a template away. I add it only if I want it.
Where determinism ends
Two structured streams land on the Mac every day: Apple Health's daily summaries, and glucose from a continuous glucose monitor, which arrives through Health as well.
That boundary is the thing I keep thinking about. Right now I trust code with every number and the model with none of them. That is clearly the right default for a plan I am going to load onto my body. But the facts the Mac assembles are getting richer, and the question of which facts a coach should even see, and how fresh they are, is starting to look like judgement rather than arithmetic.
I do not know yet where determinism ends and the model begins. Three weeks ago the answer was "everything is a note". I would rather keep moving that line by hand, one week at a time, than guess at it.