Notes

How it works

Slash-commands reuse the context-mentions engine via a second trigger channel. Add a / channel to contextMentions.triggers (typically triggerPosition: "line-start", allowSpaces: true for args). Its source is the in-package createSlashCommandsSource. The whole command runtime ships in the same lazy-loaded chunk as mentions, so the core bundle is unchanged.

Command flavors

Use the Skill flavor toggle above the preview to compare the three dispatch kinds. There are only three — a command is always a prompt, an action, or a server skill. Everything else (taking an argument, coexisting with @) is a modifier any kind can carry, so each variant already shows an arg example:

  • Prompt macroskind: "prompt" writes text into the composer (submitOnSelect sends it immediately). No message-in-a-chip; the command becomes the message. /greet takes an argument.
  • Client actionskind: "action" runs a browser function (/clear, /help, /echo). Nothing is sent; the host wires broader actions via the controller. This variant also registers an @ context source, so commands and mentions share one engine (only one is active at any caret); the others stay pure slash commands.
  • Server skillkind: "server" sends structured data(args) to the backend via request context.mentions; the echo backend prints what it received.

Arg-bearing commands (/greet, /echo, /lookup) use inline completion (Slack-style): selecting fills /greet  into the composer with a ‹name› hint, you type the argument inline, and the command runs at submit. Server commands always work this way.

All variants are produced by one shareable factory (src/commands/slash-commands-experience.ts) spread into contextMentions — the config is a portable unit, since the plugin registry is render-only.

Config snippet

import { createSlashCommandsSource } from "@runtypelabs/persona"; const config = { contextMentions: { enabled: true, sources: [/* @ mention sources */], triggers: [{ trigger: "/", triggerPosition: "line-start", allowSpaces: true, sources: [ createSlashCommandsSource({ id: "commands", label: "Commands", commands: [ { name: "summarize", kind: "prompt", prompt: "Summarize.", submitOnSelect: true }, { name: "clear", kind: "action", action: () => controller.clearChat() }, { name: "lookup", kind: "server", data: (args) => ({ intent: "lookup-order", orderId: args }) }, ], }), ], }], }, };

Multiple arguments

There are no named argument slots. args is a single free-text string: everything typed after the command name, trimmed. Split it however you like inside data / action / prompt(args), so several space-separated values work today with no extra API:

{ name: "deploy", kind: "action", argsPlaceholder: "env region", action: ({ args }) => { const [env, region] = args.split(/\s+/); // "staging us-east-1" /* ... */ } }

Two caveats: for a line-start command the arguments come from the first line only (a newline ends the command line), and argsPlaceholder is a single display hint, not per-slot UI. Structured, validated argument slots (Discord's /ban user: reason: style) are not built in.