I'm proud to present OhMyStash! OMS stores unfinished OhMyPi prompts without submitting them. It preserves normal and /queue drafts, images, collapsed large pastes, timestamps, source-chat metadata, locks, and a whole lot more!
I had a ton of fun making this, and I hope you find it just as useful as I do!
OMP's plugin manager uses Bun for package installation:
brew install bunInstall OhMyStash directly from GitHub:
omp plugin install github:hkay-dev/OhMyStashRestart OMP, then open the browser with Alt+Shift+S or /stash.
OhMyStash requires OMP 18.2.5 or newer. Its image attachment helper uses the TUI package's prompt/image-format export. Version 1.9.0 was loaded from an installed npm archive in compiled OMP 18.6.1; stash/restore, the browser, and the native plugin settings page were exercised. On macOS, 48 tests passed and 12 Windows-only tests were skipped. No model requests were made.
To update OhMyStash after a new release:
omp plugin install --force github:hkay-dev/OhMyStashCheck the installed package and extension manifest with:
omp plugin doctor @hkay-dev/ohmystashOMP uses the package ID @hkay-dev/ohmystash for plugin settings and diagnostics. Existing stash storage paths do not change.
Press Alt+S while the composer contains a prompt to stash it immediately. The composer clears so you can move to something else.
Press Alt+S on an empty composer to restore the newest stash from the current chat. The stash remains saved after restoration.
Press Alt+Shift+S to open the full stash browser. The browser supports preview, search, chat scope, queue actions, editing, locking, and deletion.
Considerable work went into the browser's visual hierarchy, color treatment, spacing, and keyboard flow.
The browser uses a centered overlay at 90% of terminal width, with square, accent-colored borders and an embedded title. Contextual Nerd Font glyphs honor Show icons without changing OMP's global symbol preset. Use a Nerd Font or symbols fallback to display them. This shared frame does not replace the browser's mature search, chat scope, queue, attachment, edit, lock, recovery, retention, or adaptive-layout behavior.
You can do quite a bit more in the browser:
- Chat scope. Open stashes from the current chat and press
gto switch to all chats. - Source metadata. Global entries show the source chat, workspace, timestamp, and short session ID.
- Search. Filter prompt text, chat names, workspaces, timestamps, queue mode, locks, and attachments.
- Queue draft. Press
qto place the selected stash in the composer as an editable/queuedraft. - Submit queue. Press
Shift+Qto prepend/queueand submit the selected stash while keeping the browser open for more. - Attachments. Restore images and collapsed large pastes with the prompt that owns them.
- Editing. Press
eto edit a stash with the configured editor or OMP's built-in editor. - Locking. Lock reusable stashes so deletion leaves them alone.
- Scoped deletion. Delete one unlocked stash or clear unlocked stashes from the current browser scope.
The browser starts on the current chat. Pressing g switches to all chats, back to the current chat, and back to all chats again.
Regular q comes first. It puts the stash into the composer as an editable /queue draft.
Shift+Q prepends /queue , submits the stash immediately, and keeps the browser open. Repeat it to stack messages in OMP's queue, then press Esc to exit.
Stash or clear any draft in the composer before restoring or submitting a saved prompt. This includes drafts that contain only images.
Search narrows the current scope as you type.
Images and large pasted bodies return with their stash.
Search for a stash, select it, and press e to edit it.
Locked stashes remain protected during bulk deletion.
| Action | Default control |
|---|---|
| Stash the composer, or restore the newest stash from this chat when empty | Alt+S |
| Open the stash browser | Alt+Shift+S |
| Open the browser from the composer | /stash |
| Restore the newest stash from this chat | /stash restore |
| Switch between This chat and All chats | g |
| Start fuzzy search | / |
| Keep the current filter selected | Tab |
| Restore the selected stash | Enter |
| Insert an editable queue draft | q |
Prepend /queue and submit the selected stash |
Shift+Q |
| Edit the selected stash | e |
| Lock or unlock the selected stash | l |
| Delete the selected unlocked stash | d or Delete |
| Delete every unlocked stash in the active scope | Shift+D |
| Scroll the preview | [ / ] |
| Clear search or close | Esc |
Open /settings, choose Plugins, select @hkay-dev/ohmystash, and press Enter.
Available settings:
- Stash shortcut and Browser shortcut, with
noneto disable either one - Editor command, blank to use
$VISUAL,$EDITOR, or OMP's built-in editor - Browser layout: Automatic, Side by side, Stacked, or Compact
- Maximum body rows
- Time format: 12-hour or 24-hour
- Retention days:
0keeps stashes indefinitely - Dim background
- Background brightness (%)
- Background saturation (%)
- Show icons, controlling contextual Nerd Font glyphs in the stash browser
Retention removes only expired, unlocked, normal stashes. Locked stashes, conflict copies, and recovery entries do not expire.
All the same settings are available from the CLI:
omp plugin config list @hkay-dev/ohmystash
omp plugin config set @hkay-dev/ohmystash "Browser layout" "Stacked"
omp plugin config set @hkay-dev/ohmystash "Retention days" 30
omp plugin config set @hkay-dev/ohmystash "Editor command" "code --wait"
omp plugin config set @hkay-dev/ohmystash "Dim background" false
omp plugin config delete @hkay-dev/ohmystash "Browser layout"OMS reloads plugin settings when a new OMP session starts.
I treated failed saves and missing stashes as bugs. OMS uses private atomic writes, file and directory fsync, attachment hashes, recoverable crash-window files, conflict copies, lock protection, and strict file checks.
The regression suite covers interrupted writes, concurrent saves and edits, corrupted attachments, symlinks, permissions, quota contention, recovery files, scoped deletion, source metadata, and retention.
I treated noticeable delay after a keypress as a bug. Safety checks stay enabled while OMS avoids repeated parsing, lowercasing, preview construction, attachment writes, and rendering work.
Representative medians:
| Operation | Median |
|---|---|
| Plain stash save | 0.249 ms |
| Warm load, 100 entries | 0.995 ms |
| Literal search | 0.00121 ms |
| Fuzzy search | 0.0824 ms |
| Unique 1 MiB attachment write | 1.036 ms |
| Verified 1 MiB attachment reuse | 0.901 ms |
| Verified 1 MiB attachment read | 0.372 ms |
| 1 MiB preview build | 1.315 ms |
| Preview-page extraction | 0.747 ms |
| 1,000 ANSI transformations | 0.226 ms |
Cross-chat benchmark medians:
| Operation | 50 stashes / 10 chats | 256 stashes / 16 chats |
|---|---|---|
| Cold load | 2.874 ms | 7.571 ms |
| Warm load | 0.763 ms | 4.150 ms |
| Scope toggle and render | 0.048 ms | 0.045 ms |
| Global literal search and render | 0.086 ms | 0.134 ms |
| Global fuzzy search and render | 0.631 ms | 3.570 ms |
| Split render | 0.016 ms | 0.025 ms |
| Stacked render | 0.015 ms | 0.018 ms |
| Compact render | 0.005 ms | 0.007 ms |
Stash files:
~/.omp/agent/prompt-stash/
Attachments:
~/.omp/agent/prompt-stash/attachments/
Limits:
- 1 MiB inline prompt text
- 64 MiB file-backed prompt body or individual attachment
- 128 MiB total attachments per stash
- 64 attachments per stash
- 2 MiB serialized stash metadata
- 256 normal active stashes
- 16 MiB normal metadata budget
Conflict copies and complete recovery files load outside the normal count and metadata caps. Attachments remain content-addressed for recovery and deduplication.
A separate filesystem backup is still required for hardware failure, filesystem corruption, or machine loss.
bun install
bun run check
bun test
bun run benchmark:cross-chatOhMyStash targets OMP 18.2.5 or newer. The extension entry point remains extensions/prompt-stash.ts.
Version 1.9.0 exports the common popup helpers at @hkay-dev/ohmystash/ui:
createFrame(theme, width)returns square, accent-coloredtop,row,divider, andbottomrenderers, with an embedded title and terminal-width-safe content.fitToWidth(text, width)clips and pads text to the requested visible terminal width, accounting for ANSI styling and wide characters.extensionIcon(key)reads the Nerd Font symbol preset and returns an empty string for an unknown key. It does not change the host symbol preset or read a plugin's Show icons setting; callers apply their own setting.selectOption(ctx, title, options, iconKey?)opens a searchable, keyboard-navigable option overlay and resolves to the selected string, orundefinedon cancellation, leaving the host composer and attachments untouched.POPUP_OPTIONSsuppliesoverlay: truewith a centered90%width and100%maximum height.
Extensions consuming this subpath must install @hkay-dev/ohmystash as a package dependency before registration. Copying a standalone extension file or linking extracted files without installing dependencies does not supply the shared module. Custom popups use the square frame; /settings → Plugins pages retain OMP's native settings chrome.
Use the existing settings capture to check a real package archive through the installed compiled OMP loader, not -e against this worktree. Review the installed version's contracts first. The recipe below targets OMP 18.6.0 using its tagged CLI, loader, installer, and root-path documentation. A newer source checkout is not matching-version evidence.
From this repository, with the existing capture dependencies available:
export OMS_CAPTURE_OUTPUT="$(mktemp -d "${TMPDIR:-/tmp}/ohmystash-proof.XXXXXX")"
artifact_name="$(npm pack --ignore-scripts --pack-destination "$OMS_CAPTURE_OUTPUT")"
export OMS_CAPTURE_ARTIFACT="$OMS_CAPTURE_OUTPUT/$artifact_name"
export OMS_CAPTURE_OMP="$(command -v omp)"
export OMS_CAPTURE_OMP_VERSION=18.6.0
npm exec -- tcut test showcase/ohmystash-settings.video.ts
npm run capture:settings
npm exec -- tcut doctor "$OMS_CAPTURE_OUTPUT/ohmystash-release.cast"
ffprobe -v error -show_entries format=duration,size -show_entries stream=codec_name,width,height,avg_frame_rate -of json "$OMS_CAPTURE_OUTPUT/ohmystash-release.mp4"npm pack above produces an archive of the current working tree without lifecycle scripts. For an approved release artifact, set OMS_CAPTURE_ARTIFACT to that archive instead. Record the authored revision/working-tree state separately from its SHA-256; a local pack is not publication evidence. The helper requires the exact expected version and a compiled executable, with no source-launcher fallback.
Before OMP can import any extension, the helper clears inherited profile/credential/session environment values and creates private HOME, agent, cwd, temporary and XDG roots. It writes reviewed startup/background-disable and display settings plus the catalog described below, never live config, models, auth or stashes. It installs the archive and exact matching-version SDK peers into a disposable consumer with Bun lifecycle scripts disabled, records peer versions, registers the installed package with isolated omp plugin link, and starts compiled OMP without -e or --no-extensions. Linking extracted bytes alone doesn't supply runtime dependencies such as pi-tui. Dependency installation may fetch public packages; no prompt is submitted.
Local commands still need a selected model. The fixture writes credential-free synthetic Flash catalog metadata with a reserved .invalid endpoint and selects only that entry. This allows local UI commands; it doesn't provide a backend or prove Gemini inference.
The captured sequence exercises Alt+S save/restore, Alt+Shift+S browser entry, Enter restore, one retained synthetic stash under the isolated agent root, and plugin settings visibility. Successful shutdown removes only that run's fixture. Failure leaves the private fixture for diagnosis. The JSON receipt is prepared until those consumer assertions and exit status 0 succeed, then consumer-exercised; it does not claim media acceptance. Inspect both PNGs, the GIF/MP4, and the complete raw cast/header, including hidden intervals and environment values, before accepting release evidence.
This is one-session PTY shortcut/TUI/storage evidence with the recorded dependency graph. It doesn't establish physical OS key delivery, queue dispatch or model inference, attachments, restart durability, registry publication or upgrades. Background discovery may contact public metadata endpoints; fresh roots aren't a network/OS sandbox.
The older browser showcase and capture:all use worktree/seeded fixtures, and their queue-submit scene can dispatch inference. They are not this packaged-release check or a no-credentials/offline recipe. Do not use them as installed-release evidence.
Terminal recordings were captured programmatically with tcut.









