Files
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

13 KiB

@elizaos/plugin-commands

Chat command system for Eliza agents — registers a slash-command surface (/help, /status, /reset, etc.) and a provider that injects command context into the LLM prompt only when needed.

Purpose / role

Adds a structured slash-command system to any Eliza agent. Commands are detected by text prefix (/ or !), registered as a COMMAND_REGISTRY provider, and handled by deterministic *_COMMAND actions this plugin registers directly (the commandActions array). The plugin also owns the wire-serialization (serializeCommand), connector catalog, and dispatch layer that every surface consumes. Auto-enabled when config.features.commands is truthy; controlled by auto-enable.ts.

Plugin surface

Actions

Name Description
*_COMMAND (one per deterministic key, e.g. HELP_COMMAND, THINK_COMMAND, RESET_COMMAND) Deterministic handlers for the built-in agent-target commands owned by this plugin, built from DETERMINISTIC_COMMAND_KEYS via createCommandActions(). Each validate() is strictly slash-only (never intercepts conversational text) and re-scopes to the per-runtime store. The pre-LLM shortcut gate dispatches these before inference; they are also registered so the planner can route to them as a fallback.

Providers

Name Description
COMMAND_REGISTRY Injects full command list into the LLM context only when the incoming message is a slash command; returns a minimal/empty hint otherwise. Scoped per agentId.

Exported plugin object: commandsPlugin (default export, also named export)

No services, evaluators, routes, or events are registered by this plugin. Beyond the actions + provider it exports the catalog layer (serializeCommand, getCatalogCommands, getConnectorCommands, navigationCommandDefinitions) and the dispatch helpers that consuming surfaces use.

Layout

src/
  index.ts              Plugin entry — exports commandsPlugin (with actions: commandActions),
                        commandRegistryProvider, formatCommandResult, isAuthorized, isElevated,
                        and re-exports actions/parser/registry/types/serialize/connector-catalog/
                        connector-bridge/navigation-commands/settings-sections
  registry.ts           Per-runtime command store: DEFAULT_COMMANDS (built-in defs),
                        initForRuntime(), useRuntime(), registerCommand(), registerCommands(),
                        unregisterCommand(), resetCommands(), getCommands(),
                        getEnabledCommands(), getCommandsByCategory(),
                        findCommandByAlias(), findCommandByKey(), startsWithCommand()
  parser.ts             Text parsing: hasCommand(), detectCommand(), parseCommand(),
                        normalizeCommandBody(), extractCommand(), isCommandOnly()
  types.ts              Shared types: CommandDefinition, CommandTarget, CommandSurface,
                        CommandArgSource, SerializedCommand, SerializedCommandArg,
                        CommandContext, CommandResult, ParsedCommand, CommandScope,
                        CommandCategory, CommandArgDefinition, ClientCommandAction
  serialize.ts          serializeCommand() — the canonical CommandDefinition → SerializedCommand
                        projection (the GET /api/commands wire shape); commandVisibleForSurface()
  navigation-commands.ts  navigationCommandDefinitions() — navigate + client commands as
                        first-class CommandDefinitions (target navigate/client, surfaces, icons)
  connector-catalog.ts  Connector-neutral catalog: getConnectorCommands(surface) (→ ConnectorCommand)
                        and getCatalogCommands(surface) (→ SerializedCommand[]); unions the agent
                        registry with navigation/client commands, filters by surface + active view.
  actions/              Deterministic command action layer: command-actions.ts (createCommandActions,
                        commandActions), handlers.ts (DETERMINISTIC_COMMAND_KEYS + handlers),
                        dispatch.ts (dispatch helper for the pre-LLM gate / connectors),
                        command-settings.ts (per-conversation settings store)
  settings-sections.ts  Settings section registry: SETTINGS_SECTIONS, resolveSettingsSection(),
                        getSettingsSectionChoices() — canonical /settings <section> tokens.

auto-enable.ts  Lightweight shouldEnable() — reads config.features.commands;
                loaded by the auto-enable engine at boot (no full plugin import)

Commands

bun run --cwd plugins/plugin-commands build         # bun build + tsc declarations
bun run --cwd plugins/plugin-commands dev           # hot-rebuild with bun --hot
bun run --cwd plugins/plugin-commands test          # vitest run
bun run --cwd plugins/plugin-commands typecheck     # tsgo --noEmit
bun run --cwd plugins/plugin-commands lint          # biome check --write --unsafe
bun run --cwd plugins/plugin-commands format        # biome format --write
bun run --cwd plugins/plugin-commands clean         # rm dist/.turbo artifacts

Config / env vars

All vars are read during plugin.init(config, runtime). None are required.

Var Default Description
COMMANDS_CONFIG_ENABLED "false" Enable /config command
COMMANDS_DEBUG_ENABLED "false" Enable /debug command
COMMANDS_BASH_ENABLED "false" Enable /bash shell execution (elevated)
COMMANDS_RESTART_ENABLED "true" Enable /restart command

Auto-enable gate: config.features.commands — truthy object or true enables the plugin.

Built-in command definitions

Defined in src/registry.ts as DEFAULT_COMMANDS. Each agent runtime receives an isolated copy via initForRuntime(agentId).

Status (category: "status"): help (/help /h /?), commands (/commands /cmds), status (/status /s), context (/context /ctx), whoami (/whoami /who)

Session (category: "session"): stop (/stop /abort /cancel), restart (/restart, auth), reset (/reset, auth), new (/new), compact (/compact)

Options (category: "options"): think (/think /thinking /t), verbose (/verbose /v), reasoning (/reasoning /reason), elevated (/elevated /elev, auth), model (/model /m), models (/models), usage (/usage), queue (/queue /q)

Management (category: "management"): allowlist (/allowlist /allow, auth), approve (/approve, auth), subagents (/subagents /sub, auth), accounts (/accounts, auth + elevated writes), backend (/backend, auth + elevated writes), config (/config /cfg, auth, disabled by default), debug (/debug, auth, disabled by default)

Media (category: "media"): tts (/tts /voice)

Tools (category: "tools"): bash (/bash /sh /!, auth + elevated, disabled by default)

How to extend

Add a command definition (registers it in the registry; built-in deterministic keys get a *_COMMAND action automatically — see actions/; a custom command still needs a handler):

import { registerCommand } from "@elizaos/plugin-commands";

registerCommand({
  key: "mycommand",
  description: "Does something useful",
  textAliases: ["/mycommand", "/mc"],
  scope: "both",
  category: "tools",
  acceptsArgs: true,
  args: [{ name: "target", description: "What to act on" }],
});

Add an action that handles a registered command: create an Action in your plugin with a validate() that calls hasCommand(message.content.text) and detectCommand() to match the right key, then implement handler(). See src/index.ts comments on validate/simile design.

Add a provider: follow the COMMAND_REGISTRY provider pattern in src/index.ts. Call useRuntime(runtime.agentId) before accessing registry functions so you operate on the correct per-agent store.

Conventions / gotchas

  • Registry is per-agent. initForRuntime(agentId) must be called in plugin.init() before any registry access; otherwise all agents share the fallback store. The plugin's own init() already does this.
  • Built-in deterministic actions live here. The plugin registers *_COMMAND actions for deterministic built-in keys (commandActions, built from DETERMINISTIC_COMMAND_KEYS via createCommandActions() in actions/): status/help-style commands, option-setting commands owned by the command-settings store, and the reset/new/compact session commands. Broader management commands whose side effects live outside this package (stop, restart, allowlist, approve, etc.) still flow through the normal pipeline. Plugin-specific or skill commands still register their own Action objects elsewhere.
  • Similes must be slash-only. Never add natural-language similes to command actions — the LLM will misroute conversational messages.
  • bash command is elevated + disabled by default. requiresElevated: true in the definition; enabled is set to false during init() because COMMANDS_BASH_ENABLED defaults to "false". Set COMMANDS_BASH_ENABLED=true to enable it.
  • Provider context-gates itself. For non-command messages the provider returns an empty string to keep the prompt clean.
  • Parser accepts / or ! prefix. The ! prefix is treated the same as /.
  • auto-enable.ts is a separate entry point — it must stay lightweight (no plugin runtime imports) because it is loaded by the auto-enable engine for every plugin at boot.
  • connector-catalog.ts for remote connectors. Use getConnectorCommands(surface) to get a connector-neutral view of all commands; kind: "client" targets are already filtered off remote connectors (Discord, Telegram, etc.).

NON-NEGOTIABLE — evidence, trajectories & real end-to-end tests

The binding, repo-wide standard is AGENTS.md. Read it. Nothing in this package is done until it is proven done — a reviewer must confirm it works without reading the code, from the artifacts you attach. This applies to every feature, fix, refactor, and chore here. "Tests pass" is not proof; "CI is green" is not proof.

  • Record AND read model trajectories. Capture the actual inputs and outputs of the model from a live LLM — not the deterministic proxy, not a mock: the prompt, the providers/context, the raw model output, every tool/action call, and the result. Then open the trajectory and review it by hand. A captured-but-unread trajectory is not evidence (packages/scenario-runner/bin/eliza-scenarios run <scenario> --report <out>).
  • Real, full-featured E2E — no larp. Every feature ships detailed end-to-end tests that drive the real path end to end. Not the happy "front door" only: cover error paths, edge/empty/invalid input, concurrency, roles/permissions, and adversarial input. A test that asserts against a mock/stub/fixture standing in for the thing under test does not count. If the real model/device/chain/connector/account is hard to reach, make it reachable — that is the work, not an excuse to mock. If the existing tests here are shallow or mocked, fixing them is part of your change.
  • Screenshots + logs at every phase, plus a complete walkthrough video/run-through of the entire feature or view, start to finish (bun run test:e2e:record).
  • Manually review every artifact the change touches — never just the green check: client logs (console + network), server logs ([ClassName] …), the model trajectories in and out, before/after full-page screenshots, and the domain artifacts listed below for this package.
  • No residuals. No shortcuts. The goal is not "done" — it is everything done. Clear every blocker by the hard path: build the real architecture, stand up the real model/device/service, actually test it. Never leave a TODO, a stub, a stepping-stone, or a "follow-up." When unsure, research thoroughly, weigh the options, and ship the best, highest-effort, production-ready version. Keep going until every possibility is exhausted.

Artifacts → attached inline in the PR (MP4 video, JPG screenshots, logs in <details>); attach each evidence type or explicitly mark it N/A with a reason — never leave it blank. If develop moved and changed behavior, re-capture evidence; stale proof is worse than none.

Capture & manually review for this package — CLI / tooling:

  • The real command/flow invocation transcript (args in, stdout/stderr, exit code) and the artifacts it generated (files, scaffolds, manifests, screenshots/recordings).
  • Failure paths: bad args, missing deps, partial state, permission/network errors.
  • A recording/log of the actual run end to end — not a unit test of one helper.
  • Any model interaction captured as a live trajectory and reviewed.