# Prompt Trail

> For agents: start with the [agent guide](https://pi-tui.ratstack.sh/llms.txt). Every page here has a Markdown twin, and every pattern has a JSON record.

Behavioral / Editors and drafts · `prompt-trail` · [HTML](https://pi-tui.ratstack.sh/patterns/prompt-trail/) · [JSON](https://pi-tui.ratstack.sh/patterns/prompt-trail.json) · [all patterns](https://pi-tui.ratstack.sh/patterns.md)

Also known as Prompt history.

## Intent

Browse submitted prompts while retaining the current editor draft.

## Motivation

Nico's editor history lets users revisit prompts without losing the current draft.

## Applicability

- Use this when previous prompts should be reusable inside the editor.

## Structure

```text
draft -> previous prompts
next through history -> draft
```

## Participants

- [`Editor`](https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#compose-built-in-components): Owns multi-line editing, autocomplete and history.
- [`Editor.addToHistory`](https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/keybindings.md#cursor-movement): Adds submitted text to editor history.
- `Current draft`: Returns when forward history browsing ends.

Pi component APIs: [`Editor`](https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#compose-built-in-components), [`Editor.addToHistory`](https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/keybindings.md#cursor-movement), `Focusable`

## Consequences

- Earlier submissions remain reachable inside the editor.
- Arrow history depends on cursor boundaries unless dedicated actions are used.

## Implementation

- Boundary arrow navigation differs from interior cursor movement.
- Dedicated history actions do not require a cursor boundary.

## States

Each state was rendered at 40, 60, 80 and 120 columns in Pi's dark and light themes. Each frame links one WebP. An animated frame links its first image, then the animation.

### Current draft

`draft`: Show a synthetic draft with two saved prompts.

Checks at every width and theme:

- width: ✓ pass
- style-leak: ✓ pass
- hard-coded-colour: ✓ pass
- height: ✓ pass

Frames:

- 40 columns: ![Prompt Trail, Current draft, 40 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/draft-40-dark.a43a0222b960.webp) ![Prompt Trail, Current draft, 40 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/draft-40-light.1daf84287d06.webp)
- 60 columns: ![Prompt Trail, Current draft, 60 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/draft-60-dark.d4b30985b790.webp) ![Prompt Trail, Current draft, 60 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/draft-60-light.3cdfe13862c3.webp)
- 80 columns: ![Prompt Trail, Current draft, 80 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/draft-80-dark.a526e2a748b9.webp) ![Prompt Trail, Current draft, 80 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/draft-80-light.720a057bf217.webp)
- 120 columns: ![Prompt Trail, Current draft, 120 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/draft-120-dark.3ace6ccee306.webp) ![Prompt Trail, Current draft, 120 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/draft-120-light.8a86da5d90a3.webp)

### Previous prompt

`previous`: Navigate history at an editor boundary.

Checks at every width and theme:

- width: ✓ pass
- style-leak: ✓ pass
- hard-coded-colour: ✓ pass
- height: ✓ pass

Frames:

- 40 columns: ![Prompt Trail, Previous prompt, 40 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/previous-40-dark.25686fc7a7c8.webp) ![Prompt Trail, Previous prompt, 40 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/previous-40-light.58d214f5ac8d.webp)
- 60 columns: ![Prompt Trail, Previous prompt, 60 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/previous-60-dark.70d792f933e4.webp) ![Prompt Trail, Previous prompt, 60 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/previous-60-light.99125ff0ae8b.webp)
- 80 columns: ![Prompt Trail, Previous prompt, 80 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/previous-80-dark.9f6b015902a7.webp) ![Prompt Trail, Previous prompt, 80 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/previous-80-light.3c41c3dc9fdc.webp)
- 120 columns: ![Prompt Trail, Previous prompt, 120 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/previous-120-dark.0049a6fc2b94.webp) ![Prompt Trail, Previous prompt, 120 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/previous-120-light.1c95b88c89f6.webp)

### Draft retained

`returned`: Browse forward until the current draft returns.

Checks at every width and theme:

- width: ✓ pass
- style-leak: ✓ pass
- hard-coded-colour: ✓ pass
- height: ✓ pass

Frames:

- 40 columns: ![Prompt Trail, Draft retained, 40 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/returned-40-dark.a43a0222b960.webp) ![Prompt Trail, Draft retained, 40 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/returned-40-light.1daf84287d06.webp)
- 60 columns: ![Prompt Trail, Draft retained, 60 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/returned-60-dark.d4b30985b790.webp) ![Prompt Trail, Draft retained, 60 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/returned-60-light.3cdfe13862c3.webp)
- 80 columns: ![Prompt Trail, Draft retained, 80 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/returned-80-dark.a526e2a748b9.webp) ![Prompt Trail, Draft retained, 80 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/returned-80-light.720a057bf217.webp)
- 120 columns: ![Prompt Trail, Draft retained, 120 columns, dark theme](https://pi-tui.ratstack.sh/frames/prompt-trail/returned-120-dark.3ace6ccee306.webp) ![Prompt Trail, Draft retained, 120 columns, light theme](https://pi-tui.ratstack.sh/frames/prompt-trail/returned-120-light.8a86da5d90a3.webp)

## Sample code

`stories/patterns/behavioral/prompt-trail.ts`, the story the frames above were rendered from.

```ts
// Prompt Trail: browse real Editor history without overwriting the current draft.
import { Editor, truncateToWidth, type Component, type Focusable } from "@earendil-works/pi-tui";
import { getSelectListTheme } from "@earendil-works/pi-coding-agent";
import type { PatternStory } from "../../../src/pattern.ts";

export const story: PatternStory = {
  id: "prompt-trail",
  title: "Prompt Trail",
  kind: "component",
  apis: ["Editor", "Editor.addToHistory", "Focusable"],
  rows: 10,
  states: [
    { id: "draft", label: "Current draft" },
    { id: "previous", label: "Previous prompt", steps: [
      { type: "keys", data: "\x1b[A" }, { type: "keys", data: "\x1b[A" },
    ] },
    { id: "returned", label: "Draft retained", steps: [
      { type: "keys", data: "\x1b[B" }, { type: "keys", data: "\x1b[B" },
    ] },
  ],
  setup({ theme, tui }) {
    const currentDraft = "Check the parser edge cases";
    const prompts = ["Map the parser entry points", "Write the token boundary tests"];
    const editor = new Editor(tui, {
      borderColor: text => theme.fg("border", text),
      selectList: getSelectListTheme(),
    }, { paddingX: 1 });
    for (const prompt of prompts) editor.addToHistory(prompt);
    editor.setText(currentDraft);
    class HistoryView implements Component, Focusable {
      get focused() { return editor.focused; }
      set focused(value: boolean) { editor.focused = value; }
      invalidate() { editor.invalidate(); }
      handleInput(data: string) { editor.handleInput(data); tui.requestRender(); }
      render(width: number) {
        return [
          theme.fg("accent", "Prompt Trail · two saved prompts"),
          theme.fg("muted", truncateToWidth("1 · " + prompts[0], width)),
          theme.fg("muted", truncateToWidth("2 · " + prompts[1], width)),
          theme.fg(editor.getText() === currentDraft ? "success" : "accent",
            editor.getText() === currentDraft ? "Current draft · retained" : "Browsing saved history"),
          ...editor.render(width),
          theme.fg("muted", truncateToWidth("↑ older at top · ↓ newer at bottom", width)),
        ];
      }
    }
    return new HistoryView();
  },
};
```

## Known uses: seen in Nico's repos

- [**earendil-works/pi**](https://github.com/earendil-works/pi): Navigate submitted prompts from the editor
  - [packages/tui/src/components/editor.ts:51-116](https://github.com/earendil-works/pi/blob/c550ed2bcab8db29fd70e2096a390cf80d69cd91/packages/tui/src/components/editor.ts#L51-L116) @c550ed2b
  - [packages/tui/src/components/editor.ts:451-465](https://github.com/earendil-works/pi/blob/c550ed2bcab8db29fd70e2096a390cf80d69cd91/packages/tui/src/components/editor.ts#L451-L465) @c550ed2b

## For agents: choose and check

Choose Prompt Trail when your job matches its intent and applicability above. Its neighbours in Editors and drafts are listed below. Read the one whose intent fits your job more closely before you commit.

- [Editor Steward](https://pi-tui.ratstack.sh/patterns/editor-steward.md): Compose editor enhancements behind one replacement factory.
- [Retry Buffer](https://pi-tui.ratstack.sh/patterns/retry-buffer.md): Keep the local draft editable after a failed send.
- [Draft Fence](https://pi-tui.ratstack.sh/patterns/draft-fence.md): Keep inline draft edits separate from the committed queue snapshot.
- [Draft Return](https://pi-tui.ratstack.sh/patterns/draft-return.md): Restore the captured editor draft after a temporary submission.

Check your version:

- Render your version at 40, 60, 80 and 120 columns in the dark and light themes.
- Check width: no rendered line is wider than the terminal.
- Check style-leak: no line ends with colour, bold or a link still switched on.
- Check hard-coded-colour: every colour on screen comes from the active theme.
- Check height: the output fits in the rows the terminal has.
- Read the Pi 1.0.3 docs for [`Editor`](https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#compose-built-in-components), [`Editor.addToHistory`](https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/keybindings.md#cursor-movement), `Focusable` before you use them.
- Every reference frame gets the verdict its state expects.

Next actions: `related({ id: "prompt-trail" })` lists what to read next, and `states({ id: "prompt-trail", width: 40 })` returns every frame and verdict at one width. The [build-pi-tui-component skill](https://pi-tui.ratstack.sh/skills/build-pi-tui-component.md) walks through the whole loop.

## Related

- [Editor Steward](https://pi-tui.ratstack.sh/patterns/editor-steward.md): preserves the base editor history

## Linked from

No other pattern links here.
