Conversation history
Every chat message in a card's modal is persisted. This page explains where it lives, what's kept, and what's not.
Storage
Conversations are stored in the local SQLite database, in a conversations table. Columns:
| Column | What it is |
|---|---|
id | Message UUID |
cardId | Which card the message belongs to |
sectionType | detail / opinion / solution / tests — which tab's chat it belongs to |
role | user / assistant |
content | The rendered message text (HTML) |
mentions | JSON array of @skill / @mcp / @card / @document mentions used in the message |
toolCalls | JSON array of MCP tool calls the agent made during this turn |
createdAt | ISO timestamp |
A separate chatSessions table maps (cardId, sectionType) to a CLI session ID so you can resume a chat instead of starting a new one every time.
Per-section scoping
The thread you see when you open the Detail tab is not the same thread as Opinion, Solution, or Tests. Each tab has its own independent conversation history. This is deliberate:
- It keeps context small — the agent doesn't re-read the plan discussion when you're in the tests tab
- It lets you hold four parallel conversations about the same card without noise
- It matches the mental model: "talk about what's on screen"
If you want a conversation that spans sections, put it in Detail. Detail is the default/overview tab, and the agent will pick up the other sections naturally as it reads the card.
What's kept
- Every user and assistant message, indefinitely
- Full
mentionsandtoolCallsJSON alongside each message - Tool inputs and outputs — so you can audit what an agent did on a card after the fact
Conversations are never auto-cleared or compressed. They grow. For most users this is fine (cards have bounded lifespans), but if a specific card gets a hundred messages across months, the database grows accordingly.
What's not synced
In the Team edition, the local database syncs to Supabase for pool collaboration — but conversations are not part of the sync. Your chat history stays on your machine. A teammate pulling the same card from the pool gets the card state (plan, tests, opinion) but not the thread you had with the agent while writing them.
This is intentional. Conversations are often long, verbose, and personal to the writer. Syncing them would blow up payloads for no shared benefit.
If you need to hand off the thinking, copy the relevant messages into the card body — or use save_plan / save_tests / save_opinion to capture the conclusions in structured form. That's the whole point of those tools.
Accessing conversations outside the modal
There's an API: GET /api/cards/[id]/conversations returns the full thread for a card (all sections). You can use it for:
- Export before deleting a card
- Bulk analysis of which tools got called most on which cards
- Building a custom dashboard on top of local state
There's no built-in export button in the UI today. If you need one, open an issue or build it against the API.
Pruning by hand
If you do need to prune, the conversations table is just SQLite. Open the database, delete rows where createdAt is older than some cutoff, and the next time you open the card the history starts from whatever's left. Don't do this while the app is running — take a backup first.
Prev: Interactive CLI sessions Next: Prompting patterns Up: User guide index