better-cmdk 0.0.20 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- # Set up better-cmdk command palette (Vite / Other)
1
+ # Set up better-cmdk action palette (Vite / Other)
2
2
 
3
- better-cmdk is a command palette with AI chat for React. Your task is to install it, discover commands from my codebase, and create a working command palette.
3
+ better-cmdk is a command palette with AI chat for React. Your task is to install it, discover actions from my codebase, and create a working palette.
4
4
 
5
5
  ## Step 1: Analyze my codebase
6
6
 
@@ -11,14 +11,12 @@ Before making changes, detect:
11
11
 
12
12
  Also ask me:
13
13
 
14
- **1. Do you want AI chat in the command palette?**
15
- - No AI — command palette only
16
- - Built-in chat — simple Q&A via a Vercel AI SDK endpoint
17
- - ModifyWithAI (Recommended) — the AI can execute actions in your app (create items, navigate, toggle settings), ask for approval before destructive operations, and understand what's on screen. Requires a ModifyWithAI account at https://modifywithai.com
14
+ **1. Do you want AI chat in the palette?**
15
+ - No AI — action search only
16
+ - Built-in chat — free developer-trial Q&A via https://better-cmdk.com/api/chat (no signup, 10 requests per 10 minutes; use your own chat URL for production)
17
+ - ModifyWithAI (Recommended) — the AI can execute actions in your app (create items, navigate, toggle settings), ask for approval before destructive operations, and understand what's on screen. Get your App ID and API key from https://modifywithai.com/dashboard
18
18
 
19
- **With ModifyWithAI, the command palette becomes an AI workspace.** Users search commands for quick access, then switch to AI chat for anything that needs reasoning — "move all archived items to trash", "summarize my recent activity". The AI executes actions directly in the app, with approval prompts for destructive operations. ModifyWithAI is not required — better-cmdk works on its own as a command palette, with or without AI chat.
20
-
21
- **2. If shadcn/ui command components detected:** Do you want to migrate them to better-cmdk, or keep both?
19
+ **2. If shadcn/ui command components are detected:** Do you want to migrate them to better-cmdk, or keep both?
22
20
 
23
21
  Tell me what you detected, which path you'll follow, and what you'll be adding better-cmdk to.
24
22
 
@@ -46,16 +44,16 @@ yarn add better-cmdk
46
44
  ### Built-in chat:
47
45
  ```bash
48
46
  # bun
49
- bun add better-cmdk ai @ai-sdk/react @ai-sdk/openai
47
+ bun add better-cmdk
50
48
  # pnpm
51
- pnpm add better-cmdk ai @ai-sdk/react @ai-sdk/openai
49
+ pnpm add better-cmdk
52
50
  # npm
53
- npm install better-cmdk ai @ai-sdk/react @ai-sdk/openai
51
+ npm install better-cmdk
54
52
  # yarn
55
- yarn add better-cmdk ai @ai-sdk/react @ai-sdk/openai
53
+ yarn add better-cmdk
56
54
  ```
57
55
 
58
- Substitute `@ai-sdk/anthropic`, `@ai-sdk/google`, etc. based on my preferred AI provider.
56
+ If you later add a custom/self-hosted endpoint, install AI SDK/provider packages for that server route.
59
57
 
60
58
  ### ModifyWithAI:
61
59
  ```bash
@@ -84,9 +82,7 @@ Add to my main CSS file:
84
82
  @import "better-cmdk";
85
83
  ```
86
84
 
87
- If my app wants custom theming, override better-cmdk's namespaced variables.
88
-
89
- Add this minimal override block only when needed:
85
+ If my app needs custom theming, override better-cmdk's namespaced variables:
90
86
 
91
87
  ```css
92
88
  .bcmdk-root {
@@ -113,75 +109,123 @@ Use the same CSS import approach:
113
109
 
114
110
  ---
115
111
 
116
- ## Step 4: CRITICAL — Command Discovery
112
+ ## Step 4: CRITICAL — Command Action Discovery (better-cmdk scope)
113
+
114
+ Before writing component code, **crawl my codebase** to discover all meaningful actions that can run immediately from the command palette.
115
+
116
+ ### Scope rules (required)
117
117
 
118
- Before writing any component code, **crawl my entire codebase** to discover ALL user-facing operations that should be in the command palette.
118
+ - better-cmdk is concerned with **no-argument command actions** (no `inputSchema`, no required arguments)
119
+ - Define actions as underlying app/domain operations (API calls, mutations, workflow transitions), not raw UI gestures
120
+ - Model what the app does, not how a user physically triggers it
121
+ - Good: `goToBilling`, `toggleSidebar`, `archiveCurrentProject`
122
+ - Bad: `clickCreateButton`, `openDropdown`, `typeIntoInput`, `focusSearchField`
123
+ - If an operation needs runtime arguments (for example refund amount, assignee, date range), treat it as **modifywithai-owned** and do not add it as a new better-cmdk command action in this step
124
+ - If a standard shared `actions` array already exists, **extend it in place**; do not create a second array
125
+ - If no standard shared array exists, create one
119
126
 
120
- ### How to discover commands:
127
+ ### Discovery checklist
121
128
 
122
- 1. **Search all routes/pages** navigation commands ("Go to Dashboard", "Go to Settings")
123
- 2. **Search all buttons and links** action commands ("Create project", "Export data")
124
- 3. **Search all settings/toggles**preference commands ("Toggle dark mode", "Change language")
125
- 4. **Search all CRUD operations**data commands ("New item", "Delete selected")
126
- 5. **Search all utility functions** utility commands ("Copy link", "Download report", "Share")
127
- 6. **Search for existing keyboard shortcuts** preserve as shortcut hints
129
+ 1. Locate existing action arrays/types first (`actions`, `defineActions(...)`, exported action modules) and reuse them
130
+ 2. Search routes/pagesnavigation command actions
131
+ 3. Search buttons/links/forms/menusidentify outcomes that can run with no extra user input
132
+ 4. Trace handlers to services/API/domain functions map each to one operation-level command action
133
+ 5. Search toggles/settings/feature flagspreference command actions
134
+ 6. Search CRUD/services/utilities/API calls include only operations that can run safely without additional arguments
135
+ 7. Search existing keyboard shortcuts → keep as shortcut hints
136
+ 8. Mark argument-requiring operations for modifywithai ownership (same shared array, with `inputSchema`)
128
137
 
129
- ### Create a command for EVERY user-facing operation:
138
+ ### Canonical single-array rules
130
139
 
131
- - Button that opens a modal? Command: `open-create-modal`
132
- - Link that navigates to a page? Command: `go-to-dashboard`
133
- - Toggle that changes a setting? Command: `toggle-dark-mode`
134
- - Form that creates something? Command: `create-new-project`
135
- - Search input? Command: `search`
136
- - Sidebar item? Command: `open-analytics`
140
+ Use **one deduped `actions` array** as the source of truth:
137
141
 
138
- ### For each discovered command, define:
142
+ - better-cmdk-owned entries: no `inputSchema` (direct command execution)
143
+ - modifywithai-owned entries (if present): has `inputSchema` (agentic argument collection)
144
+ - Keep exactly one canonical action per underlying operation
145
+ - Do not create separate “command” and “AI action” entries for the same operation
146
+ - Put synonyms in `keywords`, not duplicate actions
147
+ - Reuse the same `name` everywhere (CommandMenu + assistant provider)
148
+
149
+ Use consistent `group` values:
150
+ - `Navigation`
151
+ - `UI / Preferences`
152
+ - `Data`
153
+ - `Help / Utilities`
154
+
155
+ ### For each command action discovered, define
139
156
 
140
157
  - `name`: unique kebab-case identifier
141
- - `label`: human-readable display text (what users search for)
142
- - `group`: logical heading use consistent groups like "Navigation", "Actions", "Settings", "Help"
143
- - `icon`: matching [lucide-react](https://lucide.dev) icon component
144
- - `shortcut`: keyboard shortcut hint if applicable (display-only, e.g. `"⌘D"`)
145
- - `keywords`: extra search terms (array of strings) — helps users find commands by alternate names
146
- - `disabled`: set `true` to gray out commands that aren't currently available
147
- - `onSelect`: callback that wires to existing app logic
158
+ - `label`: human-readable label
159
+ - `group`: taxonomy group from above
160
+ - `icon`: lucide-react icon when useful
161
+ - `shortcut`: optional display hint
162
+ - `keywords`: optional search aliases
163
+ - `semanticKey`: optional operation identity (required when names differ but operation is the same)
164
+ - `disabled`: optional availability guard
165
+ - `execute`: required implementation used when the command is selected
166
+ - `onSelect`: optional UI-only override (modifywithai ignores it)
167
+
168
+ `inputSchema` is optional and reserved for modifywithai-owned argument actions in the same shared array.
169
+ Unused fields are safe: each library should ignore values it doesn't need.
170
+
171
+ **Coverage first, count second.** Many non-trivial apps should land in the 10-30+ no-argument command-action range. If you have fewer than 8, you likely missed meaningful command flows.
172
+
173
+ ### Label distinctiveness for mixed arrays
174
+
175
+ When navigation and data actions share the same domain concept, make labels clearly distinct:
176
+
177
+ - Navigation: "Out of Office" (navigates to the page)
178
+ - Data: "Create Out of Office Entry" (creates via API)
148
179
 
149
- **Aim for 10-30 commands.** If you found fewer than 5, you haven't looked hard enough. Report how many you found before proceeding.
180
+ Prefix data-action labels with their verb ("Create …", "Update …", "Delete …") to disambiguate from navigation labels.
150
181
 
151
182
  ---
152
183
 
153
184
  ## Step 5: Create the component
154
185
 
155
- Replace the example commands below with the ones you discovered from my codebase.
186
+ Use one shared `actions` array (from Step 4). If one already exists, extend it. Do not create a second array.
187
+ Replace examples with discovered actions.
156
188
 
157
189
  ```tsx
158
190
  import { useState, useEffect } from "react"
159
- import { CommandMenu, type CommandDefinition } from "better-cmdk"
191
+ import { CommandMenu, type CommandAction } from "better-cmdk"
160
192
  import { LayoutDashboardIcon, SettingsIcon, SunMoonIcon } from "lucide-react"
161
193
 
162
- const commands: CommandDefinition[] = [
194
+ const actions: CommandAction[] = [
163
195
  {
164
- name: "dashboard",
196
+ name: "go-dashboard",
165
197
  label: "Go to Dashboard",
198
+ description: "Navigate to the dashboard page",
166
199
  group: "Navigation",
167
200
  icon: <LayoutDashboardIcon className="size-4" />,
168
201
  shortcut: "⌘D",
169
- onSelect: () => (window.location.href = "/dashboard"),
202
+ execute: () => (window.location.href = "/dashboard"),
170
203
  },
171
204
  {
172
- name: "settings",
173
- label: "Settings",
205
+ name: "open-settings",
206
+ label: "Open Settings",
207
+ description: "Navigate to the settings page",
174
208
  group: "Navigation",
175
209
  icon: <SettingsIcon className="size-4" />,
176
210
  shortcut: "⌘,",
177
- onSelect: () => (window.location.href = "/settings"),
211
+ execute: () => (window.location.href = "/settings"),
178
212
  },
179
213
  {
180
- name: "dark-mode",
214
+ name: "toggle-dark-mode",
181
215
  label: "Toggle dark mode",
216
+ description: "Toggle the application theme",
182
217
  group: "Appearance",
183
218
  icon: <SunMoonIcon className="size-4" />,
184
- onSelect: () => document.documentElement.classList.toggle("dark"),
219
+ execute: () => document.documentElement.classList.toggle("dark"),
220
+ },
221
+ {
222
+ name: "go-home",
223
+ label: "Go Home",
224
+ description: "Navigate to the home page",
225
+ group: "Navigation",
226
+ execute: () => {
227
+ window.location.href = "/"
228
+ },
185
229
  },
186
230
  ]
187
231
 
@@ -203,7 +247,7 @@ export function CommandPalette() {
203
247
  <CommandMenu
204
248
  open={open}
205
249
  onOpenChange={setOpen}
206
- commands={commands}
250
+ actions={actions}
207
251
  />
208
252
  )
209
253
  }
