# refactor\(web\): the prompt stash lives in useComposerStash · PR \#23046 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/23046)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: refactor/split2-composer-stash

Target branch: refactor/split2-composer-layout-hooks

Head commit: 25fa572eba1b8a200711bee4bb5b3acc7e39e5c0

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/23046)

[Commits](https://git.cafe/pingdotgg/t3code/pull/23046/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/23046/diffs?format=markdown)

## Description

---

Stashing, restoring and deleting prompts took about 550 lines of the composer body. Its state was declared hundreds of lines away from the code that used it.

`useComposerStash` now owns all of it:

- the stash menu open state
- the badge pulse, plus the timer and in-flight refs behind it
- the stash store selectors
- `stashCurrentPrompt`, `restoreStashEntry` and `deleteStashEntry`
- `toggleStashMenu`
- closing the menu when the prompt changes
- the `composer.stash` shortcut listener

The hook reads the draft-store setters it needs itself and takes the composer values it reads as one input object. It returns what the badge and menu render.

The hook is called where the stash code used to start, so the order of the composer's other effects is unchanged. The stash shortcut listener now registers ahead of a few layout effects in between, none of which listen for keydown. The existing `useStableCallback` wrappers moved with the code. This PR adds none.

| File | before | after |
| --- | --- | --- |
| ChatComposer.tsx | 5,434 | 4,860 |
| useComposerStash.ts | | 745 |

Renders are unchanged. With Claude selected, typing 20 chars is 224 renders before and after.

Tested:
- apps/web typecheck and lint on the touched files.
- React Compiler: 0 bailouts on both files.
- Hands-on in a dev build. Ctrl+S stashes the prompt, clears the composer and shows the badge. The badge opens the menu. Restore puts the prompt back. Delete removes the entry and the badge.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

