experiments in a post-browser web
1# Cmd Extension
2
3Command palette for quick command access via keyboard shortcut.
4
5## Overview
6
7The cmd extension provides a command palette interface accessible via a global keyboard shortcut (default: `Alt+Space`). Commands can be typed, selected from a dropdown, and executed. Commands from other extensions can be registered with the cmd system.
8
9## Features
10
11- Global keyboard shortcut for quick access
12- Type-ahead filtering with adaptive matching
13- Command chaining with typed data flow (MIME types)
14- Preview pane for viewing command output
15- Output selection mode for array results
16
17## Command Chaining
18
19Commands can be composed into pipelines where the output of one command becomes the input of the next. This enables powerful data transformation workflows.
20
21### Example Flow
22
231. Run `lists` command → produces JSON array output
242. Select an item from the output list (arrow keys + Enter)
253. Run `csv` command → converts JSON to CSV format
264. Run `save` command → prompts to save the file
27
28### How It Works
29
30Commands declare what MIME types they accept and produce:
31
32```javascript
33export default {
34 name: 'csv',
35 description: 'Convert JSON to CSV format',
36 accepts: ['application/json'], // Input types this command handles
37 produces: ['text/csv'], // Output type this command generates
38
39 execute: async (ctx) => {
40 // ctx.input - data from previous command
41 // ctx.inputMimeType - MIME type of input
42 // ctx.inputTitle - human-readable title
43
44 return {
45 success: true,
46 output: {
47 data: csvString,
48 mimeType: 'text/csv',
49 title: 'CSV Output'
50 }
51 };
52 }
53};
54```
55
56### Command Types
57
58**Producer Commands** - Start chains, produce output
59- `accepts: []` (empty or omitted)
60- `produces: ['application/json']`
61- Example: `lists`
62
63**Transformer Commands** - Accept input, produce output
64- `accepts: ['application/json']`
65- `produces: ['text/csv']`
66- Example: `csv`
67
68**Consumer Commands** - Accept input, end chains
69- `accepts: ['*/*']` (or specific types)
70- `produces: []` (empty or omitted)
71- Example: `save`
72
73### MIME Type Matching
74
75The chaining system supports wildcards:
76- `*/*` - matches any MIME type
77- `text/*` - matches any text type (text/plain, text/csv, etc.)
78- `application/json` - exact match
79
80### Output Selection Mode
81
82When a command produces an array of items, the panel enters "output selection mode":
83- Items are displayed in the results dropdown
84- Navigate with arrow keys (up/down)
85- Select with Enter or Right Arrow
86- The selected item becomes input for the next command
87- ESC exits selection mode
88
89### Chain Mode UI
90
91When in chain mode:
92- A chain indicator shows the current MIME type and title
93- Only commands that accept the current MIME type are shown
94- A preview pane displays the current data
95- ESC exits chain mode first, then closes panel
96
97## Available Commands
98
99### lists
100
101Produces sample list data for chaining demonstration.
102
103```
104lists - produce sample list data
105```
106
107Output: `application/json` array
108
109### csv
110
111Converts JSON data to CSV format.
112
113```
114csv - convert JSON input to CSV
115```
116
117Accepts: `application/json`
118Produces: `text/csv`
119
120### save
121
122Saves data to a file using the native save dialog.
123
124```
125save - save with auto-generated filename
126save myfile.csv - save with specified filename
127```
128
129Accepts: `*/*` (any MIME type)
130Produces: nothing (end of chain)
131
132## Execution Context
133
134Commands receive an execution context object:
135
136```javascript
137{
138 typed: 'csv', // Full typed string
139 name: 'csv', // Command name
140 params: [], // Array of parameters
141 search: null, // Text after command name
142
143 // Chain mode only:
144 input: {...}, // Input data from previous command
145 inputMimeType: 'application/json',
146 inputTitle: 'Sample list',
147 inputSource: 'lists' // Source command name
148}
149```
150
151## Keyboard Shortcuts
152
153| Key | Action |
154|-----|--------|
155| Arrow Down | Show results / navigate down |
156| Arrow Up | Navigate up in results |
157| Enter | Execute selected command / select output item |
158| Tab | Autocomplete command name |
159| ESC | Exit chain mode → close panel |
160| Right Arrow | Select output item (in selection mode) |
161
162## Settings
163
164Configure via Settings UI:
165
166- **Shortcut Key**: Global shortcut to open cmd panel (default: `Alt+Space`)
167- **Width**: Panel window width (default: 600)
168- **Height**: Panel window height (default: 400)
169
170## Registering Commands
171
172Extensions can register commands by publishing to the `cmd:register` topic:
173
174```javascript
175api.publish('cmd:register', {
176 name: 'my-command',
177 description: 'Does something',
178 source: 'my-extension',
179 accepts: ['application/json'],
180 produces: ['text/plain']
181}, api.scopes.GLOBAL);
182```
183
184Or using the commands API:
185
186```javascript
187api.commands.register({
188 name: 'my-command',
189 description: 'Does something',
190 execute: async (ctx) => { ... }
191});
192```
193
194## Architecture
195
196### Files
197
198| File | Purpose |
199|------|---------|
200| `background.js` | Command registry, shortcut handling, save file coordination |
201| `panel.js` | Panel UI, chain mode logic, output selection, preview rendering |
202| `panel.html` | Panel layout and styles |
203| `commands.js` | Command proxy/dispatch to background |
204| `config.js` | Extension configuration and defaults |
205| `download.html` | Save dialog window (non-modal for native dialog) |
206| `commands/lists.js` | Lists command implementation |
207| `commands/csv.js` | CSV converter command |
208| `commands/save.js` | File save command |
209
210### Provider Pattern
211
212The cmd extension uses the Provider pattern:
213- Owns the command registry
214- Subscribes to `cmd:register`, `cmd:unregister` for command management
215- Subscribes to `cmd:query` for late-arriving consumers
216- Publishes `cmd:ready` when fully initialized
217
218### Save Dialog Flow
219
220The save command uses a separate window approach to avoid modal blur issues:
221
2221. `save` command publishes `cmd:save-file` to background
2232. Background stores data in `pendingDownloads` Map
2243. Background opens `download.html` window with download ID
2254. Download window subscribes to `cmd:download-data:{id}`
2265. Download window publishes `cmd:download-ready`
2276. Background sends data to download window
2287. Download window calls `api.files.save()` for native dialog
229
230This approach works because the download window is not modal and doesn't have a blur handler that would close it when the native dialog takes focus.