Skip to content

feat(opencode): timestamp gutter mode for messages#29398

Open
guysoft wants to merge 2 commits into
anomalyco:devfrom
guysoft:feat/tui-timestamp-gutter
Open

feat(opencode): timestamp gutter mode for messages#29398
guysoft wants to merge 2 commits into
anomalyco:devfrom
guysoft:feat/tui-timestamp-gutter

Conversation

@guysoft
Copy link
Copy Markdown

@guysoft guysoft commented May 26, 2026

Issue for this PR

Refs #29399. Addresses several open user requests:

Screenshot of feature showing the gutter timestamps:

image

popup window that was requested in #20406

image

Out of scope (different surfaces, separate PRs): #22037 desktop hover, #22144 tool block timestamps, #16341 session picker, #27962 desktop sidebar.

Type of change

  • New feature

What does this PR do?

Extends /timestamps to cycle three modes instead of two: hide → footer → gutter → hide. The new gutter mode renders a fixed 5-cell HH:MM column to the left of every message — user and assistant. Clicking the gutter opens a small popup with the full local datetime (HH:MM:SS) and a relative time ("3m ago"). Adds an optional tui.json key timestamps_mode (default "hide") that seeds the starting mode. Existing users with the legacy kv value "show" are mapped to "footer" at read time so their toggle keeps working.

Why it works:

  • The kv signal stays the source of truth in-session, so /timestamps still toggles immediately without writing to tui.json.
  • showTimestamps() (the existing alias used to gate the footer render) now returns true only for "footer" mode — gutter mode draws the time elsewhere, so there's no duplicate render.
  • For user messages, the gutter is a sibling of the bordered message box inside a flexDirection="row" wrapper, so its onMouseUp doesn't bubble into the row's existing click handler (which opens DialogMessage). The two interactions stay independent.
  • For assistant messages, the entire message body (parts For-loop, error block, footer) is wrapped in a flexDirection="row" with the gutter on the left only when timestamps_mode === "gutter"; non-gutter modes keep the existing fragment layout untouched, avoiding regression risk.
  • Visual alignment: user text lands at column 9 (gutter 6 + border 1 + paddingLeft 2), assistant text also lands at column 9 (gutter 6 + paddingLeft 3). Both columns align cleanly under the gutter.
  • 24-hour formatting via manual getHours()/getMinutes()/getSeconds() rather than toLocaleTimeString — keeps the gutter at exactly 5 cells regardless of locale, and side-steps the AM/PM bug reported in Timestamps always show AM/PM on Linux (Bun ignores system locale) #28804 for the new code paths.

Scope deliberately not in v1: mouse-only popup (keyboard support needs a selectedMessageID signal — follow-up).

How did you verify your code works?

  • bun turbo typecheck — clean across all 15 packages.
  • bunx oxlint on the changed files — no new warnings.
  • New tests in packages/opencode/test/cli/cmd/tui/timestamps.test.ts cover getTimestampsMode config resolution, nextTimestampsMode cycle order, normalizeTimestampsMode legacy "show" mapping, and both hourMinute / hourMinuteSecond 24-hour formatters. 14/14 pass; full TUI test directory 64/64 pass.
  • Built a darwin-arm64 binary via bun run script/build.ts --single --skip-embed-web-ui and ran it locally: cycled the three modes via /timestamps, confirmed gutter appears on both user and assistant messages, clicked both gutters to confirm the popup, restarted to confirm the kv signal persists and the config-seeded default applies on fresh state.

Screenshots / recordings

Will attach when I get them off the test machine.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

The /timestamps slash command now cycles hide → footer → gutter → hide.
Gutter mode renders a fixed 5-char HH:MM column to the left of each user
message; clicking the gutter opens a popup with the full local datetime.

Adds a new tui.json key `timestamps_mode` ("hide" | "footer" | "gutter",
default "hide") that seeds the default mode for new users. The kv signal
that backs the toggle was previously "hide" | "show"; "show" is mapped
to "footer" at read time so existing toggles keep working.
…opup

The gutter mode now renders an HH:MM column on assistant messages too,
not just user messages — closes the original ask in opencode#8634
("Add timestamp next to messages in chat (both agent and user messages)").
Assistant message body is wrapped in flexDirection="row" only when gutter
mode is active; non-gutter modes keep the existing fragment layout
untouched. Assistant text lands at column 9 (gutter 6 + paddingLeft 3),
which is also where user text lands (gutter 6 + border 1 + paddingLeft 2),
so the two sides align visually.

The timestamp popup now shows HH:MM:SS instead of HH:MM, addressing
opencode#20406 ("Add seconds to message timestamp display"). 24-hour
formatting is used consistently for both gutter and popup to avoid
opencode#28804 (Bun ignores system locale → spurious AM/PM on Linux).

Three new unit tests for hourMinuteSecond bring the suite to 14/14.
@guysoft
Copy link
Copy Markdown
Author

guysoft commented May 26, 2026

Pushed a follow-up commit (8e3981f) that broadens the scope to address more of the open user requests around message timestamps:

Visual alignment math: user text lands at col 9 (gutter 6 + border 1 + paddingLeft 2), assistant text also at col 9 (gutter 6 + paddingLeft 3). The two sides line up under a single virtual gutter, which is what makes it read as a "timeline column" rather than a per-message tag.

Tests now 14/14 (added 3 for hourMinuteSecond). Full TUI suite 64/64. Typecheck clean across all 15 packages.

Out of scope and deliberately left for follow-up PRs: #22037 (desktop hover), #22144 (tool block timestamps), #16341 (session picker), #27962 (desktop sidebar) — different surfaces.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant