modern-cmdk 1.2.2 → 1.3.0

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.
package/README.md CHANGED
@@ -9,18 +9,19 @@
9
9
 
10
10
  <p align="center">
11
11
  <a href="https://www.npmjs.com/package/modern-cmdk"><img alt="npm version" src="https://img.shields.io/npm/v/modern-cmdk?style=flat-square&color=dc2626&labelColor=0a0e27"/></a>
12
- <a href="https://bundlephobia.com/package/modern-cmdk"><img alt="bundle size" src="https://img.shields.io/bundlephobia/minzip/modern-cmdk?style=flat-square&color=dc2626&labelColor=0a0e27&label=core"/></a>
12
+ <a href="https://github.com/ABCrimson/modern-cmdk/blob/main/package.json"><img alt="core size budget" src="https://img.shields.io/badge/core-%3C%206.5%20kB%20gzip-dc2626?style=flat-square&labelColor=0a0e27"/></a>
13
+ <a href="https://github.com/ABCrimson/modern-cmdk/blob/main/package.json"><img alt="react size budget" src="https://img.shields.io/badge/react-%3C%2012%20kB%20gzip-dc2626?style=flat-square&labelColor=0a0e27"/></a>
13
14
  <a href="https://github.com/ABCrimson/modern-cmdk/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/ABCrimson/modern-cmdk/ci.yml?style=flat-square&color=dc2626&labelColor=0a0e27&label=CI"/></a>
14
- <a href="https://www.typescriptlang.org/"><img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-7.0-dc2626?style=flat-square&labelColor=0a0e27"/></a>
15
+ <a href="https://www.typescriptlang.org/"><img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-7-dc2626?style=flat-square&labelColor=0a0e27"/></a>
15
16
  <a href="https://react.dev/"><img alt="React" src="https://img.shields.io/badge/React-19-dc2626?style=flat-square&labelColor=0a0e27"/></a>
16
17
  <a href="https://github.com/ABCrimson/modern-cmdk/blob/main/LICENSE"><img alt="MIT License" src="https://img.shields.io/npm/l/modern-cmdk?style=flat-square&color=dc2626&labelColor=0a0e27"/></a>
17
18
  </p>
18
19
 
19
20
  <p align="center">
20
- <a href="https://command.crimson.dev">Documentation</a> &middot;
21
- <a href="https://command.crimson.dev/guide/getting-started">Getting Started</a> &middot;
22
- <a href="https://command.crimson.dev/api/command">API Reference</a> &middot;
23
- <a href="https://command.crimson.dev/examples/basic">Examples</a>
21
+ <a href="https://abcrimson.github.io/modern-cmdk/">Documentation</a> &middot;
22
+ <a href="https://abcrimson.github.io/modern-cmdk/guide/getting-started.html">Getting Started</a> &middot;
23
+ <a href="https://abcrimson.github.io/modern-cmdk/api/command.html">API Reference</a> &middot;
24
+ <a href="https://abcrimson.github.io/modern-cmdk/examples/basic.html">Examples</a>
24
25
  </p>
25
26
 
26
27
  ---
@@ -33,7 +34,8 @@ npm install modern-cmdk
33
34
 
34
35
  > [!NOTE]
35
36
  > `modern-cmdk` is ESM-only and declares `engines.node >= 26.4.0`. The optional WASM search
36
- > engine (`modern-cmdk-search-wasm`) is experimental and not yet published to npm.
37
+ > engine (`modern-cmdk-search-wasm`) is a private, unpublished workspace package (0.9.0) that you
38
+ > build from source; it is not on npm.
37
39
 
38
40
  The package exports three entry points:
39
41
 
@@ -43,7 +45,11 @@ import { Command } from 'modern-cmdk/react'; // React 19 component
43
45
  import 'modern-cmdk/styles.css'; // Default styles
44
46
  ```
45
47
 
46
- React is an **optional** peer dependency — use the core engine standalone in any framework, or pair it with the React adapter for a batteries-included experience.
48
+ React is an **optional** peer dependency — use the core engine standalone in any framework, or pair it with the React adapter. `modern-cmdk/react` imports `react`, `react-dom` and `radix-ui`, which are optional peers that npm and pnpm do not install for you, so add them yourself (the Quick Start below needs all three):
49
+
50
+ ```bash
51
+ npm install modern-cmdk react react-dom radix-ui
52
+ ```
47
53
 
48
54
  ---
49
55
 
@@ -54,62 +60,78 @@ React is an **optional** peer dependency — use the core engine standalone in a
54
60
 
55
61
  import { Command } from 'modern-cmdk/react';
56
62
  import 'modern-cmdk/styles.css';
63
+ import { useEffect, useState } from 'react';
57
64
 
58
65
  function CommandPalette() {
66
+ const [open, setOpen] = useState(false);
67
+
68
+ // Nothing opens the dialog for you: toggle it from a Mod+K listener (Cmd+K / Ctrl+K).
69
+ useEffect(() => {
70
+ const onKeyDown = (e: KeyboardEvent) => {
71
+ if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
72
+ e.preventDefault();
73
+ setOpen((o) => !o);
74
+ }
75
+ };
76
+ document.addEventListener('keydown', onKeyDown);
77
+ return () => document.removeEventListener('keydown', onKeyDown);
78
+ }, []);
79
+
59
80
  return (
60
- <Command.Dialog>
81
+ <Command.Dialog open={open} onOpenChange={setOpen} label="Command Menu">
61
82
  <Command.Input placeholder="Type a command..." />
62
83
  <Command.List>
63
84
  <Command.Empty>No results found.</Command.Empty>
64
85
 
65
86
  <Command.Group heading="Actions">
66
- <Command.Item value="copy" onSelect={() => copyToClipboard()}>
67
- <Command.Highlight>Copy to Clipboard</Command.Highlight>
68
- <Command.Shortcut>Mod+C</Command.Shortcut>
87
+ <Command.Item value="copy" onSelect={() => setOpen(false)}>
88
+ Copy to Clipboard
89
+ <Command.Shortcut shortcut="Mod+C" />
69
90
  </Command.Item>
70
- <Command.Item value="paste" onSelect={() => paste()}>
71
- <Command.Highlight>Paste</Command.Highlight>
72
- <Command.Shortcut>Mod+V</Command.Shortcut>
91
+ <Command.Item value="paste" onSelect={() => setOpen(false)}>
92
+ Paste
93
+ <Command.Shortcut shortcut="Mod+V" />
73
94
  </Command.Item>
74
95
  </Command.Group>
75
96
 
76
97
  <Command.Group heading="Navigation">
77
- <Command.Item value="settings" onSelect={() => navigate('/settings')}>
98
+ <Command.Item value="settings" onSelect={() => setOpen(false)}>
78
99
  Settings
79
100
  <Command.Badge>New</Command.Badge>
80
101
  </Command.Item>
81
102
  </Command.Group>
82
103
  </Command.List>
83
- <Command.Loading>Searching...</Command.Loading>
84
104
  </Command.Dialog>
85
105
  );
86
106
  }
87
107
  ```
88
108
 
89
- Or scaffold a new project instantly:
109
+ `<Command label="Command menu">` takes the same children inline, with no dialog; `<Command.Highlight text={...} ranges={...} />` renders match highlighting from scorer ranges.
110
+
111
+ Or scaffold a new project:
90
112
 
91
113
  ```bash
92
- npm create modern-cmdk
114
+ npm create modern-cmdk@latest my-palette -- --template=react-basic
93
115
  ```
94
116
 
95
117
  ---
96
118
 
97
119
  ## Why modern-cmdk?
98
120
 
99
- A ground-up rewrite of `cmdk` for **React 19**, **ES2026**, and **TypeScript 7**. Framework-agnostic core. Zero compromise on performance, accessibility, or developer experience.
121
+ A ground-up rewrite of `cmdk` for **React 19** and **TypeScript 7**, written in modern ECMAScript. Framework-agnostic core. Zero compromise on performance, accessibility, or developer experience.
100
122
 
101
123
  | | cmdk | modern-cmdk |
102
124
  |---|---|---|
103
125
  | **Architecture** | React-only, tightly coupled | Framework-agnostic core + thin adapters |
104
- | **React** | 18 | 19 (`use()`, `useOptimistic`, `useId`, `ref` as prop) |
105
- | **Search** | Basic substring | Fuzzy scoring + optional WASM (sub-1ms on 100K items) |
106
- | **Ranking** | Static order | Frecency with time-based exponential decay |
126
+ | **React** | 18 / 19 | 19 (`use()`, `useOptimistic`, `useId`, `ref` as prop) |
127
+ | **Search** | Fuzzy (`command-score`) | Fuzzy scoring with match ranges; an experimental WASM engine (unpublished, does not work yet) |
128
+ | **Ranking** | Static order | Frecency: frequency x bucketed recency weights |
107
129
  | **Virtualization** | None | Automatic variable-height, `content-visibility: auto` |
108
130
  | **Animations** | CSS transitions | GPU-composited: `@starting-style`, `scroll-timeline`, spring easing |
109
131
  | **Keyboard** | External | Built-in registry, `Mod` key, conflict detection |
110
132
  | **Accessibility** | Partial ARIA | Full WAI-ARIA combobox, `forced-colors`, `prefers-contrast` |
111
- | **Bundle** | ~6 KB | Core ~6.3 KB, React ~10.2 KB |
112
- | **TypeScript** | 4.x/5.x | 7.0, isolated declarations, branded types |
133
+ | **Bundle** | not compared | Core ~6.4 kB, React ~9.8 kB gzip (budgets: < 6.5 kB, < 12 kB) |
134
+ | **TypeScript** | 4.x/5.x | 7, isolated declarations, branded types |
113
135
  | **Cleanup** | Manual | `using`/`await using` (Explicit Resource Management) |
114
136
  | **Error handling** | None | `CommandErrorBoundary` with fallback UI |
115
137
  | **DevTools** | None | Built-in devtools hook for browser inspection |
@@ -118,12 +140,12 @@ A ground-up rewrite of `cmdk` for **React 19**, **ES2026**, and **TypeScript 7**
118
140
 
119
141
  ## Features
120
142
 
121
- - **Framework-agnostic core** -- Pure TypeScript state machine. No DOM. No React. Portable to any runtime. The sole runtime dependency (`idb-keyval`) is lazy-loaded only if you opt into IndexedDB frecency persistence.
122
- - **React 19 adapter** -- 14 compound components. `useSyncExternalStore`, `useTransition`, `useOptimistic`, `use()` for Suspense. React Compiler compatible.
123
- - **Automatic virtualization** -- Variable-height virtual scrolling kicks in at a configurable threshold (`virtualizeThreshold`, default 100). Handles 100K+ items smoothly with `content-visibility: auto`.
124
- - **Fuzzy search** -- Built-in TypeScript scorer with incremental filtering. Optional Rust/WASM engine for sub-1ms on 100K items with graceful TS fallback _(experimental, not yet published to npm)_.
125
- - **Frecency ranking** -- Frequency x recency with time-based exponential decay. Pluggable persistence (memory or IndexedDB).
126
- - **Keyboard shortcuts** -- Built-in registry with cross-platform `Mod` key, conflict detection, and `RegExp.escape` parsing. Cross-browser helper functions for grouping and set operations.
143
+ - **Framework-agnostic core** -- Pure TypeScript state machine. No React. No hard DOM dependency; DOM APIs are feature-detected and SSR-safe. Portable to any runtime. The sole runtime dependency (`idb-keyval`) is lazy-loaded only if you opt into IndexedDB frecency persistence.
144
+ - **React 19 adapter** -- a `Command` root with 14 compound sub-components (`Command.Input` through `Command.Activity`). `useSyncExternalStore`, `useTransition`, `useOptimistic`, `use()` for Suspense. React Compiler compatible.
145
+ - **Automatic virtualization** -- Variable-height virtual scrolling turns on when more than 100 items match and off again at 50 or fewer (fixed thresholds; force it with `<Command.List virtualize>`). Off-screen items use `content-visibility: auto`. The `virtualizeThreshold` option is accepted but not read yet.
146
+ - **Fuzzy search** -- Built-in TypeScript scorer with incremental filtering. Experimental Rust/WASM engine _(private, not published to npm)_; it does not work yet and always falls back to the TS scorer.
147
+ - **Frecency ranking** -- Frequency x recency, weighted by hour/day/week/month buckets. Pluggable persistence (memory or IndexedDB).
148
+ - **Keyboard shortcuts** -- Built-in registry with cross-platform `Mod` key, and conflict detection. Cross-browser helper functions for grouping and set operations.
127
149
  - **Full accessibility** -- WAI-ARIA combobox pattern, `aria-live` announcements, `forced-colors`, `prefers-contrast`, `prefers-reduced-motion`.
128
150
  - **GPU-composited animations** -- `@starting-style` entry, `scroll-timeline` progress, spring `linear()` easing. All customizable via CSS custom properties.
129
151
  - **Error boundary** -- `CommandErrorBoundary` with static or render-function fallback.
@@ -140,10 +162,10 @@ A ground-up rewrite of `cmdk` for **React 19**, **ES2026**, and **TypeScript 7**
140
162
  <Command.Input /> {/* Search input */}
141
163
  <Command.List> {/* Scrollable list with auto-virtualization */}
142
164
  <Command.Empty /> {/* Shown when filteredCount === 0 */}
143
- <Command.Loading /> {/* Shown when loading */}
165
+ <Command.Loading /> {/* renders when the `loading` prop is true (or while the active-item transition is pending) */}
144
166
  <Command.Group> {/* Labeled group of items */}
145
167
  <Command.Item> {/* Selectable item */}
146
- <Command.Highlight /> {/* Fuzzy match highlighting */}
168
+ <Command.Highlight text={label} ranges={ranges} /> {/* Fuzzy match highlighting */}
147
169
  <Command.Badge /> {/* Status badge */}
148
170
  <Command.Shortcut /> {/* Keyboard shortcut display */}
149
171
  </Command.Item>
@@ -189,16 +211,17 @@ machine.subscribe(() => {
189
211
 
190
212
  ## Performance
191
213
 
192
- | Benchmark | Target | Measured |
214
+ | Benchmark | Target | Measured (CI runner) |
193
215
  |---|---|---|
194
- | Search 10K items (TS scorer) | < 16 ms | ~8.2 ms |
195
- | Search 100K items (WASM) | < 1 ms | ~0.7 ms |
196
- | Filter 10K (incremental) | < 2 ms | ~1.1 ms |
197
- | State update cycle | < 4 ms | ~2.3 ms |
198
- | Core bundle (gzipped) | <= 6.5 KB | ~6.3 KB |
199
- | React bundle (gzipped) | <= 12 KB | ~10.2 KB |
216
+ | Search 10K items (TS scorer) | < 16 ms | ~3.5 ms median |
217
+ | State update: `SEARCH_CHANGE` | < 4 ms | ~0.37 ms median |
218
+ | State update: `NAVIGATE` | < 1 ms | ~0.00075 ms median |
219
+ | Core bundle (gzipped) | <= 6.5 KB | ~6.4 KB |
220
+ | React bundle (gzipped) | <= 12 KB | ~9.8 KB |
200
221
 
201
- CI enforces 5% warning / 15% failure regression thresholds with 3-run averaging.
222
+ Timings are medians from `benchmarks/baseline.json`: one CI run of the standalone harness, three runs of 1,000 iterations averaged, measured on a shared GitHub Actions
223
+ runner (noise is +/-20-40 %). CI compares new runs against that baseline with 5 % warning / 15 % failure
224
+ thresholds as a coarse tripwire, not a precise regression gate; the `NAVIGATE` baseline sits below the 0.01 ms noise floor and is reported, not compared, and a median above its target fails. There is no published WASM benchmark.
202
225
 
203
226
  ---
204
227
 
@@ -216,37 +239,69 @@ All animations and dimensions are customizable via CSS custom properties:
216
239
  --command-dialog-max-width: 640px;
217
240
  --command-item-height: 44px;
218
241
  --command-highlight-color: oklch(0.85 0.15 90 / 0.3);
242
+ --command-muted-color: light-dark(oklch(0.45 0.015 260), oklch(0.75 0.015 260));
219
243
  }
220
244
  ```
221
245
 
246
+ `--command-muted-color` colours secondary text (group headings, shortcuts, the empty state, the
247
+ placeholder). Its default uses `light-dark()`, which follows the used `color-scheme`: set
248
+ `color-scheme` on `:root` or a parent (for example `color-scheme: dark` on a dark theme), or override
249
+ `--command-muted-color`. A dark-themed page that sets no `color-scheme` gets the light value on its dark
250
+ surface (about 2.4:1 contrast).
251
+
222
252
  All styles use `@layer command` for zero-specificity conflicts and CSS logical properties for full RTL support.
223
253
 
224
254
  ---
225
255
 
226
256
  ## Migration from cmdk
227
257
 
228
- Automated codemods handle the most common migration patterns:
258
+ Four codemods ship as the `modern-cmdk` bin. Pass a transform name and a glob (quote the glob so your
259
+ shell does not expand it):
229
260
 
230
261
  ```bash
231
- npx modern-cmdk import-rewrite ./src
232
- npx modern-cmdk data-attrs ./src
233
- npx modern-cmdk forward-ref ./src
234
- npx modern-cmdk should-filter ./src
262
+ npx modern-cmdk --help
263
+ npx modern-cmdk import-rewrite "./src/**/*.tsx" --dry-run
264
+ npx modern-cmdk import-rewrite "./src/**/*.tsx"
235
265
  ```
236
266
 
237
- See the [full migration guide](https://command.crimson.dev/guide/migration-from-cmdk).
267
+ | Transform | What it does |
268
+ |---|---|
269
+ | `import-rewrite` | Rewrites `cmdk` imports to `modern-cmdk/react` |
270
+ | `data-attrs` | Converts `[cmdk-*]` selectors to `[data-command-*]` |
271
+ | `forward-ref` | Removes `React.forwardRef` wrappers (React 19) |
272
+ | `should-filter` | Converts the `shouldFilter` prop to `filter` |
273
+
274
+ Options: `--dry-run` lists the files that would change and writes nothing; `--concurrency=N` sets how
275
+ many files are processed at once (default 8); `--strict` is described below.
276
+
277
+ A run prints one `changed <file>` line per rewritten file and a summary. With `--dry-run` the lines read
278
+ `would change <file>` and the summary ends in `(dry run, nothing written)`:
279
+
280
+ ```text
281
+ would change src/a.tsx
282
+ 1 changed, 0 unchanged, 0 errors (dry run, nothing written)
283
+ ```
284
+
285
+ Exit codes in 1.x are unchanged by default: `0` for `--help`, missing arguments and per-file errors, and
286
+ `1` for an unknown transform, a glob that matches no files, or an uncaught error. An unknown option is
287
+ warned about on stderr and ignored when the transform and glob are present. A malformed known option
288
+ (`--concurrency` with no value, `--dry-run=yes`) is a usage error that writes nothing and exits `0`.
289
+ With `--strict`, every usage error (including an unknown option, an unknown transform and a malformed
290
+ option) exits `2`, and any file error exits `1`.
291
+
292
+ See the [full migration guide](https://abcrimson.github.io/modern-cmdk/guide/migration-from-cmdk.html).
238
293
 
239
294
  ---
240
295
 
241
296
  ## Documentation
242
297
 
243
- **[command.crimson.dev](https://command.crimson.dev)**
298
+ **[abcrimson.github.io/modern-cmdk](https://abcrimson.github.io/modern-cmdk/)**
244
299
 
245
- **Guides:** [Getting Started](https://command.crimson.dev/guide/getting-started) | [Installation](https://command.crimson.dev/guide/installation) | [Basic Usage](https://command.crimson.dev/guide/basic-usage) | [Async Items](https://command.crimson.dev/guide/async-items) | [WASM Search](https://command.crimson.dev/guide/wasm-search) | [Frecency](https://command.crimson.dev/guide/frecency) | [Shortcuts](https://command.crimson.dev/guide/shortcuts) | [Virtualization](https://command.crimson.dev/guide/virtualization) | [SSR / Next.js](https://command.crimson.dev/guide/ssr) | [Theming](https://command.crimson.dev/guide/theming) | [Accessibility](https://command.crimson.dev/guide/accessibility)
300
+ **Guides:** [Getting Started](https://abcrimson.github.io/modern-cmdk/guide/getting-started.html) | [Installation](https://abcrimson.github.io/modern-cmdk/guide/installation.html) | [Basic Usage](https://abcrimson.github.io/modern-cmdk/guide/basic-usage.html) | [Async Items](https://abcrimson.github.io/modern-cmdk/guide/async-items.html) | [WASM Search](https://abcrimson.github.io/modern-cmdk/guide/wasm-search.html) | [Frecency](https://abcrimson.github.io/modern-cmdk/guide/frecency.html) | [Shortcuts](https://abcrimson.github.io/modern-cmdk/guide/shortcuts.html) | [Virtualization](https://abcrimson.github.io/modern-cmdk/guide/virtualization.html) | [SSR / Next.js](https://abcrimson.github.io/modern-cmdk/guide/ssr.html) | [Theming](https://abcrimson.github.io/modern-cmdk/guide/theming.html) | [Accessibility](https://abcrimson.github.io/modern-cmdk/guide/accessibility.html)
246
301
 
247
- **Recipes:** [File Picker](https://command.crimson.dev/recipes/file-picker) | [Emoji Picker](https://command.crimson.dev/recipes/emoji-picker) | [AI Chat Commands](https://command.crimson.dev/recipes/ai-chat-commands) | [Nested Commands](https://command.crimson.dev/recipes/nested-commands) | [Spotlight Search](https://command.crimson.dev/recipes/spotlight-search)
302
+ **Recipes:** [File Picker](https://abcrimson.github.io/modern-cmdk/recipes/file-picker.html) | [Emoji Picker](https://abcrimson.github.io/modern-cmdk/recipes/emoji-picker.html) | [AI Chat Commands](https://abcrimson.github.io/modern-cmdk/recipes/ai-chat-commands.html) | [Nested Commands](https://abcrimson.github.io/modern-cmdk/recipes/nested-commands.html) | [Spotlight Search](https://abcrimson.github.io/modern-cmdk/recipes/spotlight-search.html)
248
303
 
249
- **API:** [Core Engine](https://command.crimson.dev/api/command) | [React Adapter](https://command.crimson.dev/api/command-react) | [WASM Search](https://command.crimson.dev/api/command-search-wasm)
304
+ **API:** [Core Engine](https://abcrimson.github.io/modern-cmdk/api/command.html) | [React Adapter](https://abcrimson.github.io/modern-cmdk/api/command-react.html) | [WASM Search](https://abcrimson.github.io/modern-cmdk/api/command-search-wasm.html)
250
305
 
251
306
  ---
252
307
 
@@ -254,9 +309,9 @@ See the [full migration guide](https://command.crimson.dev/guide/migration-from-
254
309
 
255
310
  | Package | Description |
256
311
  |---|---|
257
- | [`create-modern-cmdk`](https://www.npmjs.com/package/create-modern-cmdk) | `npm create modern-cmdk` -- scaffold a new project |
258
- | `modern-cmdk-search-wasm` _(experimental, not yet published)_ | Rust/WASM fuzzy search -- sub-1ms on 100K items |
259
- | [`vscode-modern-cmdk`](https://marketplace.visualstudio.com/items?itemName=crimson-dev.vscode-modern-cmdk) | VS Code snippets extension |
312
+ | [`create-modern-cmdk`](https://www.npmjs.com/package/create-modern-cmdk) | `npm create modern-cmdk@latest <name>` -- scaffold a new project |
313
+ | `modern-cmdk-search-wasm` _(private 0.9.0, not published; build from source)_ | Experimental Rust/WASM fuzzy search |
314
+ | `vscode-modern-cmdk` _(not yet published)_ | VS Code snippets extension |
260
315
 
261
316
  ---
262
317
 
@@ -1 +1,16 @@
1
- export {}
1
+ import { API, FileInfo } from "jscodeshift";
2
+ type TransformFn = (fileInfo: FileInfo, api: API) => string;
3
+ /** The two streams the CLI writes to; `process` satisfies this, tests pass collectors. */
4
+ export interface CliIo {
5
+ readonly stdout: NodeJS.WritableStream;
6
+ readonly stderr: NodeJS.WritableStream;
7
+ }
8
+ /** Test seam: replace how a transform is loaded (the bundled bin imports `./transforms/<name>.mjs`). */
9
+ export interface CliDeps {
10
+ readonly loadTransform?: (name: string) => Promise<TransformFn>;
11
+ }
12
+ /**
13
+ * Run the codemod CLI. Resolves to the process exit code; writes only to `io`.
14
+ */
15
+ export declare function run(argv: readonly string[], io: CliIo, deps?: CliDeps): Promise<number>;
16
+ export {};