madelogdocs

Workflow

One project over three weeks, day by day, from madelog init to the link you send. What you type, what gets recorded, and what the page makes of it.

This page follows ledger, a CLI that reconciles bank CSV exports against invoices, from the first commit on Monday 31 August 2026 to a published page on Thursday 17 September. The log listings, analysis and summaries are the real output of madelog 0.1.0 over that log. Times in the log are UTC; the developer is in Zagreb, two hours ahead.

Before the first commit

Install madelog, then set the repository up while the intent is fresh. The four answers become the headline of the page, so write them the way you would say them to a person.

$ curl -fsSL https://madelog.app/install.sh | sh
$ cd ~/projects/ledger && git init -b main
$ madelog init
What are you building? A CLI that reconciles bank CSV exports against invoices
Who is it for? A small accounting firm that closes its books by hand
Which AI tools do you use? (comma separated) claude-code, cursor
Record AI sessions from Git AI? [Y/n] y

If you use an AI coding agent, install Git AI now. It attributes lines at commit time; a commit made before it was installed carries no attribution and never will.

Week 1: 31 August to 6 September

Monday. Two commits: the skeleton at 09:12 UTC and, after a note, the SQLite store with its first migration. The note takes ten seconds and lands between the two commits, anchored to the first:

$ madelog note "chose SQLite over Postgres: one binary, no service to run"
noted at 162c5db

That order matters later. A decision followed by a commit that opens a directory no earlier commit touched (migrations/) is what the analysis calls a direction change.

Tuesday. A Claude Code session writes src/import.rs. Git AI attributes 51 of its 58 lines to the session; the hook records the commit and one ai_session event with the session's first prompt. At 17:05 a fix to the same file: the importer dropped the last row of a file without a trailing newline. Nothing to type; the hook records both.

Wednesday. Three commits on src/matcher.rs inside 50 minutes, all with "wip: matching by amount" in the subject. The analysis will call this a retry.

Thursday. A report command, reverted an hour and a half later, and two notes. One of them is private:

$ madelog note "dropped the report command for now: the client only needs the matched list as CSV"
noted at 50f2f57
$ madelog note --private "ask Ivana whether the bank export can include the counterparty IBAN"
noted at 50f2f57 (private, never published)

The private note is in the chain and in madelog log, marked (private). It is not in the summaries, not in the preview, not on the page.

Week 2: 7 to 13 September

Nothing until Thursday the 10th. Then one commit of 12 files and 444 lines: the matcher rewritten around a rules table. Six days of silence followed by a large commit is a stall in the analysis, and the longest stall becomes a moment on the page, with the length of the gap and the size of the commit that ended it.

Week 3: 14 to 20 September

Tuesday. Documentation. Wednesday. A note, then a Cursor session writes the CSV export. Cursor's session id is not a Claude Code transcript, so the event has no prompt; the page will say "No prompt was recorded for this session". Thursday. The release commit, and time to look at what was recorded.

$ madelog log
   1  2026-08-31T09:00:00.000Z  intent      A CLI that reconciles bank CSV exports against invoices
   2  2026-08-31T09:12:00.000Z  commit     162c5db  feat: project skeleton
   3  2026-08-31T09:40:00.000Z  decision   162c5db  chose SQLite over Postgres: one binary, no service to run
   4  2026-08-31T10:05:00.000Z  commit     d7448f4  feat: sqlite store and first migration
   5  2026-09-01T14:20:00.000Z  commit     fb7eeec  feat: csv import with BOM handling
   6  2026-09-01T14:20:01.000Z  ai_session fb7eeec  claude-code: Write src/import.rs: read a bank CSV with columns amount, reference, booked_on into a Vec<Row>. Strip a UTF-8 BOM, skip the header, store amounts as integer cents.
   7  2026-09-01T17:05:00.000Z  commit     d366a14  fix: importer dropped the last row when the file has no trailing newline
   8  2026-09-02T10:00:00.000Z  commit     fcd9b5f  wip: matching by amount
   9  2026-09-02T10:25:00.000Z  commit     b17e06a  wip: matching by amount and date
  10  2026-09-02T10:50:00.000Z  commit     1595716  wip: matching by amount and reference
  11  2026-09-03T09:30:00.000Z  commit     ea23143  feat: report command
  12  2026-09-03T11:00:00.000Z  commit     50f2f57  Revert "feat: report command"
  13  2026-09-03T11:10:00.000Z  decision   50f2f57  dropped the report command for now: the client only needs the matched list as CSV
  14  2026-09-03T11:12:00.000Z  decision   50f2f57  ask Ivana whether the bank export can include the counterparty IBAN (private)
  15  2026-09-10T09:00:00.000Z  commit     72ddd54  feat: matcher rewrite with explicit rules and a rules table
  16  2026-09-15T08:40:00.000Z  commit     b80d5ec  docs: usage and the matching rules
  17  2026-09-16T09:05:00.000Z  decision   b80d5ec  kept the export in the same binary: a second tool means a second install for the client
  18  2026-09-16T11:30:00.000Z  commit     a54c60b  feat: export matched rows as csv
  19  2026-09-16T11:30:01.000Z  ai_session a54c60b  cursor: (prompt not recorded)
  20  2026-09-17T16:02:00.000Z  commit     f850c1c  chore: release 0.1.0

Twenty events in three weeks, of which you typed four. Check the chain, then run the analysis:

