Skip to content

annotate-last: picks wrong message after /rewind; consider a message-picker UI #800

@GLips

Description

@GLips

Problem

plannotator last (and the /plannotator-last slash command) selects the last assistant text block by position in the session transcript. When the conversation has been rewound—e.g. the user ran /rewind in Claude Code—the message displayed at the bottom of the chat from the user's perspective is not the same as what's newest in the harness's on-disk transcript, which still contains the orphaned pre-rewind messages.

The result is that Plannotator opens on a message the user intended to backtrack on and there's no affordance to correct this.

This is similar to #739 in that the wrong message is selected, but the rewind case isn't covered by that fix and there's no existing issue tracking it.

Repro (Claude Code)

  1. Have a multi-turn conversation.
  2. /rewind back one or more assistant responses.
  3. Run /plannotator-last.
  4. Plannotator opens on the most recent transcript entry, which after a rewind is not the message the user likely intends to annotate.

Why it happens

Per the annotate-last docs, all four supported harnesses (Claude Code, OpenCode, Pi, Codex) select "the last assistant text block(s)" from the session, with filtering for system/noise entries but no awareness of conversation-mutation commands like /rewind or /clear. The current input contract has no flag for "which message" — only --gate, --json, --hook.

Proposed fix

Show a dropdown or numbered list in the Plannotator last UI with recent assistant messages, ordered newest first, defaulting to the current "last" selection. The user picks which one to annotate. Each entry shows a short preview (first few dozen chars + timestamp, perhaps) so it's easy to find the intended message.

This is a strict improvement over the current behavior:

  • Solves the rewind case naturally — the user just picks the message they actually see in their terminal.
  • Provides general affordance to annotate any earlier message without manual transcript hunting.
  • Backwards-compatible: if the user doesn't interact with the picker, the default selection matches today's behavior.

All four supported harnesses already expose ordered message lists (jsonl files for Claude Code/Codex, SDK calls for OpenCode/Pi), so the picker data source is available without per-harness work beyond message extraction (which already exists).

Optional companion: a --index N or --message-id <id> flag for scripted/hooked use cases — useful if annotate-last is ever wired into automation.

Contributing

Happy to send a PR if you agree the picker UI is the right direction. Wanted to check first since you are likely inundated with slop PRs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions