Skip to content

Built-in slash commands: autocomplete and dispatch#148

Merged
dnouri merged 1 commit intomasterfrom
feat/builtin-slash-dispatch
Feb 26, 2026
Merged

Built-in slash commands: autocomplete and dispatch#148
dnouri merged 1 commit intomasterfrom
feat/builtin-slash-dispatch

Conversation

@dnouri
Copy link
Copy Markdown
Owner

@dnouri dnouri commented Feb 25, 2026

What changed

Built-in slash commands now autocomplete and work from the input buffer. Previously, typing /new or /model sent the text as a prompt to the LLM instead of executing the command.

Fixes #143

All built-in commands work

/new, /model, /compact, /session, /name, /fork, /resume, /reload, /export, /copy, /quit — all dispatch locally. Extension and skill commands (/pisay, /skill:brave-search, etc.) still pass through to pi as before.

Model selector improvements

  • Fuzzy matching: opus matches "Opus 4.6", code matches "GPT-5.1 Codex Max" (case-insensitive flex completion)
  • Auto-select on unique match: /model spark sets the model directly without opening the picker; /model opus opens the picker pre-filled since multiple Opus models exist
  • Shortened names: selector shows "Opus 4.6" instead of "Claude Opus 4.6", matching the header-line

Slash commands accept arguments

  • /model opus — pre-fills/auto-selects in the model picker
  • /model zzzzz — prints "No model matching" instead of opening an empty picker
  • /export /tmp/out.html — exports to a custom path
  • /compact keep API details — passes custom compaction instructions
  • /name my-session — sets name directly; /name without arg prompts interactively
  • C-c C-p e now prompts for export path (RET for default)

Fix: "current: unknown" in model selector

The model selector and transient menu showed "unknown" when invoked from the input buffer (where the cursor normally lives), because session state is buffer-local in the chat buffer. Now reads state correctly from either buffer.

Built-in slash commands (/new, /model, /compact, /session, /name,
/fork, /resume, /reload, /export, /copy, /quit) were not autocompleted
or dispatched locally — they were sent verbatim as prompts, causing the
LLM to respond about them instead of executing them.

Dispatch table and autocomplete
  Data-driven table in ui.el maps command names to existing handler
  functions with an :args spec (nil, optional, required).  Autocomplete
  in input.el merges builtin names with RPC-provided commands.
  Dispatch in render.el replaces the old /compact-only special case.

Fix session state reads in menu functions
  Menu functions (model description, thinking description, select-model)
  read pi-coding-agent--state directly, but state is buffer-local in the
  chat buffer.  When called from the input buffer, state was nil giving
  'unknown'.  New --menu-state accessor reads via buffer-local-value.

Model selector improvements
  Shortened display names (Opus 4.6 not Claude Opus 4.6), matching the
  header-line.  Case-insensitive flex completion so 'opus' matches
  'Opus 4.6' and 'code' matches 'GPT-5.1 Codex Max'.  Unique flex
  match auto-selects without opening the picker (/model op46 sets
  Opus 4.6 directly).  No match prints a message; multiple matches
  open the picker pre-filled.

Argument passing for /model and /export
  /model accepts optional search text as initial-input.
  /export accepts optional output path, sent as :outputPath in the RPC.
  Interactive C-c C-p e now prompts for export path (RET for default).
@dnouri dnouri force-pushed the feat/builtin-slash-dispatch branch from 814fe85 to 7d59473 Compare February 26, 2026 01:05
@dnouri dnouri merged commit 7311a02 into master Feb 26, 2026
7 of 8 checks passed
@dnouri dnouri deleted the feat/builtin-slash-dispatch branch February 26, 2026 01:59
dnouri added a commit that referenced this pull request Feb 26, 2026
Built-in slash commands (/new, /model, /compact, /session, /name,
/fork, /resume, /reload, /export, /copy, /quit) were not autocompleted
or dispatched locally — they were sent verbatim as prompts, causing the
LLM to respond about them instead of executing them.

Dispatch table and autocomplete
  Data-driven table in ui.el maps command names to existing handler
  functions with an :args spec (nil, optional, required).  Autocomplete
  in input.el merges builtin names with RPC-provided commands.
  Dispatch in render.el replaces the old /compact-only special case.

Fix session state reads in menu functions
  Menu functions (model description, thinking description, select-model)
  read pi-coding-agent--state directly, but state is buffer-local in the
  chat buffer.  When called from the input buffer, state was nil giving
  'unknown'.  New --menu-state accessor reads via buffer-local-value.

Model selector improvements
  Shortened display names (Opus 4.6 not Claude Opus 4.6), matching the
  header-line.  Case-insensitive flex completion so 'opus' matches
  'Opus 4.6' and 'code' matches 'GPT-5.1 Codex Max'.  Unique flex
  match auto-selects without opening the picker (/model op46 sets
  Opus 4.6 directly).  No match prints a message; multiple matches
  open the picker pre-filled.

Argument passing for /model and /export
  /model accepts optional search text as initial-input.
  /export accepts optional output path, sent as :outputPath in the RPC.
  Interactive C-c C-p e now prompts for export path (RET for default).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant