Action design rules
Use these rules to keep behavior predictable acrossbetter-cmdk and modifywithai.
- Define one canonical
actions: CommandAction[]array. - Use one action per underlying operation (no duplicates).
- Write specific
descriptiontext so AI routing is reliable. - Add
inputSchemaonly when the action needs arguments. - Mark sensitive operations with
approvalRequired: true.
CommandMenu uses https://better-cmdk.com/api/chat as a free developer trial endpoint (no signup, 10 requests per 10 minutes). For production, set your own chatEndpoint or use modifywithai for agentic capabilities. You can disable chat with chatEndpoint={null}.
CommandAction reference
| Field | Type | Required | Used by |
|---|---|---|---|
name | string | Yes | both |
description | string | Yes | both |
execute | (options: Record<string, unknown>) => void | Yes | both |
label | string | No | better-cmdk |
group | string | No | better-cmdk |
icon | ReactNode | No | better-cmdk |
shortcut | string | No | better-cmdk |
keywords | string[] | No | better-cmdk |
semanticKey | string | No | both (overlap identity) |
disabled | boolean | No | better-cmdk |
onSelect | () => void | No | better-cmdk |
inputSchema | Record<string, { type; description?; required? }> | No | both |
approvalRequired | boolean | No | agent providers |
Quality examples
- Good
- Bad
Command-like vs argument-requiring
| Action kind | Definition | Direct select behavior |
|---|---|---|
| Command-like | No inputSchema | Calls onSelect or execute({}) |
| Argument-requiring | Has inputSchema | Routed into chat so arguments can be gathered |
Shared-array integration with modifywithai
Reuse the sameactions list in both libraries:
Custom rendering (composition API)
Usechildren for full UI control:
actions and children are both provided, actions takes precedence.
Approval workflow
For external agents,approvalRequired actions can be gated by user confirmation.
Flow:
- Agent requests execution of one or more actions.
- UI asks the user to approve or deny.
- Your app sends the decision with
addToolApprovalResponse.
AssistantMessages renders built-in confirmation UI for standard chat mode. Use custom confirmation components only when you need custom presentation.
Context and history hooks
useCommandMenuContext() exposes runtime state (mode, messages, status, sendMessage, switchToChat, switchToCommand).
Use historyStorageKey and maxConversations on CommandMenu to control persisted chat history:
Theming and styling
Customize tokens on.bcmdk-root:
className props for local overrides, and cn() for conditional classes.
Next steps
ModifyWithAI concepts
Deep dive into action routing, context, and approvals.
GitHub
Browse source, open issues, or contribute improvements.