Skip to content

Commit f2ff6a2

Browse files
ChristineThamclaude
andcommitted
content: both apps were built from single-sentence prompts
Clarifies the strongest claim, which the articles were undercutting: the founding PRD, architecture and plan documents were drafted by the agent, not the author — from reference context the agent fetched for itself (GnuCash's source and manual; Obsidian and Bear feature lists). The author approved documents, and did not write them. Both descriptions now say "built from a single-sentence prompt", the FinvestLens ground-truth passage no longer claims the agent could not have obtained the source it in fact cloned, and both articles close on the point: a complete, shipping application, from a single sentence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent c9ded19 commit f2ff6a2

2 files changed

Lines changed: 43 additions & 35 deletions

File tree

src/content/blog/2026-07-27-finvestlens-1-0.md

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: 'FinvestLens 1.0: 56,000 lines of accounting software in fourteen days'
3-
description: A native Apple double-entry accounting app, verified against a real 46,000-transaction GnuCash book to the cent — built by writing specifications and issuing prompts. What the method got right, and what real data found that no test suite would.
3+
description: A native Apple double-entry accounting app, verified against a real 46,000-transaction GnuCash book to the cent — built from a single-sentence prompt, with the agent drafting its own specifications. What the method got right, and what real data found that no test suite would.
44
author: chris-tham
55
publishDate: 2026-07-27T07:00:00.000Z
66
featuredpost: true
@@ -29,12 +29,14 @@ The first commit landed on 12 July 2026. This one is 26 July. In between: 325
2929
commits, ten Swift packages, 56,611 lines across 221 files, 1,179 tests, and a
3030
phase plan taken from P0 through P10.
3131

32-
I typed very little of it, and less than you would guess. The instructions were
33-
mostly of two shapes — _"implement the next phase"_ and _"audit the implemented
34-
codebase against the plan and fix what you find"_ — issued to **Claude Code**,
35-
Anthropic's coding agent, running in an agentic loop. The specification said what
36-
done meant. The audits found the mistakes. That division of labour is the more
37-
interesting story.
32+
I typed very little of it, and less than you would guess. The whole project
33+
began as a single sentence — reimplement GnuCash as a native app for Apple
34+
platforms — and after that the instructions were mostly of two shapes:
35+
_"implement the next phase"_ and _"audit the implemented codebase against the
36+
plan and fix what you find"_, issued to **Claude Code**, Anthropic's coding
37+
agent, running in an agentic loop. The specification said what done meant. The
38+
audits found the mistakes. That division of labour is the more interesting
39+
story.
3840

3941
The method was not improvised. It is the one I set out in Chapters 2 and 3 of my
4042
book [_AI-dō_](https://christham.net/aidou/) — the practice and the craft — and
@@ -48,13 +50,13 @@ on whether the Way holds up.
4850
Nothing here is exotic, and I'd rather state it plainly than let anyone imagine
4951
a secret ingredient:
5052

51-
| | |
52-
| ------------ | ----------------------------------------------------------------------------------------------- |
53-
| **Agent** | Claude Code — working directly in the repository |
54-
| **Model** | Claude Opus 5 (`claude-opus-5`) |
55-
| **Language** | Swift 6 / SwiftUI, ten local Swift packages, one Xcode project |
56-
| **Oracle** | My own 46,553-transaction GnuCash book, GnuCash 5.16, and GnuCash's C/C++ source cloned locally |
57-
| **Sessions** | Many, across fourteen days — each beginning with no memory of the last |
53+
| | |
54+
| ------------ | ----------------------------------------------------------------------------------------------------- |
55+
| **Agent** | Claude Code — working directly in the repository |
56+
| **Model** | Claude Opus 5 (`claude-opus-5`) |
57+
| **Language** | Swift 6 / SwiftUI, ten local Swift packages, one Xcode project |
58+
| **Oracle** | My own 46,553-transaction GnuCash book, GnuCash 5.16, and GnuCash's C/C++ source, cloned by the agent |
59+
| **Sessions** | Many, across fourteen days — each beginning with no memory of the last |
5860

5961
The tools that actually mattered, as distinct from the ones that merely existed:
6062

@@ -105,14 +107,16 @@ The temptation with a capable coding agent is to start asking for features. That
105107
is the main way these projects go wrong: you get a pile of plausible code with no
106108
spine.
107109

108-
So the first artefacts weren't code. From a short statement of what I wanted, the
109-
agent drafted — and I reviewed — a **PRD** with numbered
110-
requirements, an **architecture document** with numbered decisions, a **porting
111-
strategy** mapping GnuCash's C modules to Swift ones, and a **phased plan**
112-
eleven phases, each with objectives, dependencies, deliverables, exit criteria,
113-
test focus and risks.
110+
So the first artefacts weren't code — but they weren't mine either. From that
111+
one sentence, the agent fetched its own reference context — cloning GnuCash's
112+
source, pulling its user manual — and then drafted, for my review, a **PRD**
113+
with numbered requirements, an **architecture document** with numbered
114+
decisions, a **porting strategy** mapping GnuCash's C modules to Swift ones,
115+
and a **phased plan** — eleven phases, each with objectives, dependencies,
116+
deliverables, exit criteria, test focus and risks. I approved documents; I did
117+
not write them.
114118

115-
That initial statement could afford to be vague because the reference context
119+
That sentence could afford to be that vague because the reference context
116120
was not. The product already existed — twenty-five years of it. GnuCash's
117121
source code, its user manual, its file format and its reports specify a
118122
double-entry accounting application more precisely than any requirements
@@ -142,14 +146,15 @@ Here's the decision I'd repeat on any project like this: **our own tests were
142146
never the final word.**
143147

144148
The final word was GnuCash itself. The expectation was written that way, and
145-
three things were supplied for the agent to check against:
149+
three things sat on disk for the agent to check against — two of them supplied
150+
by me, the third fetched by the agent for itself:
146151

147152
1. **A real book — mine.** My personal GnuCash file: 46,553 transactions, 559
148153
accounts, over 100,000 price records, multi-currency, a decade and a half of
149154
my actual financial history.
150155
2. **A real GnuCash install** (5.16) to produce reference reports.
151-
3. **GnuCash's actual C/C++ source**, cloned locally, as the porting oracle —
152-
not the documentation, not the binary, the source.
156+
3. **GnuCash's actual C/C++ source**, which the agent cloned for itself as the
157+
porting oracle — not the documentation, not the binary, the source.
153158

154159
That third one changed the quality of the work more than anything else. A prompt
155160
like _"audit our lot and cost-basis implementation against the real GnuCash
@@ -303,9 +308,10 @@ rule assigning one to a transaction has no coherent target); Quick Look for
303308
`.gnucash` (it's the interchange format, not the document you browse). An agent
304309
will happily build all four. Deciding they shouldn't exist is the job.
305310

306-
**I supplied the ground truth.** The real book, the GnuCash install, the source
307-
checkout, four genuine bank export files to validate the import matcher against.
308-
None of that is something the agent could have obtained.
311+
**The personal ground truth was mine to give.** The real book, and four genuine
312+
bank export files to validate the import matcher against — data no agent could
313+
obtain. The rest of the reference context the agent fetched for itself, starting
314+
with GnuCash's source.
309315

310316
**And taste stayed mine.** Whether a dashboard reads well, whether a number
311317
means the right thing — I can be shown the screen, but the verdict is a decision
@@ -490,8 +496,9 @@ whether there are any.
490496

491497
Which is the whole argument. State the intent and the expectations well enough,
492498
put something real within reach for the work to be checked against, and the rest
493-
— the implementation, the review, and the catching of its own mistakes — follows
494-
from the harness rather than from you.
499+
— the specifications, the implementation, the review, and the catching of its
500+
own mistakes — follows from the harness rather than from you. A complete,
501+
shipping application, from a single sentence.
495502

496503
## Try it
497504

src/content/blog/2026-07-27-hellonotes-1-0.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: 'HelloNotes 1.0: a Markdown knowledge base that is actually a Mac app'
3-
description: Fifteen days, 220 commits and 32,000 lines of Swift — a local-first knowledge base whose database is a folder, built by prompting. What the method got right, and the four traps that ate real hours.
3+
description: Fifteen days, 220 commits and 32,000 lines of Swift — a local-first knowledge base whose database is a folder, built from a single-sentence prompt. What the method got right, and the four traps that ate real hours.
44
author: chris-tham
55
publishDate: 2026-07-27T06:00:00.000Z
66
featuredpost: true
@@ -145,7 +145,7 @@ Both the app and its website follow your Mac, or pin to one appearance:
145145

146146
## How this was actually built
147147

148-
I wrote very little of this code by hand. I built HelloNotes by prompting [Claude Code](https://claude.com/claude-code), and the git history is co-authored throughout.
148+
I wrote very little of this code by hand. I built HelloNotes by prompting [Claude Code](https://claude.com/claude-code), the git history is co-authored throughout — and the whole thing began as one sentence.
149149

150150
It wasn't improvised, either. I published **[AI-dō — The Way of AI](https://christham.net/aidou/)** — a book arguing that working with AI is a discipline rather than a vibe — on **8 July**. The first commit in this repository is dated **11 July**. HelloNotes is the first thing I've built start-to-finish under a method I'd finished writing down three days earlier — specifically [Chapter 2, _Personal Productivity_](https://christham.net/aidou/productivity.html) and [Chapter 3, _Software Development_](https://christham.net/aidou/software.html).
151151

@@ -162,9 +162,10 @@ Before any code existed, I asked Claude to generate three documents based on my
162162
That intent could afford to be vague because the anchors were strong.
163163
HelloNotes sits in a category that existing products have already mapped —
164164
Obsidian for the linking model, Bear for what native ought to feel like — and
165-
the PRD was drafted against those reference points. The four-way gap in "The
166-
bet" above _is_ the specification: name what to keep and what to refuse from
167-
each anchor, and the requirements largely write themselves. A vague prompt over
165+
the PRD was drafted against those reference points — feature lists the agent
166+
researched and fetched for itself, not ones I wrote out. The four-way gap in
167+
"The bet" above _is_ the specification: name what to keep and what to refuse
168+
from each anchor, and the requirements largely write themselves. A vague prompt over
168169
strong references beats a precise prompt over none.
169170

170171
The plan is the part that made this work. Each milestone wasn't a wish, it was a table — task, target file, and an **acceptance criterion**:
@@ -185,7 +186,7 @@ as one of those passes. Extending something that already runs is an easier
185186
conversation than specifying everything up front, because the app itself
186187
becomes part of the reference context.
187188

188-
Why this works is worth being exact about, because the book states it as a caution: _"A model is a next-token predictor, not a compiler: it does not execute a specification, it produces the most plausible continuation of everything in its context."_ A spec doesn't help by being run — nothing runs it. It helps by putting the definition of _right_ into that context before the work starts, so that afterwards there is something other than plausibility to judge the output against. Commissioning that plan, and stating what "done" meant in it, was the highest-leverage work of the fortnight. Everything after it was "do Milestone 3".
189+
Why this works is worth being exact about, because the book states it as a caution: _"A model is a next-token predictor, not a compiler: it does not execute a specification, it produces the most plausible continuation of everything in its context."_ A spec doesn't help by being run — nothing runs it. It helps by putting the definition of _right_ into that context before the work starts, so that afterwards there is something other than plausibility to judge the output against. Commissioning that planand insisting the work be judged against the acceptance criteria in itwas the highest-leverage thing I did all fortnight. The heading above is not a paraphrase: one sentence went in, and the PRD, the architecture and the plan came out, drafted by the agent from context it had gathered itself. Everything after that was "do Milestone 3".
189190

190191
(That plan has since been folded into [`implemented.md`](https://github.com/hellotham/hellonotes/blob/main/docs/implemented.md), which is the honest engineering log — milestones, fixes, and a lot of what _didn't_ work. It's still in git history if you want the original.)
191192

0 commit comments

Comments
 (0)