SLOPSHOPPER

last-answer

A side pane showing the agent's previous final answers, without reasoning or tool calls

newpanecommand
v0.1.0no licenseupdated 2026-10-15eduojeda/claude-last-answer
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · last-answer
│ ┃ Previous answer ✕ › fix the failing auth test and add an audit log call │ ┃ 1 of 1 │ ┃ Done. I made refresh reject expired claims, ⏺ Read(src/auth.ts) │ ┃ added an audit call, and created ⎿ Read 6 lines │ ┃ src/audit.ts. One test still fails (revokes ⏺ Update(src/auth.ts) │ ┃ on logout), which looks unrelated to this ⎿ Added 2 lines, removed 1 line │ ┃ change. ⏺ Bash(bun test) │ ⎿ 3 pass, 1 fail │ │ ● Done. refresh now rejects expired claims and logs an audit event. │ │ ✻ Worked for 42s · done 4:20 PM │ │ › /last │ ⎿ last-answer: Previous answer pane opened. │ │ ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts

Draws

Pane · Previous answer
1 of 1 Done. I made refresh reject expired claims, added an audit call, and created src/audit.ts. One test still fails (revokes on logout), which looks unrelated to this change.
README

last-answer

A Claude Code mod that keeps the agent's final answers in a side pane, so you can re-read the previous turn's answer without scrolling back past reasoning and tool calls.

  • /last opens or closes the pane.
  • The pane shows the most recent finished answer. While a new turn runs, that is the previous turn's answer.
  • ◀ older / newer ▶ (hotkeys o / n while the pane has the keyboard) step through the last 20 answers of the session.
  • Subagent reports and empty answers are skipped.

Install

At the prompt of a Claude Code terminal session:

/plugin install last-answer --marketplace eduojeda/claude-last-answer

Answer y to add the marketplace, then pick a scope.

Development

claude plugin validate .
claude plugin test .
Source 2 files
hooks/register.tsx 75 lines
1import { atom, read, update } from 'claude-code'
2import type { Register } from 'claude-code'
3
4const PANE = 'last-answer'
5const KEEP = 20
6// Newest last. `offset` counts back from the newest: 0 shows the newest.
7const answers = atom({ plugin: 'last-answer', key: 'answers' } as const, [])
8const offset = atom({ plugin: 'last-answer', key: 'offset' } as const, 0)
9
10export const register: Register = on => {
11  on('session.start', async ($, e, next) => {
12    await $.command.register({
13      name: 'last',
14      description: "Open or close the pane with the agent's previous answers",
15    })
16
17    return next(e)
18  })
19
20  on('command.run', { command: 'last' }, async $ => {
21    const isOpen = (await $.ui.panes()).some(pane => pane.id === PANE)
22    if (isOpen) {
23      await $.ui.close({ id: PANE })
24      return { text: 'Previous answer pane closed.' }
25    }
26    await $.ui.open({ id: PANE, title: 'Previous answer' })
27    return { text: 'Previous answer pane opened.' }
28  })
29
30  on('turn.complete', async ($, e, next) => {
31    if (e.agentId === undefined && e.answer.trim() !== '') {
32      await update($, answers, list => [...list, e.answer].slice(-KEEP))
33      await update($, offset, () => 0)
34    }
35
36    return next(e)
37  })
38
39  on('ui.render', { component: 'Pane', requestId: PANE }, async ($, e) => {
40    const { Box, Text, Button, Markdown } = $.ui.resolve(e)
41    const list = await read($, answers)
42    if (list.length === 0) {
43      return <Text dimColor>No answers yet this session.</Text>
44    }
45
46    const back = Math.min(await read($, offset), list.length - 1)
47    const position = list.length - back
48
49    return (
50      <Box flexDirection="column">
51        <Box>
52          <Text dimColor>{`${position} of ${list.length} `}</Text>
53          {back < list.length - 1 && (
54            <Button
55              key="older"
56              label="◀ older"
57              hotkey="o"
58              onPress={() => update($, offset, n => n + 1)}
59            />
60          )}
61          {back > 0 && (
62            <Button
63              key="newer"
64              label="newer ▶"
65              hotkey="n"
66              onPress={() => update($, offset, n => n - 1)}
67            />
68          )}
69        </Box>
70        <Markdown key="answer" text={list[list.length - 1 - back] ?? ''} />
71      </Box>
72    )
73  })
74}
75
types/index.d.ts 8 lines
1export type Answer = string
2
3declare module 'claude-code' {
4  interface PluginState {
5    'last-answer': { answers: Answer[]; offset: number }
6  }
7}
8