Skip to content
Cisco AI Defense logo
CiscoAI Security

Command palette — DefenseClaw

Overview

The command palette is an overlay modeled on charm.sh + sahilm/fuzzy. It indexes the full CmdEntry registry defined in internal/tui/command.go, runs commands through the same subprocess bridge the panels use, and streams output back inline. Anything you can do from a panel, you can also do from the palette — the registry is the single source of truth.

Opening the palette

KeyWhere
Ctrl+KAnywhere
:Anywhere

Ctrl+K is the conventional binding; : exists because operators with muscle memory from editors and k9s reach for it first. Both open the same overlay.

Layout

┌─ Command palette ────────────────────────────────────────────────┐
│ > setup guardr                                                   │
├──────────────────────────────────────────────────────────────────┤
│  ▸ setup guardrail         Configure LLM guardrail         setup │
│    setup guardrail --mode  Flip mode (observe/action)      setup │
│    setup guardrail --disable  Disable the guardrail        setup │
└──────────────────────────────────────────────────────────────────┘

The input line echoes what you typed; the result list shows TUIName (left), Description (center), Category (right). Fuzzy matching is case-insensitive and orders by match score.

Registry categories

CategoryExample entries
setupinit, setup skill-scanner, setup guardrail, setup splunk, setup provider add
scanscan skill, scan skill --all, scan mcp, scan plugin, scan aibom, scan code
enforceblock skill, allow skill, quarantine skill, set mcp, disable plugin
keyskeys list, keys set, keys fill-missing, keys check
policypolicy test, policy reload, policy edit
auditaudit query, audit export, audit stats
gatewaygateway start, gateway stop, gateway restart, gateway status
miscdoctor, status, alerts, upgrade

See internal/tui/command.go for the full list (200+ entries). Duplicate TUI names are caught by command_test.go.

Executing a command

  1. Type enough characters to disambiguate.
  2. Press enter on the highlighted match.
  3. If the entry has NeedsArg=true, you're prompted for the argument with ArgHint as placeholder text.
  4. The palette closes; output streams inline in the panel's command output region.

For long-running commands (scans, setups), the output region expands and Ctrl+C cancels the subprocess without killing the TUI.

Arg-taking entries

A subset of entries expects a positional argument — the palette prompts for it after enter:

EntryArg hint
scan skill<skill-name>
scan mcp<url>
scan plugin<plugin-name>
scan code<path>
block skill / unblock skill / ...<skill-name>
keys set<ENV_NAME>

Arg resolution uses whatever is selected in the panel when relevant — e.g. invoking block skill from the Skills panel pre-fills the argument with the selected row's name.

Why a palette exists alongside panels

Panels are optimized for browsing-and-acting-on-lists. The palette is optimized for "I know what I want to do". They share the subprocess bridge, so:

  • A palette run with scan skill --all and a scan-all action chosen from the Skills panel run the exact same CLI invocation.
  • Audit logs see both as scan.skill.all events.
  • CI pipelines that invoke the CLI directly produce identical audit rows.

This three-way parity — palette, panel, CLI — is tested in cli_parity_test.go.

Closing the palette

KeyBehavior
escClose without running
enterClose after running (unless the entry keeps the palette open)
Ctrl+CClose the palette (global Ctrl+C still quits the TUI if the palette is already closed)

Related