Skip to content

[Feature] Collapse slash command into inline mark inside the prompt input #778

@Astro-Han

Description

@Astro-Han

What task are you trying to do?

After PR #768, slash commands like /brainstorming xxx are collapsed into an inline mark (icon + brand-colored name + args as plain text) in the sent user-message bubble. The same visual treatment should also apply in the prompt input area itself, so the user sees a coherent representation of "this is a slash command, not a regular line of text" from the moment they trigger it, all the way through to the sent bubble.

Which area would this change affect?

UI or design system

What do you do today?

Today, when a user either:

  1. Types /brainstorming directly in the prompt input, or
  2. Selects a custom command from the slash popover,

the input shows the literal plain-text string /brainstorming (or /brainstorming <args>). Only after submission does the sent bubble render the collapsed inline mark introduced by PR #768. The "before submit" and "after submit" representations are visually inconsistent.

What would a good result look like?

The prompt input should render the same inline mark as the sent bubble: a 16px filled command icon visually replacing the slash, the command name in brand color, and the user-typed args as regular editable text following it. The collapsed form is the canonical representation of an active slash command at every stage (input → optimistic → sent bubble → restore via Undo / Fork / Edit).

What would count as done?

  • Selecting a custom command from the slash popover inserts a non-editable command pill (icon + brand-color name) at the start of the prompt input, followed by an editable caret position for args. The current behavior of inserting the plain-text /<trigger> string is replaced.
  • Typing /<known-command> directly and then SPACE (or any args char) auto-converts the leading /<command> into the same command pill, leaving the cursor right after it ready to type args. If the typed name is not a registered command, no conversion happens and the input remains plain text.
  • Backspacing into the pill removes the entire pill including the leading /<name> slice in one keystroke (consistent with how @file pills behave today — those are also atomic-delete, not restore-to-text). If the user had typed args, the args remain as plain text after the pill is gone; if there were no args, the prompt collapses to empty. The slash literal is not restored as plain text. (Updated 2026-05-20 after design spec round 4: PawWork's own @file pill already deletes atomically; chip + free-text-args products like Cursor / Codex Desktop converge on the same behaviour.)
  • The pill cannot appear anywhere except as the leading element of the prompt input; mid-string slashes remain plain text.
  • Submit flow is unchanged at the wire level: the backend still receives command: <name>, arguments: <args> exactly as today, regardless of whether the input is rendered as a pill or as plain text.
  • Restore paths (Undo / Fork / Edit a queued followup) put the pill back into the input, not the expanded template text or the plain-text /<name> <args>.
  • Visual style of the pill matches docs/design/scratch/slash-command-final.html and the sent-bubble rendering in packages/ui/src/components/message-part/user-message.tsx 1:1.

What should stay out of scope?

  • Backend metadata or SDK schema changes. PR feat(ui): collapse slash command into inline mark #768 already covers commandInvocation stamping; this feature only consumes it.
  • Built-in (non-custom) slash commands. Those clear the editor and trigger immediately and never sit as text in the input.
  • Shell-mode (!-prefixed) input.

Which audience does this matter to most?

Both

Extra context

  • Parent feature: [Feature] Collapse slash command template into a chip card in the chat bubble #762 — covered the sent-bubble side.
  • Implementation reference: PR feat(ui): collapse slash command into inline mark #768 (packages/ui/src/lib/command-invocation.ts, packages/ui/src/components/command-icon.tsx, packages/ui/src/components/message-part/user-message.tsx).
  • Existing pill infrastructure in the editor: packages/app/src/components/prompt-input/editor-serialize.ts (createPill), used today for @file and @agent mentions; the command pill should reuse the same mechanism.
  • Slash insertion entry point: packages/app/src/components/prompt-input/popover-controllers.ts handleSlashSelect (custom branch, currently writes /${cmd.trigger} as text).
  • Restore entry points already converging on a single helper: packages/app/src/utils/prompt.ts extractPromptFromParts (uses deriveCommandInvocation).

Current state

input bar:  /brainstorming █                 ← plain text
sent bubble: [icon] brainstorming             ← collapsed mark (PR #768)

Desired state

input bar:  [icon] brainstorming █            ← same collapsed mark
sent bubble: [icon] brainstorming             ← unchanged

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestuiDesign system and user interface

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions