2026-10-08 · one afternoon
Role: sole developer, pairing with Claude Code. Stack: Python, FastAPI, Next.js, Claude Opus, Obsidian. Outcome: spec to merged PR on 2026-10-08; a saved brief reads back in 0.08 s.
The idea
Praxis, my personal AI operating system (Article 1 covers how it works), already answered "what did I do yesterday?" well, but the answer vanished when I closed the panel. I wanted the answer to become a page: a formatted daily brief saved into an Obsidian vault, readable on the dashboard and in Obsidian, and reused the next time anyone asked about that day.
The reference point was a video of someone's "Jarvis" assistant that reads reports out of Obsidian. I took the read-or-generate idea and changed the part that wouldn't survive contact with a daily report.
Step 1: grill it before building it (14 decisions)
I use a reasoning workflow called grill-me: Claude interviews me one question at a time, recommends an answer for each, and pushes back when an answer is weak. It settled 14 decisions; these six shaped the design most:
- Who reads it? Both the dashboard and Obsidian, from the same file. Obsidian wasn't even installed yet, so the first version had to work without it.
- What gets saved? Named reports get their own page; every other question goes into one ask-history note per day, not a page each.
- Is writing a page a mutation? It became a rule: questions may write derived output that can be rebuilt, never state.
- When is a saved page stale? When its sources change, not when it exists (a fingerprint of log lines, commits and closed tasks).
- Which model? Opus, because the brief is the durable record and gets regenerated rarely.
- What triggers it? On demand, end of session, and start of the next session, which finalizes yesterday.
The pushback that mattered most: I wanted a full composite "morning report" system straight away. The grill separated the goal (see a rich report to learn what I want) from the means (a generic framework). The morning report became its own follow-up feature.
Step 2: a PRD with 11 tasks
feature-prd turned the decisions into requirements, acceptance criteria and a task list; prd-to-tasks filed the tasks with ids.
Step 3: implement, one task at a time
The implement workflow builds one task, then stops. Before every edit it states the files it will touch and the approach, and waits for my yes. Highlights from the eleven tasks:
- A task-completion date stamped by editing only the metadata comment, so task titles stay byte-for-byte.
- A shared reports module: paths, frontmatter, notes preserved across regeneration, freshness checks, freezing, a cross-process lock and atomic writes.
- The skill itself: gather the day's logs, my commits across all local branches (filtered to my author email, so collaborators' work isn't mine), and closed tasks; have Opus write five sections, plus a
## Notessection of my own that survives every rewrite; reject any output without a summary, so a bad generation never overwrites a good page. - Routing: one-day questions go to the brief, and its summary is returned word for word with no second summarization pass.
- Dashboard: a reports page, the full brief in the Ask panel, and "Open in Obsidian" links.
Step 4: validate on real days
I generated three real days, a quiet one, a normal one and a busy one, twice each: once with thinking on and once with it off. Then I read all six pages against their sources.
| Day | Log lines | Thinking | Time to write | Output tokens |
|---|---|---|---|---|
| 2026-10-04 | 6 | on | 14.4 s | 1,323 |
| 2026-10-04 | 6 | off | 12.0 s | 1,121 |
| 2026-10-06 | 14 | on | 26.0 s | 2,878 |
| 2026-10-06 | 14 | off | 25.8 s | 2,925 |
| 2026-10-02 | 84 | on | 40.6 s | 4,902 |
| 2026-10-02 | 84 | off | 40.1 s | 4,665 |
Thinking turned out not to be the cost on Opus, unlike Haiku. Time tracks the length of the page, about 115–120 output tokens a second, so a busy day simply takes longer. I left thinking at its default. Reading each page against its sources, nothing was overstated and every number traced back to a real commit or PR. A page already written reads back in 0.08 s.
Step 5: first contact with Obsidian
Opening the vault's graph exposed something no test would: file names like 2026-10-08.md collided with other notes of the same date, because Obsidian labels and links notes by file name alone. Pages became brief-<date>.md and asks-<date>.md, and the decision was recorded as an amendment to the original grill.
The result
Everything above happened on 2026-10-08. The grill wrapped up around 16:15, the spec and its 11 tasks were committed at 16:39, and the PR merged at 19:58.
- One feature, ~2,000 lines across 38 files, merged as one squash commit.
- 919 tests passing, and CodeRabbit's automated review had no findings.
- A second Claude session was building a mobile app in the same repo on the same day. The two sessions kept each other informed about API changes, and the mobile app's task updates went to main in their own commit so they didn't ride along in this feature.
What I'd keep: decisions written down before code, a checkpoint before every edit, and validation on real data rather than fixtures.
Next in this series: A day with Praxis, on what using it actually looks like.