Skip to content

feat(codegraff): slash command palette + autocomplete#21

Merged
justrach merged 2 commits into
mainfrom
feat/codegraff-slash-palette
May 5, 2026
Merged

feat(codegraff): slash command palette + autocomplete#21
justrach merged 2 commits into
mainfrom
feat/codegraff-slash-palette

Conversation

@justrach

@justrach justrach commented May 4, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a fuzzy / command palette to the codegraff TUI (closes #17). Typing / on an empty composer pops a centered overlay that fuzzy-matches commands ported from the graff REPL AppCommand enum, with single-line descriptions, keyboard navigation, Tab autocomplete, and Enter dispatch through the existing handle_enter parser path.

  • New Overlay::CommandPalette(CommandPaletteState) variant; declared next to existing overlay types so main.rs stays a single file.
  • Static PALETTE_COMMANDS catalogue mirrors the AppCommand enum (crates/forge_main/src/model.rs) plus codegraff-only commands (/workflow, /image, /logs, /login, /connect, /models, /usage). REPL-only entries (:exit, :edit, :retry) are explicitly excluded.
  • Fuzzy ranking uses the workspace nucleo = "0.5.0" dep (already declared, just wired into crates/codegraff-tui/Cargo.toml). Score-0 results are filtered; ties preserve catalogue order.
  • Dispatch is intentionally reuse-first: the palette sets self.composer = "/<name>" and calls handle_enter, so /workflow, /image, /login, /models, etc. keep their existing per-command branches and parsers untouched.
  • Render path calls Clear over the overlay rect on top of the full-frame Clear already present in render(), so opening, closing, and resizing the palette do not leave ghost borders. overlay_area() is recomputed every frame, so resize re-clamps.

Files changed:

  • Cargo.lock
  • crates/codegraff-tui/Cargo.toml (add nucleo.workspace = true)
  • crates/codegraff-tui/src/main.rs (palette table, overlay variant, palette key handler, dispatcher, render arm, 7 unit tests)

Keybindings inside the palette

Key Action
Up / Down Navigate (wraps at edges)
Tab Autocomplete the highlighted name into the query
Enter Run the highlighted command via existing dispatch
Esc Close without running
Backspace Delete one char; closes overlay when query is empty
Any printable char Append to the query and reset selection to top

Test plan

  • cargo check -p codegraff clean
  • cargo build --release -p codegraff clean
  • cargo test -p codegraff --bin codegraff — 118 passed (111 prior + 7 new palette tests)
  • cargo clippy -p codegraff --tests -- -D warnings clean
  • Interactive smoke test on macOS: confirm typing / opens the palette, fuzzy filtering ranks results live, Tab autocompletes, Enter dispatches /usage / /models / /workflow <goal>, Esc closes without artifacts, Backspace closes from empty query, terminal resize re-centers the overlay. (I could not run the interactive TUI from the sandbox shell; the binary builds and unit-test coverage exercises the pure logic. Reviewer please confirm on a real terminal.)

Notes / asks for human review

  • Commands ported are conservative: every entry in AppCommand except :exit, :edit, :retry is in the palette. If anything else should be hidden (e.g. delete, which is command(skip) in the parser and not user-typable from the REPL — that's why I left it out), please flag.
  • Descriptions are paraphrased from the #[strum(props(usage = ...))] annotations to fit a single line; they are not auto-derived. If you want them generated, that's a follow-up.
  • Triggering on / only fires when the composer is empty so users can still type / mid-message.

🤖 Generated with Claude Code

Adds a fuzzy slash command palette to the codegraff TUI. Typing `/`
when the composer is empty opens a centered overlay listing all
slash commands ported from graff's REPL AppCommand enum, plus
codegraff-specific commands (/workflow, /image, /logs, etc.).

Implementation notes:
- New Overlay::CommandPalette variant with CommandPaletteState
  (query + selected_index) lives next to the existing overlay types
  in main.rs to avoid risky refactors.
- Static PALETTE_COMMANDS table holds (name, description). The list
  mirrors crates/forge_main/src/model.rs, excluding REPL-only
  entries (:exit, :edit, :retry).
- Fuzzy ranking uses the workspace `nucleo` dep (already declared in
  Cargo.toml). Items with score 0 are filtered out; ties preserve
  catalogue order.
- `dispatch_command_palette` writes "/<name>" into self.composer and
  reuses the existing handle_enter dispatch path, so commands like
  /workflow keep their parser unchanged.
- Keybindings: Up/Down navigate, Tab autocompletes, Enter dispatches,
  Esc closes, Backspace deletes (closes when query empty), any other
  char appends to the query.
- Render path calls Clear over the overlay rect; full-frame Clear at
  the top of render() prevents close artifacts. overlay_area is
  recomputed each frame, so resize re-clamps automatically.

Tests cover empty-query catalogue, fuzzy match, zero-score filter,
catalogue uniqueness, REPL-only exclusion, and rendered line content.
All 118 codegraff bin tests pass; clippy and release build are clean.

Closes #17

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the type: feature Brand new functionality, features, pages, workflows, endpoints, etc. label May 4, 2026
…utes

Pre-merge review caught that ~30 entries in PALETTE_COMMANDS exposed
commands the codegraff TUI dispatcher does not yet handle locally
(`/new`, `/info`, `/agent`, `/commit`, `/dump`, `/skill`, `/tools`,
`/copy`, `/clone`, `/conversation*`, `/workspace-*`, `/index`, `/update`,
`/compact`, `/sage`, `/help`, `/plan`, `/act`, `/rename`, `/fast`,
`/config-*`, `/suggest`, etc.). Selecting any of those from the palette
would silently send the literal slash text to the LLM as a chat message,
which is strictly worse UX than not exposing them.

Restrict the palette to the 8 commands `handle_enter` does route:
`/connect`, `/image`, `/login`, `/logs`, `/model`, `/models`, `/usage`,
`/workflow`. Wiring the rest into the TUI dispatcher is tracked in a
follow-up issue under the parity tracker.

Also tighten `palette_command_names_are_unique_and_lowercase` to
actually assert lowercase (it didn't before — name was misleading) and
add a sanity test confirming every locally-handled command is in the
palette so the dispatcher stays in sync.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@justrach justrach merged commit 6e48433 into main May 5, 2026
6 of 7 checks passed
@justrach justrach deleted the feat/codegraff-slash-palette branch May 5, 2026 03:52
justrach added a commit that referenced this pull request May 5, 2026
Captures the slash-palette + tier 1-7 dispatcher work merged in #21,
#23 (via #25), and #25, plus the rebrand and image-paste work from
#19. All forge_* and codegraff crates inherit via
\`version.workspace = true\`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: feature Brand new functionality, features, pages, workflows, endpoints, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add slash command (/) palette + autocomplete to codegraff TUI

1 participant