pi-copy-message4.0.0
Pi extension with a searchable TUI picker for copying raw session messages
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi copy-message extension
A pi extension that adds /copy-message: a keyboard-first picker for copying raw session message text without terminal wrapping, padding, or rendered TUI artifacts. It also adds /copy-user as a direct shortcut for the most recent user message.
pi-copy-message supersedes pi-copy-user-message, which only copied the most recent user message.
What it does
- Adds
/copy-message - Adds
/copy-userfor copying the most recent user message directly - Copies raw stored session message text, not rendered terminal lines
- Shows messages in chat order: oldest at top, newest at bottom
- Selects the newest visible message by default
- Supports role filters for user, assistant, tool/bash, and custom messages
- Hides tool/bash messages by default
- Supports type-to-filter search across role and message text, with
time:<term>for timestamp search - Supports Home/End jumps for oldest/newest visible messages
- Uses Pi's configured selection bindings for navigation, copy, and cancel
- Keeps Pi's platform clipboard writes and OSC 52 fallback, but reports success only after local text readback
- Includes fast paths:
/copy-message latest,/copy-message last, and/copy-message newest, using Pi's canonical active context - Supports direct numbered copies like
/copy-message 3 - Supports metadata copies with
--with-meta,--with-metadata, or--with-role
Install
Install it from npm with pi:
pi install npm:pi-copy-message
Or install it directly from GitHub with pi:
pi install https://github.com/fitchmultz/pi-copy-message
Use /reload after updating extension code on current official Pi and the maintained fork. Restart Pi after changing dependencies or the host runtime.
If you prefer to load it directly from a local checkout during development:
pi -e ./extensions/copy-message.ts
Usage
Open the picker:
/copy-message
Copy the most recent user message directly:
/copy-user
Copy the latest visible default message directly:
/copy-message latest
Aliases:
/copy-message last
/copy-message newest
Copy the 3rd default-visible message directly, matching the picker's 1-based oldest-to-newest numbering:
/copy-message 3
Copy with role and timestamp metadata instead of raw text only:
/copy-message latest --with-meta
/copy-message 3 --with-role
/copy-user --with-meta
Keyboard controls
| Key | Action |
|---|---|
Configured tui.select.up (default: ↑) |
Move to older visible message |
Configured tui.select.down (default: ↓) |
Move to newer visible message |
Configured tui.select.pageUp / tui.select.pageDown (default: PageUp / PageDown) |
Move by one visible page in regular mode |
Ctrl+PageUp / Ctrl+PageDown |
Move by one visible page in fullscreen mode |
Home / End |
Jump to oldest/newest visible message in regular mode |
Ctrl+Home / Ctrl+End |
Jump to oldest/newest visible message in fullscreen mode |
| Type or paste text | Filter visible messages; pasted line breaks and tabs become spaces |
time:<term> |
Search timestamps |
Backspace |
Delete one search character |
Ctrl+U |
Toggle user messages |
Ctrl+A |
Toggle assistant messages |
Ctrl+T |
Toggle tool/bash messages |
Alt+C |
Toggle custom messages |
Tab |
Toggle a wrapped preview of the selected message |
Alt+M |
Toggle raw vs metadata copy format |
Configured tui.select.confirm (default: Enter) |
Copy selected message text |
Configured tui.select.cancel (default: Esc/Ctrl+C) |
Cancel |
Behavior notes
- Entry IDs are hidden from the picker.
- Mouse wheel navigates; clicking a message copies it and returns keyboard focus to the unchanged draft.
- Session replacement, tree navigation, shutdown and reload cancel pending pickers without stale-context notifications.
- The picker caps visible rows and scrolls instead of filling the screen.
- Search preserves your original selected message and restores it when the search is cleared.
- General search does not match timestamps; use
time:<term>when you want to search by displayed time. - Picker previews and copy notifications remove terminal control characters; the copied text stays raw.
- Filter labels honor the active pi theme.
- Selection key hints show the active Pi bindings. Configured selection actions take precedence if they collide with the picker's filter, preview, or format shortcuts.
- Only custom messages with
display: truecan appear or be copied from currentcustom_messageentries or legacy message-wrapped entries; visible ones can be toggled withAlt+C. - A verified local copy notification includes the role and a short preview. Unavailable, empty or mismatched readback warns instead of claiming success; rejected writes report an error. Remote terminal delivery via OSC 52 cannot be verified, even when the remote machine's local clipboard matches.
- Native clipboard reads are preferred where available. Bounded platform readers preserve exact text, including newlines; the extension never replaces Pi's working write fallback chain.
latestuses Pi's canonical session projection, honoring context edits, omissions and compaction. Numbered selectors, the picker and/copy-userretain raw active-branch history, including older pre-compaction messages./copy-message latestand numbered selectors include user, assistant, and visible custom messages by default while hiding tool/bash messages.Alt+Conly affects the picker. If only hidden messages exist,latestfalls back to the newest message so the command still does something useful./copy-messagewith no direct selector requires interactive TUI mode because the picker is a custom TUI component.- Direct commands such as
/copy-user,/copy-message latest, and/copy-message 3do not require TUI mode, though non-UI modes may not display notifications.
Compatibility
- Requires Pi 1.0.0 or later. Development and standalone/packed qualification use the official 1.0.0 cohort; a maintained fork must be qualified at its actual supported revision, not by version-string equivalence.
- The picker coalesces legacy in-progress assistant snapshots within their context-window boundaries so each response appears once. Current official Pi and the maintained fork no longer write those legacy boundaries.
- Android/Termux clipboard writes use Pi's normal fallback chain, including OSC 52 when native clipboard commands are unavailable.
- Pi includes
Ctrl+Xfor copying the latest assistant response; this extension remains useful for searchable history, other roles, metadata, and direct selectors. - Node.js
>=24.15.0..nvmrcpins Node 24.21.0 for local development.
This package keeps pi core packages as wildcard peers (*) per pi package guidance. Pi aliases these imports to its own bundled copies when loading the extension, so the package never bundles or shadows pi core. Local development uses @earendil-works/pi-coding-agent and @earendil-works/pi-tui as dev dependencies for typechecking and tests.
Development
npm ci
npm run check # node --test + tsc --noEmit + pack dry-run
No production build or prepare is required. Tests run TypeScript directly with Node's type stripping, so source must stay erasable (erasableSyntaxOnly). Qualification uses the selected host installed in this checkout's dependency graph. The tests cover formatting, native command execution, canonical context and branch selection, both TUI modes, pointer focus and pending-picker disposal. Native addon interception and an isolated command PATH keep test clipboard writes in temporary fixture files, never the operator clipboard. Actual Android/Termux, Windows/WSL and remote terminal delivery still require platform qualification.
package-lock.json must only reference registry.npmjs.org; a test fails on private-registry URLs. Behind a registry proxy that rewrites tarball URLs, refresh the lock from public metadata and install through the proxy:
npm install --package-lock-only --ignore-scripts --registry=https://registry.npmjs.org/
npm ci
Key files:
extensions/copy-message.ts— publishable extension implementationtests/copy-message.test.ts— regression tests for command wiring, filtering, search, navigation, and copy formatting