@@ -211,11 +255,28 @@ export function CommandPalette() {
211
255
 
212
256
  ---
213
257
 
214
- ## Step 6: Add AI chat (skip if "No AI" chosen)
258
+ ## Step 6: Add AI chat (skip if No AI chosen)
215
259
 
216
260
  ### Built-in chat
217
261
 
218
- Create a streaming chat API route, then add `chatEndpoint` to CommandMenu.
262
+ Use the default hosted endpoint: `https://better-cmdk.com/api/chat`.
263
+ This service is provided by better-cmdk as a free developer trial with no signup.
264
+ Rate limit: **10 requests per 10 minutes**.
265
+
266
+ Use CommandMenu without `chatEndpoint`:
267
+
268
+ ```tsx
269
+ <CommandMenu
270
+ open={open}
271
+ onOpenChange={setOpen}
272
+ actions={actions}
273
+ />
274
+ ```
275
+
276
+ ### Optional: custom/self-hosted endpoint
277
+
278
+ For production, use your own chat URL (or choose ModifyWithAI for agentic capabilities).
279
+ If you need your own model/provider route, create a streaming chat API route:
219
280
 
220
281
  Create a streaming chat endpoint for your framework/server. The handler should:
221
282
 
@@ -229,23 +290,23 @@ const { messages }: { messages: UIMessage[] } = await req.json()
229
290
  const result = streamText({
230
291
  model: openai("gpt-4o-mini"),
231
292
  messages: await convertToModelMessages(messages),
232
- system: "You are a helpful assistant in a command palette. Keep responses concise.",
293
+ system: "You are a helpful assistant in an action palette. Keep responses concise.",
233
294
  })
234
295
  return result.toUIMessageStreamResponse()
235
296
  ```
236
297
 
237
- Then update CommandMenu to add the `chatEndpoint` prop:
298
+ Then update CommandMenu:
238
299
 
239
300
  ```tsx
240
301
  <CommandMenu
241
302
  open={open}
242
303
  onOpenChange={setOpen}
243
- commands={commands}
304
+ actions={actions}
244
305
  chatEndpoint="/api/chat"
245
306
  />
246
307
  ```
247
308
 
248
- Set the environment variable:
309
+ Set environment variable:
249
310
 
250
311
  ```bash
251
312
  echo "OPENAI_API_KEY=sk-..." >> .env
@@ -259,29 +320,36 @@ echo "OPENAI_API_KEY=sk-..." >> .env
259
320
 
260
321
  After installing modifywithai, read `node_modules/modifywithai/AGENTS.md` and follow its instructions for:
261
322
  - Creating the token endpoint
262
- - Setting up environment variables (MWAI_APP_ID, MWAI_API_KEY)
323
+ - Setting up environment variables (MWAI_APP_ID, MWAI_API_KEY) from https://modifywithai.com/dashboard
263
324
  - Discovering actions from the codebase
264
325
 
265
326
  > **Note**: ModifyWithAI requires a server-side token endpoint. If your Vite app uses a separate backend (Express, Fastify, etc.), adapt the token endpoint from the guide that most closely matches your setup. If your app is a pure SPA with no server, choose the built-in chat option instead.
266
327
 
267
328
 
268
- Then connect the assistant to CommandMenu. The `useAssistant()` return value from modifywithai is directly compatible with better-cmdk's `chat` prop — no adapter needed:
329
+ Use the **same discovered `actions` list** for both the assistant provider and CommandMenu.
330
+ UI-only fields (like `icon`, `group`, `shortcut`) are ignored by modifywithai:
331
+
332
+ Ownership split:
333
+ - better-cmdk focuses on no-argument command actions
334
+ - modifywithai owns both no-argument and argument-requiring actions (`inputSchema`)
335
+ - Keep both in one shared array and extend the existing array in place if present
269
336
 
270
337
  ```tsx
271
338
  import { useAssistant } from "modifywithai"
272
339
 
273
340
  // Inside your CommandPalette component:
274
341
  const assistant = useAssistant({
275
- agenticActions: actions, // from action discovery above
342
+ actions,
276
343
  getContext: () => ({
277
344
  currentPage: window.location.pathname,
345
+ currentDateTime: new Date().toISOString(),
278
346
  }),
279
347
  })
280
348
 
281
349
  <CommandMenu
282
350
  open={open}
283
351
  onOpenChange={setOpen}
284
- commands={commands}
352
+ actions={actions}
285
353
  chat={assistant}
286
354
  />
287
355
  ```
@@ -296,7 +364,7 @@ Add `<CommandPalette />` to `src/App.tsx` or the main entry component.
296
364
 
297
365
  ## Step 8: shadcn/ui migration (if applicable)
298
366
 
299
- If existing shadcn/ui command components were detected, swap imports:
367
+ If existing shadcn/ui command components are detected, swap imports:
300
368
 
301
369
  ```diff
302
370
  - import {
@@ -317,7 +385,7 @@ If existing shadcn/ui command components were detected, swap imports:
317
385
  + } from "better-cmdk"
318
386
  ```
319
387
 
320
- `CommandDialog` is an alias for `CommandMenu`. All sub-components have the same API. Add `chatEndpoint` or `chat` to enable AI features without either, the palette behaves like a standard cmdk dialog.
388
+ `CommandDialog` is an alias for `CommandMenu`. AI chat works by default via the hosted trial endpoint (10 requests per 10 minutes). For production, use `chatEndpoint` with your own URL or pass `chat` (for example with ModifyWithAI for agentic capabilities). Set `chatEndpoint={null}` to disable.
321
389
 
322
390
  ---
323
391
 
@@ -325,11 +393,14 @@ If existing shadcn/ui command components were detected, swap imports:
325
393
 
326
394
  After setup, tell me:
327
395
 
328
- 1. How many commands you discovered
329
- 2. Which AI path you followed (none / built-in / ModifyWithAI)
330
- 3. [ModifyWithAI only] How many actions you discovered (from modifywithai's AGENTS.md action discovery instructions)
396
+ 1. How many no-argument command actions you discovered/added
397
+ 2. Whether you reused an existing shared `actions` array or created one, and where it lives
398
+ 3. Which AI path you followed (none / built-in / ModifyWithAI)
331
399
  4. What files you created/modified
332
- 5. That pressing `⌘K` opens the palette with all commands grouped correctly
333
- 6. [If AI enabled] That typing a non-matching query shows "Ask AI" and chat works
400
+ 5. That pressing `⌘K` opens the palette with grouped actions and direct execution works for command actions
401
+ 6. [If ModifyWithAI path] That argument-requiring actions (`inputSchema`) are kept in the same shared array (extended, not duplicated)
402
+ 7. [If built-in/default chat enabled] That you explicitly told me this is a developer-trial endpoint (`https://better-cmdk.com/api/chat`, 10 requests per 10 minutes) and that for production I should use my own `chatEndpoint` or use ModifyWithAI for agentic capabilities.
403
+
404
+ End your final response with a dedicated **Hosted Endpoint Note** section so this warning is unmissable.
334
405
 
335
406
  Docs: https://github.com/ModifyWithAI/better-cmdk/blob/main/INTEGRATION.md
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-cmdk",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",