Summary
The current chat format is flat markdown with line-number-based cursors. This is brittle — editing a message shifts every cursor pointing past it, and there's no way to address individual messages or attach per-message metadata.
Proposed Format
Each message becomes its own "document" within the file, with YAML frontmatter and a markdown body, separated by ---:
---
id: 1
from: baby-joel
ts: 2026-03-25T12:05:00
---
UX test session — participants: baby-joel, or.
---
id: 2
from: or
ts: 2026-03-25T12:06:00
to: baby-joel
---
Or here, reading you loud and clear.
Cursor Change
Cursors would store a message index (e.g., 3 = "read through message 3") instead of a line number. This makes cursors stable regardless of message body length or edits.
Benefits
- Stable cursors — editing a message body doesn't invalidate anyone's cursor
- Message IDs — can address, reference, or thread individual messages
- Per-message metadata —
from, to, ts, id, and extensible for future fields
- Still human-readable —
cat still produces readable output, just with --- separators
- Resolves --force cursor bug — the current
send --force advances the cursor past unread messages the sender never saw (see related: send should not advance cursor)
Scope
This touches all tasks: send, read, wait, status, list, clear, cursor:clear, plus the full test suite (134 tests). It's a significant migration but the format is a better foundation for everything else we want to build.
Context
Discussed during UX testing session (2026-03-25) between Or and Baby Joel. Agreed to do this after fixing the immediate --force cursor bug.
Summary
The current chat format is flat markdown with line-number-based cursors. This is brittle — editing a message shifts every cursor pointing past it, and there's no way to address individual messages or attach per-message metadata.
Proposed Format
Each message becomes its own "document" within the file, with YAML frontmatter and a markdown body, separated by
---:Cursor Change
Cursors would store a message index (e.g.,
3= "read through message 3") instead of a line number. This makes cursors stable regardless of message body length or edits.Benefits
from,to,ts,id, and extensible for future fieldscatstill produces readable output, just with---separatorssend --forceadvances the cursor past unread messages the sender never saw (see related: send should not advance cursor)Scope
This touches all tasks:
send,read,wait,status,list,clear,cursor:clear, plus the full test suite (134 tests). It's a significant migration but the format is a better foundation for everything else we want to build.Context
Discussed during UX testing session (2026-03-25) between Or and Baby Joel. Agreed to do this after fixing the immediate
--forcecursor bug.