$ madelog verify
chain ok
20 events, root fee0947a2807ec497d534040725b20c26975e617c6c45fc9623b10f1a546ae62
$ madelog analyze
4 patterns in this log:
  fix_after_ai  fb7eeec d366a14          d366a14 reworked AI-written code in src/import.rs two hours after fb7eeec.
  retry         fcd9b5f b17e06a 1595716  Three commits in 50 minutes reworked the same file.
  revert        ea23143 50f2f57          Reverted 2 files changed in ea23143 one hour earlier.
  stall         50f2f57 72ddd54          After six days without commits, 72ddd54 changed 12 files (444 lines).
recorded 4 new pattern events

4 moments for the page:
  1. Fixing AI-written code in src/import.rs (fix_after_ai)
     fb7eeec ("feat: csv import with BOM handling") carried AI-written lines in src/import.rs. Two hours later, d366a14 went back to the same code: "fix: importer dropped the last row when the file has no trai...". Git AI attributed 51 lines in fb7eeec to the model.
  2. A decision, then a new migrations/ (direction_change)
     You wrote down a decision: "chose SQLite over Postgres: one binary, no service to run". The next commit, d7448f4, added 1 file under migrations/. It was called "feat: sqlite store and first migration".
  3. A decision, then a new src/rules/ (direction_change)
     You wrote down a decision: "dropped the report command for now: the client only needs the matched list as CSV". The next commit, 72ddd54, added 3 files under src/rules/. It was called "feat: matcher rewrite with explicit rules and a rules table".
  4. Six days away, then 12 files at once (stall)
     Nothing was committed for six days. Work restarted with 72ddd54 ("feat: matcher rewrite with explicit rules and a rules table"), touching 12 files and 444 lines. The next commit followed four days later.

The retry and the revert are patterns but not moments: the page tells stories about fixes after AI, direction changes and stalls, and the summaries mention the rest. madelog publish runs analyze and summarize itself, so this step is optional; running it first lets you read the result without the preview in the way.

The summaries

Without Ollama, or with llm.provider = none, the template writes them:

$ madelog summarize
week 1  2026-08-31 to 2026-09-06  (generated)  heuristic  01a0b382-67ed-7328-a588-dc65588b0c1e
In the week of 2026-08-31 you made 9 commits over 4 days. Most of the changes landed in src/main.rs, src/matcher.rs and Cargo.toml.

You wrote down 2 decisions: chose SQLite over Postgres: one binary, no service to run; dropped the report command for now: the client only needs the matched list as CSV.

week 2  2026-09-07 to 2026-09-13  (generated)  heuristic  01a0b382-67ed-7328-a588-dc66939bf940
In the week of 2026-09-07 you made 1 commit over 1 day. Most of the changes landed in README.md, src/import.rs and src/main.rs.

No decisions were written down that week, and the analysis found no patterns.

week 3  2026-09-14 to 2026-09-20  (generated)  heuristic  01a0b382-67ed-7328-a588-dc677b1e2c0f
In the week of 2026-09-14 you made 3 commits over 3 days. Most of the changes landed in src/export.rs, src/main.rs and README.md.

You wrote down 1 decision: kept the export in the same binary: a second tool means a second install for the client.

The analysis found 4 patterns that week: a fix after an AI session (d366a14 reworked AI-written code in src/import.rs two hours after fb7eeec); repeated attempts at the same files (Three commits in 50 minutes reworked the same file); a revert (Reverted 2 files changed in ea23143 one hour earlier); a stall (After six days without commits, 72ddd54 changed 12 files (444 lines)).

edit any of them with `madelog summary edit <id>`

The four patterns are listed under week 3 because madelog analyze ran in week 3; a pattern event carries the timestamp of the run that found it. Week 2's paragraph reads thin because one commit is all there was. This is the moment to rewrite what reads wrong, in your own words:

$ madelog summary edit 01a0b382-67ed-7328-a588-dc66939bf940

Your text replaces the template's on the page, with no "generated" marker.

Review and publish

madelog publish --local renders the page without sending anything. Open .madelog/site/index.html and read it as the company will: the headline, the four figures, the timeline, the moments, the attribution bar (81 AI-proposed lines of 746, 11 %), the "Not yet published" badge. If a session should not be there, hide it now:

$ madelog log --json | grep -B4 '"kind": "ai_session"' | grep '"id"'
    "id": "01a05d57-5a68-7075-b25a-15867fd58d96",
    "id": "01a0a9fb-1aa8-7e72-a32c-06e6ee576225",
$ madelog hide 01a0a9fb-1aa8-7e72-a32c-06e6ee576225
hidden. The session stays in the chain; the page will say one session is hidden.

Then publish. The preview opens first; Enter confirms it, q aborts and sends nothing.

$ madelog publish
...
page   /Users/ana/projects/ledger/.madelog/site/index.html
verify https://madelog-server-production.up.railway.app/v1/verify/north-fable-4xt3

published  https://madelog-server-production.up.railway.app/p/north-fable-4xt3
Send that link. `madelog unpublish` takes it down again.

Send the link. The company needs no account and no software; the page is one file that works with JavaScript off, and "Check the root" on the badge opens the server's record.

After sending

Keep working. Every commit is still recorded. When the project moves on, madelog publish again replaces the page at the same address with a new root, and the server keeps both roots in its history. When you want the page gone, madelog unpublish; when you want everything gone from your machine, rm -r .madelog and the two hook lines, as described under Uninstall.

What to do more of: write a note whenever you choose between two things. The notes are the only part of the record in your voice, they anchor two of the three kinds of moment, and the summaries quote them.