Three changes from comparing the UI against Raycast's AI chat.
1. Transcript reads newest message first
An answer now sits above the question it responds to. The search bar is pinned to the top of the window, so the most recent thing belongs directly under it rather than below the fold.
buildThreadMarkdown regroups messages back into exchanges, so the horizontal rule separates one exchange from the next instead of dividing every single message:
Lam Today is Sunday, October 4, 2026 (5:08 AM, Asia/Manila, GMT+8)
Tools used: get_datetime · Reasoning: Need current date...
You What day is it today
─────────────────────────────────────────────────
Lam Running fine — ready when you are...
You how are you today?
2. Sidebar is titles only, grouped by recency
This fixes the row that elided down to Hello l.... A subtitle and a timestamp on a 38px row left the title almost no width. Raycast's sidebar works the same way — title only, grouped under Today / Yesterday / This week / Older. The check icon is what marks the open conversation now.
3. The status bar names the open conversation
Vicinae's nearest equivalent to the header Raycast puts above its transcript.
Dead code removed
ThreadMessage.preview was no longer read by anything once the rows became conversations. Rather than delete the plumbing outright, the activity line it carried ("Searching the web") moved into the transcript placeholder and the search bar — tool activity is still visible, it just is not a per-row preview any more.
Verification
tsc --noEmit clean, eslint . clean
113 tests passing (was 112)
vici build succeeds
Verified on screen: answer above question, one rule per exchange, a single Today section with a title-only row, status bar naming the conversation
Three changes from comparing the UI against Raycast's AI chat.
## 1. Transcript reads newest message first
An answer now sits **above** the question it responds to. The search bar is pinned to the top of the window, so the most recent thing belongs directly under it rather than below the fold.
`buildThreadMarkdown` regroups messages back into exchanges, so the horizontal rule separates one exchange from the next instead of dividing every single message:
```
Lam Today is Sunday, October 4, 2026 (5:08 AM, Asia/Manila, GMT+8)
Tools used: get_datetime · Reasoning: Need current date...
You What day is it today
─────────────────────────────────────────────────
Lam Running fine — ready when you are...
You how are you today?
```
## 2. Sidebar is titles only, grouped by recency
This fixes the row that elided down to `Hello l...`. A subtitle *and* a timestamp on a 38px row left the title almost no width. Raycast's sidebar works the same way — title only, grouped under `Today` / `Yesterday` / `This week` / `Older`. The check icon is what marks the open conversation now.
## 3. The status bar names the open conversation
Vicinae's nearest equivalent to the header Raycast puts above its transcript.
## Dead code removed
`ThreadMessage.preview` was no longer read by anything once the rows became conversations. Rather than delete the plumbing outright, the activity line it carried (`"Searching the web"`) moved into the transcript placeholder and the search bar — tool activity is still visible, it just is not a per-row preview any more.
## Verification
- `tsc --noEmit` clean, `eslint .` clean
- **113 tests passing** (was 112)
- `vici build` succeeds
- Verified on screen: answer above question, one rule per exchange, a single `Today` section with a title-only row, status bar naming the conversation
Three changes from comparing against Raycast's AI chat.
1. The transcript now reads newest message first, so an answer sits above
the question it responds to. The search bar is pinned to the top of
the window, so the most recent thing belongs directly under it rather
than below the fold. buildThreadMarkdown regroups messages back into
exchanges, so the horizontal rule separates one exchange from the next
instead of dividing every single message.
2. The sidebar is titles only, grouped into recency sections (Today,
Yesterday, This week, Older). Raycast does this, and it fixes rows
eliding down to "Hello l..." -- a subtitle and a timestamp on a 38px
row left the title almost no width. The check icon is what marks the
open conversation now.
3. The status bar names the open conversation, which is the nearest thing
Vicinae has to the header Raycast puts above its transcript.
Also removes dead code found on the way: ThreadMessage.preview was no
longer read by anything once the rows became conversations. Rather than
delete the plumbing outright, the activity line it carried ("Searching
the web") moved into the transcript placeholder and the search bar, so
tool activity is still visible -- it just is not a per-row preview any
more.
Verified on screen: answer above question, one rule per exchange, the
sidebar showing a single "Today" section with a title-only row, and the
status bar naming the conversation. typecheck, eslint, 113 tests and
vici build all pass.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Three changes from comparing the UI against Raycast's AI chat.
1. Transcript reads newest message first
An answer now sits above the question it responds to. The search bar is pinned to the top of the window, so the most recent thing belongs directly under it rather than below the fold.
buildThreadMarkdownregroups messages back into exchanges, so the horizontal rule separates one exchange from the next instead of dividing every single message:2. Sidebar is titles only, grouped by recency
This fixes the row that elided down to
Hello l.... A subtitle and a timestamp on a 38px row left the title almost no width. Raycast's sidebar works the same way — title only, grouped underToday/Yesterday/This week/Older. The check icon is what marks the open conversation now.3. The status bar names the open conversation
Vicinae's nearest equivalent to the header Raycast puts above its transcript.
Dead code removed
ThreadMessage.previewwas no longer read by anything once the rows became conversations. Rather than delete the plumbing outright, the activity line it carried ("Searching the web") moved into the transcript placeholder and the search bar — tool activity is still visible, it just is not a per-row preview any more.Verification
tsc --noEmitclean,eslint .cleanvici buildsucceedsTodaysection with a title-only row, status bar naming the conversationThree changes from comparing against Raycast's AI chat. 1. The transcript now reads newest message first, so an answer sits above the question it responds to. The search bar is pinned to the top of the window, so the most recent thing belongs directly under it rather than below the fold. buildThreadMarkdown regroups messages back into exchanges, so the horizontal rule separates one exchange from the next instead of dividing every single message. 2. The sidebar is titles only, grouped into recency sections (Today, Yesterday, This week, Older). Raycast does this, and it fixes rows eliding down to "Hello l..." -- a subtitle and a timestamp on a 38px row left the title almost no width. The check icon is what marks the open conversation now. 3. The status bar names the open conversation, which is the nearest thing Vicinae has to the header Raycast puts above its transcript. Also removes dead code found on the way: ThreadMessage.preview was no longer read by anything once the rows became conversations. Rather than delete the plumbing outright, the activity line it carried ("Searching the web") moved into the transcript placeholder and the search bar, so tool activity is still visible -- it just is not a per-row preview any more. Verified on screen: answer above question, one rule per exchange, the sidebar showing a single "Today" section with a title-only row, and the status bar naming the conversation. typecheck, eslint, 113 tests and vici build all pass.