Skip to content

Command help: a searchable popup of everyday commands with copy buttons, built once in core (#12) - #31

Merged
Maxaubert merged 9 commits into
mainfrom
feat/12-help-panel
Sep 20, 2026
Merged

Maxaubert merged 9 commits into
mainfrom
feat/12-help-panel

Conversation

@Maxaubert

Copy link
Copy Markdown
Owner

Closes #12

What it is

Press F1 (or the ? in the title bar, or "Command help" in the terminal's right-click menu) and a popup opens over the app. Type what you want to do in your own words ("find big files", "what is using port 3000", "undo last commit") and it answers with the command, a plain explanation, its variations, what each placeholder means, and a marked warning on anything that deletes or overwrites. Every command and every variant has its own copy button.

Owner, 2026-09-19: "an easy to use panel where you can find shell commands... searchable... metadata on each command so a natural-language search finds it... optional in settings", and DECIDED: "picking a command in the help panel does NOT insert it into the shell". 2026-09-20: "a pop up with copy icons for easy copying. searchable, natural language".

The rules it is built on

  • It never inserts and never runs. The component is handed the clipboard and nothing else: no session id, no termInput, no bridge. The e2e reads the terminal's text before the popup is touched and again after every search, copy and Enter in it, and asserts it is identical.
  • Copy is exact. The text on screen, placeholders included. It goes through main (clipboard:write, text only, refused past 4000 characters, never trimmed), because navigator.clipboard refuses when the document has no focus. A "command" that is a key to press (Ctrl+C, Esc) is drawn as key caps and has no copy button.
  • Curated and offline. 307 hand-written entries: PowerShell 94, Command Prompt 46, Bash 65, Git 42, Claude Code and Codex 38, winget / npm / pip 22. The search is pure TypeScript: stop words, a light stemmer, a small synonym table, prefix and one-typo matching. No model, no network, no new dependency. The popup and catalogue are a lazy chunk (289 kB) loaded at the first open.
  • catalogue.test.ts is the gate for content: unique ids with the shell's prefix, task length, 6 to 14 lower-case keywords, every placeholder declared and used, no angle-bracket placeholders, no em-dash, a danger line on everything matching a destructive pattern, and a dozen real questions per shell against the REAL catalogue.
  • On by default, and off means off: no button, no menu row, and F1 is the shell's again.
  • One layer, one thing in it: the popup does not open over a close question or the update window, and App puts it away when one appears.

This is a core change, so it is a change to Prism too

Everything but the way in lives in core/ (version 0.3.0 to 0.4.0): shared/help/, renderer/lib/helpPrefs.ts, renderer/components/HelpPanel.tsx, renderer/settings/Help.tsx + helpOptions.ts, and writeClipboard on the bridge. For Prism the bump is INERT until Prism wires it: nothing in the core mounts the popup, claims a key or renders the row by itself. Two things Prism's side should know:

  • ClipboardLike in core/main/ipc.ts gained writeText. Prism passes Electron's own clipboard, which has it, so this compiles unchanged.
  • The option is in a list of its OWN (helpOptions.ts), not in TERMINAL_OPTIONS: Prism's gate reads options.ts as text, and a row there would fail Prism's parity check until Prism wires the popup.

core/README.md says what a host wires.

Content fixes made while building the gate

  • pkg-scripts-disabled duplicated ps-scripts-disabled (and broke the prefix rule, being PowerShell's): removed, its npm.cmd variant and keywords folded into the PowerShell entry.
  • Command Prompt had no answer to "find big files" or "unzip": cmd-biggest-files (forfiles) and cmd-unzip (tar, which Windows 10 and 11 ship) were added, both RUN in a scratch folder in stock cmd.exe first.
  • ps-clipboard gained a danger line (its Set-Content variant overwrites a file); ps-free-port now passes -ErrorAction SilentlyContinue, so a port that is already free prints nothing instead of a wall of red (run with -WhatIf against a free port).
  • Twelve PowerShell entries had upper-case keywords (ls -R, echo $PATH), two had a duplicate after lower-casing; grep alone now belongs to the search-in-files entry, which is what it means to most people.

Verified

  • npm run typecheck: clean. npm run lint: 0 errors (the same 8 warnings as main).
  • npm test: 55 files, 755 tests, all passing (22 in catalogue.test.ts, 39 in search.test.ts).
  • e2e, all passing: helpPanel 59 checks, options 10, spawn 7, closeAsk 8, updateWindow 52, dropAndMenu 5, and every other scenario except the two dictation ones (not run: another suite may be counting speech servers).
  • LOOKED AT: .e2e-shots/help-browse-dark.png, help-results-dark.png, help-danger-dark.png, help-browse-light.png, help-results-light.png, settings-general.png. The first screenshot showed the footer sentence cut off with an ellipsis; it was shortened and is now measured.

Not machine-testable, for the hands-on list

  • F1 on a physical keyboard over a real Claude Code session, and whether losing PSReadLine's own F1 (help for the command under the cursor) is missed.
  • Entries the catalogue's authors could not run here: winget (documentation only), the Ubuntu-only tools (apt, lsof, ss; WSL had no distribution on the machine they were written on), and the agents' in-session keys.
  • Not installed on this machine: the installed apps were left alone, as instructed.

App 0.4.0 to 0.5.0, so merging publishes a release.

🤖 Generated with Claude Code

Maxaubert and others added 9 commits September 20, 2026 13:24
…guage search (#12)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ine (#12)

Stop words, a light stemmer, a small synonym table, prefix and one-typo matching, and a command-name tier so somebody who knows the command is served first. No model, no network, no dependency.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PowerShell, Command Prompt, Bash, Git, Claude Code and Codex, winget/npm/pip. catalogue.test.ts holds every rule of types.ts: ids and prefixes, keywords, placeholders declared and used, no em-dash, a danger line on everything destructive, and real questions against the real catalogue for each shell.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
navigator.clipboard refuses when the document has no focus; a copy button has to work on every press. An oversized write is refused, never trimmed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#12)

A popup with a search field, shell chips, a copy button on every command and variant, placeholders explained and a warning on anything destructive. Props only: it is handed the clipboard and nothing else, so it cannot type into a shell. On by default; its option list is its own, not a row in TERMINAL_OPTIONS.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… e2e helpPanel (#12)

F1 is claimed in ownsKey only while the setting is on. The popup never opens over a close question or the update window and is put away when one appears. The e2e asserts the terminal's text is unchanged throughout, reads the clipboard back in main, measures the layout and writes .e2e-shots/help-*.png on a dark and a light theme.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… 0.4.0 (#12)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…CI runner (#12)

The cold search measured 4.9 ms here and 21.8 ms on a shared runner, where the 20 ms bound failed the build. The keystroke bound stays at 20 ms.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ges; overwrites carry a warning; the plainest questions land

The popup stayed up over Ctrl+T, Ctrl+Tab and Ctrl+Shift+F, and a terminal
takes the focus as it attaches: the next "search" was typed into a shell
behind the popup. It now goes as soon as what was in front when it opened
(the tab, the find bar) no longer is; helpPanel holds Ctrl+T and find.

Catalogue: a single > over a file and a download over a file are destructive
patterns in the gate now, which put a danger line on seven entries; commands
are gated to printable ASCII. "what files are here" answered with Delete a
file and "newest files" with Make a new empty file: list-files gained the
plain phrasings, "newest" no longer stems to "new", and 17 more real
questions are held per shell. Keyword cap 14 -> 16.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Maxaubert
Maxaubert merged commit 65c70f8 into main Sep 20, 2026
2 checks passed
@Maxaubert
Maxaubert deleted the feat/12-help-panel branch September 20, 2026 13:18
github-actions Bot pushed a commit that referenced this pull request Sep 20, 2026
…ns, built once in core (#12) (#31)

* feat(help): the catalogue's shape: task first, keywords for plain-language search (#12)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(help): a plain-language search over the catalogue, pure and offline (#12)

Stop words, a light stemmer, a small synonym table, prefix and one-typo matching, and a command-name tier so somebody who knows the command is served first. No model, no network, no dependency.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(help): the catalogue, and the test that gates its content (#12)

PowerShell, Command Prompt, Bash, Git, Claude Code and Codex, winget/npm/pip. catalogue.test.ts holds every rule of types.ts: ids and prefixes, keywords, placeholders declared and used, no em-dash, a danger line on everything destructive, and real questions against the real catalogue for each shell.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(core): writeClipboard on the bridge, text only and bounded (#12)

navigator.clipboard refuses when the document has no focus; a copy button has to work on every press. An oversized write is refused, never trimmed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(help): the command help popup, its prefs and its setting, in core (#12)

A popup with a search field, shell chips, a copy button on every command and variant, placeholders explained and a warning on anything destructive. Props only: it is handed the clipboard and nothing else, so it cannot type into a shell. On by default; its option list is its own, not a row in TERMINAL_OPTIONS.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(app): F1, a ? in the title bar and a menu row open command help; e2e helpPanel (#12)

F1 is claimed in ownsKey only while the setting is on. The popup never opens over a close question or the update window and is put away when one appears. The e2e asserts the terminal's text is unchanged throughout, reads the clipboard back in main, measures the layout and writes .e2e-shots/help-*.png on a dark and a light theme.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs(help): the rules, the key and what a host wires; app 0.5.0, core 0.4.0 (#12)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(help): the timing bounds are for a quadratic index, not for the CI runner (#12)

The cold search measured 4.9 ms here and 21.8 ms on a shared runner, where the 20 ms bound failed the build. The keystroke bound stays at 20 ms.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(help): review of #12: the popup leaves when the tab in front changes; overwrites carry a warning; the plainest questions land

The popup stayed up over Ctrl+T, Ctrl+Tab and Ctrl+Shift+F, and a terminal
takes the focus as it attaches: the next "search" was typed into a shell
behind the popup. It now goes as soon as what was in front when it opened
(the tab, the find bar) no longer is; helpPanel holds Ctrl+T and find.

Catalogue: a single > over a file and a download over a file are destructive
patterns in the gate now, which put a danger line on seven entries; commands
are gated to printable ASCII. "what files are here" answered with Delete a
file and "newest files" with Make a new empty file: list-files gained the
plain phrasings, "newest" no longer stems to "new", and 17 more real
questions are held per shell. Keyword cap 14 -> 16.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Maxaubert added a commit that referenced this pull request Sep 25, 2026
- Warm shell: a stale exit removes only its own entry (#2).
- A tab closed while its shell is starting kills it; no duplicate spawn (#12).
- Dictation: a stop while transcribing is not heard, so one paste (#4).
- Ctrl+C / Ctrl+V also match the physical key (#6).
- The panel attach is keyed on the session; a cd no longer steals focus (#9, #23).
- Tab chords do nothing under a question or the update window (#10).
- Cells vs UTF-16: resize carry and link hit-testing via termCells (#20, #25).
- Shift+Enter continuation only where an agent runs (#21).
- The resume spinner stops when the spawn fails (#24).
- Restore runs once under StrictMode (#31).
- The terminal menu belongs to its session and goes on a tab change (#32).
- A drag that never drops gives the strip back (#33).

Core 0.15.2, app 0.18.2. New reviewKeys e2e, unit tests for sessions,
dictation and termCells; each fails on the code before the fix.


Claude-Session: https://claude.ai/code/session_01LJbePcRzre7AusNzPNS2Bk

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Sep 25, 2026
- Warm shell: a stale exit removes only its own entry (#2).
- A tab closed while its shell is starting kills it; no duplicate spawn (#12).
- Dictation: a stop while transcribing is not heard, so one paste (#4).
- Ctrl+C / Ctrl+V also match the physical key (#6).
- The panel attach is keyed on the session; a cd no longer steals focus (#9, #23).
- Tab chords do nothing under a question or the update window (#10).
- Cells vs UTF-16: resize carry and link hit-testing via termCells (#20, #25).
- Shift+Enter continuation only where an agent runs (#21).
- The resume spinner stops when the spawn fails (#24).
- Restore runs once under StrictMode (#31).
- The terminal menu belongs to its session and goes on a tab change (#32).
- A drag that never drops gives the strip back (#33).

Core 0.15.2, app 0.18.2. New reviewKeys e2e, unit tests for sessions,
dictation and termCells; each fails on the code before the fix.


Claude-Session: https://claude.ai/code/session_01LJbePcRzre7AusNzPNS2Bk

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Help panel: a searchable catalogue of shell commands

1 participant