Skip to content

feat(gentle-shell) *** Extension for adding cross-session prompt history search (/history, ctrl+shift+r, tombstone delete, GC compaction) PR#1390 al 1394 #818

Description

@carolitascl

Before submitting

  • I searched open and closed issues and did not find a request for this feature.
  • I reviewed this request and removed credentials, tokens, private paths, hostnames, and other sensitive data.

Problem or opportunity

Pi keeps prompt history only inside individual session transcripts. Once a session ends, there is no way to search or reuse prompts written hours or days ago, and the legacy editor-history.json store that survives across sessions is a single shared file that concurrent Pi instances can corrupt, with no viewer, no preview, no dedup, and no way to delete an embarrassing or secret prompt from history.

Proposed outcome

Ship extensions/history/, a Pi extension that gives the user a searchable, cross-session prompt history. It is enabled automatically because package.json declares pi.extensions: ["./extensions"] (no configuration needed). Inspired by @jasonish/pi-prompt-history.

Entry points

  • /history slash command ("Search prompt history").
  • ctrl+shift+r global shortcut (same behavior).
  • Empty history shows a warning toast ("No prompt history available.").

Search overlay (bottom-anchored, full-width, fixed 30-row TUI)

  • Search-as-you-type with multi-word AND substring matching, case-insensitive, capped at 10,000 results; a non-empty query expands to the full history snapshot.
  • 10-row result list with → selection cursor, position counter (· N of M), and lazy-window counter (· loaded N of M); entries are whitespace-compacted and control-char-sanitized.
  • Word-wrapped preview pane (10-row viewport) with range label when content overflows (Preview — start–end/total).
  • Scope toggle rendered as a radio: ◉ Current project | ○ All projects ↔ ○ Current project | ◉ All projects.
  • Empty state ("No matching prompts") and a one-line help row summarizing all keys.

Overlay keybindings

  • ↑ / ↓ — move selection (Down grows the lazy window before moving; Up wraps).
  • PgUp / PgDn — page the list (clamp, no wrap; PgDn catches up whole batches).
  • Enter — paste the selected prompt into the editor.
  • Tab — toggle project ↔ global scope and re-drain.
  • Home / End — jump to first / last entry (End loads the full history once).
  • ctrl+shift+↑ / ctrl+shift+↓ — page the preview pane.
  • ctrl+shift+backspace — delete the selected prompt (see delete flow).
  • Esc — cancel.
  • Any other key falls through into the search input.

Mouse

  • Wheel over the list rows scrolls the selection; wheel over the preview rows scrolls the preview; raw wheel bytes are never leaked into the search input.

Automatic capture

  • Every delivered user prompt is captured write-through (before_agent_start) to an append-only, per-Pi-instance JSONL file under ~/.pi/agent/history/projects/<projectHash>/<instanceId>.jsonl — zero shared writes between concurrent Pi processes.
  • Empty/whitespace and command-like prompts (/command) are not captured.

Delete flow with tombstones

  • ctrl+shift+backspace on an editor-sourced prompt physically sweeps it from the store files; a session-sourced (transcript-derived) prompt is tombstoned instead, so re-seeding from transcripts cannot resurrect it.
  • Tombstones live in ~/.pi/agent/history/hidden.json (sorted key array, atomic write); failure to write the hide file surfaces a warning toast ("Could not write the hide file; the prompt may reappear.").

Cold start: migration + seed

  • One-time migration of the legacy editor-history.json/.jsonl stores into the new layout (fail-open; legacy files kept until a successful migration).
  • One-time per-project seed (target 500 prompts) extracted from Pi session transcripts in ~/.pi/agent/sessions (read-only; header/format admission gates, user-role prefilter, 16 KB per-prompt cap, timestamp fallback chain).
  • Advisory registry.json maps project hashes to cwd paths for display; hash collisions re-key to a longer hash.

Recency, dedup, housekeeping

  • Results ordered newest-first: files sorted by newest entry timestamp (fallback mtime — stable under atomic rewrites), newest line first, keep-first dedupe by normalized identity (whitespace-collapsed, trimmed, 120-char prefix, lowercased).
  • Garbage collection at session_shutdown: past thresholds (50 files / 5000 lines) the oldest tail is compacted into compact-<ts>.jsonl, keeping the 10 newest files; originals are removed only after the compact file lands.
  • Every destructive/whole-file write is same-directory tmp + rename (atomic); malformed/torn JSONL lines are skipped at parse time.

Not configurable (yet)

  • All knobs are hard-coded constants (shortcut, list/preview sizes, batch sizes, drain limit, seed target, GC thresholds). A follow-up could expose them as settings.

Alternatives considered

  • Keep relying on Pi session transcripts directly — they are per-session, unbounded, and have no search UI; cross-session search and dedup still need an index/store.
  • Upstream a history feature into pi core — bigger cross-repo change; an extension proves the contract and storage layout first, with zero core risk.
  • Continue appending to the legacy shared editor-history.json — unsafe under concurrent Pi instances and has no tombstones, preview, or scope filtering.

Additional context

  • A reference implementation is complete and exercised in live sessions (store layout projects/, registry.json, hidden.json, history-global.jsonl in active use); a PR will be linked to this issue shortly.
  • The extension is self-contained (9 TypeScript files, ~2.9k lines): entry/wiring + TUI selector (index.ts), multi-concurrency JSONL store (store.ts), pure selector logic (selector-helpers.ts), transcript scanning (session-scan.ts), persisted transcript index (session-index.ts), combined loader (merge-history.ts), tombstones (hide-prompts.ts), legacy reader (load-shared-history.ts), atomic JSON writer (atomic-write.ts).
  • No new dependencies; uses only @earendil-works/pi-coding-agent and @earendil-works/pi-tui APIs (registerCommand, registerShortcut, on("before_agent_start" | "session_shutdown" | "tool_call"), ctx.ui.custom/notify/pasteToEditor).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status:approvedIssue approved by maintainer; PR may be opened

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions