copa-cli 0.7.1__tar.gz → 0.9.0__tar.gz
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.
- {copa_cli-0.7.1 → copa_cli-0.9.0}/PKG-INFO +273 -158
- copa_cli-0.9.0/README.md +819 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/cli.py +2 -1
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/cli_internal.py +52 -5
- copa_cli-0.9.0/copa/cli_recipe.py +196 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/config.py +38 -58
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/copa.zsh +160 -54
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/db.py +154 -11
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/fzf.py +39 -1
- copa_cli-0.9.0/copa/mcp_server.py +321 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/models.py +72 -1
- copa_cli-0.9.0/copa/scoring.py +73 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/sharing.py +23 -1
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa_cli.egg-info/PKG-INFO +273 -158
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa_cli.egg-info/SOURCES.txt +1 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/pyproject.toml +1 -1
- {copa_cli-0.7.1 → copa_cli-0.9.0}/tests/test_modal.py +64 -82
- copa_cli-0.7.1/README.md +0 -704
- copa_cli-0.7.1/copa/mcp_server.py +0 -159
- copa_cli-0.7.1/copa/scoring.py +0 -45
- {copa_cli-0.7.1 → copa_cli-0.9.0}/LICENSE +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/__init__.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/__main__.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/cli_common.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/cli_llm.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/cli_share.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/evolve.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/history.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/llm.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa/scanner.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa_cli.egg-info/dependency_links.txt +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa_cli.egg-info/entry_points.txt +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa_cli.egg-info/requires.txt +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/copa_cli.egg-info/top_level.txt +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/setup.cfg +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/tests/test_cli_and_sharing.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/tests/test_db.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/tests/test_fzf.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/tests/test_models.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/tests/test_polish.py +0 -0
- {copa_cli-0.7.1 → copa_cli-0.9.0}/tests/test_scanner.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: copa-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Command Palette — smart command tracking, ranking, and sharing for your shell
|
|
5
5
|
Author: Mark Stanford
|
|
6
6
|
License-Expression: MIT
|
|
@@ -36,12 +36,14 @@ Dynamic: license-file
|
|
|
36
36
|
|
|
37
37
|
Copa tracks the commands you run, ranks them by frequency and recency, and gives you instant fuzzy search via fzf. Think of it as a smart, searchable, shareable upgrade to shell history.
|
|
38
38
|
|
|
39
|
+

|
|
40
|
+
|
|
39
41
|
## Features
|
|
40
42
|
|
|
41
|
-
- **Smart ranking** — commands scored by `2*log(1+freq) + 8*0.5^(age/3d)`, so frequent
|
|
43
|
+
- **Smart ranking** — commands scored by `2*log(1+freq) + 8*0.5^(age/3d)`, so frequent _and_ recent commands float to the top
|
|
42
44
|
- **FTS search** — full-text search across commands and their descriptions
|
|
43
|
-
- **fzf integration** — Ctrl+R opens a fuzzy-searchable command palette with preview pane; searches across commands
|
|
44
|
-
- **Tab completion** — Copa supplements zsh's tab completion for
|
|
45
|
+
- **fzf integration** — Ctrl+R opens a fuzzy-searchable command palette with preview pane; searches across commands _and_ their descriptions
|
|
46
|
+
- **Tab completion** — Copa supplements zsh's tab completion for _any_ command using your command history database
|
|
45
47
|
- **Auto-evolution** — `copa evolve` finds your most-used commands from zsh history and promotes them
|
|
46
48
|
- **LLM descriptions** — `copa fix --auto` uses Claude or ollama to generate descriptions for undescribed commands
|
|
47
49
|
- **Script protocol** — `#@ Description:` / `#@ Usage:` / `#@ Purpose:` / `#@ Flag:` headers in your scripts are auto-detected by `copa scan` across all `$PATH` directories
|
|
@@ -49,6 +51,8 @@ Copa tracks the commands you run, ranks them by frequency and recency, and gives
|
|
|
49
51
|
- **Inline suggestions** — ghost text appears as you type; Tab accepts or opens a completion menu with the suggestion highlighted
|
|
50
52
|
- **Groups & Ctrl+G** — organize commands by project, device, or workflow; assign groups inline from the fzf palette with Ctrl+G
|
|
51
53
|
- **Bulk operations** — Ctrl+B enters select mode for batch group assignment, batch deletion, or batch LLM description
|
|
54
|
+
- **Recipes** — save multi-step command sequences as named recipes; `copa recipe run deploy` executes steps sequentially; share recipes via `.copa` files
|
|
55
|
+
- **Directory-aware suggestions** — commands used in the current directory are boosted in suggestions; automatic, configurable, zero-effort
|
|
52
56
|
- **Sharing & `copa create`** — export/import command sets as `.copa` JSON files; `copa create` scaffolds a `.copa` file from an existing group
|
|
53
57
|
- **Set filtering** — scope list, search, and fzf to a specific shared set with `--set`
|
|
54
58
|
- **MCP server** — expose your commands to Claude Code (or any MCP client)
|
|
@@ -96,6 +100,7 @@ copa setup
|
|
|
96
100
|
```
|
|
97
101
|
|
|
98
102
|
This walks you through everything:
|
|
103
|
+
|
|
99
104
|
1. Checks that **fzf** is installed (tells you how to install if missing)
|
|
100
105
|
2. Creates the Copa database (`~/.copa/copa.db`)
|
|
101
106
|
3. Adds shell integration to your `~/.zshrc` (prompts for confirmation)
|
|
@@ -134,6 +139,8 @@ copa sync
|
|
|
134
139
|
|
|
135
140
|
Once shell integration is sourced, pressing **Ctrl+R** opens an fzf-powered command palette instead of the default zsh reverse search. This is Copa's primary interface.
|
|
136
141
|
|
|
142
|
+

|
|
143
|
+
|
|
137
144
|
### What you see
|
|
138
145
|
|
|
139
146
|
Copa pipes every tracked command into fzf with aligned columns:
|
|
@@ -152,38 +159,41 @@ This is the key difference from plain zsh Ctrl+R: you're not just searching raw
|
|
|
152
159
|
|
|
153
160
|
The header shows available modes. Press **Ctrl+R** again while fzf is open to cycle:
|
|
154
161
|
|
|
155
|
-
| Mode
|
|
156
|
-
|
|
157
|
-
| `all`
|
|
158
|
-
| `frequent` | Frequency only
|
|
159
|
-
| `recent`
|
|
162
|
+
| Mode | Sort order | Use case |
|
|
163
|
+
| ---------- | --------------------------- | ------------------------------------ |
|
|
164
|
+
| `all` | Score (frequency + recency) | Default — best commands float to top |
|
|
165
|
+
| `frequent` | Frequency only | Find your most-used commands |
|
|
166
|
+
| `recent` | Last used time | Find commands you ran recently |
|
|
167
|
+
| `recipes` | Run count | Browse and run multi-step recipes |
|
|
160
168
|
|
|
161
169
|
### Keybindings
|
|
162
170
|
|
|
163
171
|
While the fzf palette is open, these keys are available:
|
|
164
172
|
|
|
165
|
-
| Key
|
|
166
|
-
|
|
167
|
-
| **Ctrl+R** | Cycle mode
|
|
168
|
-
| **Ctrl+
|
|
169
|
-
| **Ctrl+
|
|
170
|
-
| **Ctrl+
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
|
175
|
-
|
|
|
176
|
-
| **Ctrl+N** | Cycle group
|
|
177
|
-
| **Ctrl+D** | Describe
|
|
178
|
-
| **Ctrl+F** | Edit flags
|
|
179
|
-
| **Ctrl+B** | Select mode
|
|
180
|
-
| **Ctrl+H** | Toggle header | Show/hide the key hints for more screen space
|
|
181
|
-
| **ESC**
|
|
173
|
+
| Key | Action | Effect |
|
|
174
|
+
| ---------- | -------------------- | ---------------------------------------------------------------------------- |
|
|
175
|
+
| **Ctrl+R** | Cycle mode | all → frequent → recent → recipes → all |
|
|
176
|
+
| **Ctrl+X** | Compose | Opens a numbered menu to append shell operators (`\|`, `&&`, `>`, `&`, etc.) |
|
|
177
|
+
| **Ctrl+S** | Scope by group | Opens inline group list — Enter filters to that group, ESC returns to all |
|
|
178
|
+
| **Ctrl+G** | Assign group | Opens inline group list — Enter assigns the group to the highlighted command |
|
|
179
|
+
|
|
180
|
+

|
|
181
|
+
|
|
182
|
+
| Key | Action | Effect |
|
|
183
|
+
| ---------- | ------------- | ------------------------------------------------------------------- |
|
|
184
|
+
| **Ctrl+N** | Cycle group | Cycles through groups: (all) → group1 → group2 → ... → (all) |
|
|
185
|
+
| **Ctrl+D** | Describe | Generate/edit a description using LLM (with tty-aware input) |
|
|
186
|
+
| **Ctrl+F** | Edit flags | Add flag documentation to the highlighted command |
|
|
187
|
+
| **Ctrl+B** | Select mode | Enter multi-select for bulk operations (see below) |
|
|
188
|
+
| **Ctrl+H** | Toggle header | Show/hide the key hints for more screen space |
|
|
189
|
+
| **ESC** | Cancel/back | In scope/group mode: returns to command list. Otherwise: closes fzf |
|
|
182
190
|
|
|
183
191
|
Keybindings are configurable via `~/.copa/config.toml`. See [Configuration](#configuration).
|
|
184
192
|
|
|
185
193
|
### Select mode (bulk operations)
|
|
186
194
|
|
|
195
|
+

|
|
196
|
+
|
|
187
197
|
Press **Ctrl+B** from the Ctrl+R palette to enter **select mode**. This opens a new fzf view with multi-select enabled:
|
|
188
198
|
|
|
189
199
|
- **Tab** toggles selection on individual commands
|
|
@@ -202,11 +212,11 @@ Selected 5 command(s).
|
|
|
202
212
|
Action:
|
|
203
213
|
```
|
|
204
214
|
|
|
205
|
-
| Action | What it does
|
|
206
|
-
|
|
207
|
-
| **g**
|
|
208
|
-
| **d**
|
|
209
|
-
| **a**
|
|
215
|
+
| Action | What it does |
|
|
216
|
+
| ------ | -------------------------------------------------------------------------------------- |
|
|
217
|
+
| **g** | Assign all selected commands to a group (or clear their group) |
|
|
218
|
+
| **d** | Delete all selected commands (with confirmation) |
|
|
219
|
+
| **a** | Auto-generate descriptions for all selected commands using your configured LLM backend |
|
|
210
220
|
|
|
211
221
|
This is useful for organizing large command sets — select 20 undescribed commands and batch-describe them, or move a set of related commands into a group in one step.
|
|
212
222
|
|
|
@@ -220,18 +230,22 @@ Selecting a command places it directly into your shell prompt (without executing
|
|
|
220
230
|
|
|
221
231
|
## Tab Completion
|
|
222
232
|
|
|
233
|
+

|
|
234
|
+
|
|
223
235
|
Copa supplements zsh's built-in tab completion for **any** command — not just Copa's own CLI. Once `copa.zsh` is sourced, Copa registers as a completer in zsh's completion system.
|
|
224
236
|
|
|
225
237
|
### Completion modes
|
|
226
238
|
|
|
239
|
+

|
|
240
|
+
|
|
227
241
|
Copa supports four completion modes, configured via `~/.copa/config.toml`:
|
|
228
242
|
|
|
229
|
-
| Mode
|
|
230
|
-
|
|
243
|
+
| Mode | Behavior |
|
|
244
|
+
| ---------- | ----------------------------------------------------------------------------- |
|
|
231
245
|
| `fallback` | **(default)** Only show Copa completions when native completers found nothing |
|
|
232
|
-
| `hybrid`
|
|
233
|
-
| `always`
|
|
234
|
-
| `never`
|
|
246
|
+
| `hybrid` | Show Copa completions alongside native completions (in a separate group) |
|
|
247
|
+
| `always` | Copa completions replace native completions |
|
|
248
|
+
| `never` | Disable Copa tab completion entirely |
|
|
235
249
|
|
|
236
250
|
```toml
|
|
237
251
|
# ~/.copa/config.toml
|
|
@@ -269,6 +283,10 @@ Copa's own CLI completions (`copa li<TAB>` → `list`) continue to work as befor
|
|
|
269
283
|
|
|
270
284
|
## Inline Suggestions (Ghost Text)
|
|
271
285
|
|
|
286
|
+
| Tab Mode 1 (direct accept) | Tab Mode 2 (menu select, default) |
|
|
287
|
+
| -------------------------------------------------- | -------------------------------------------------- |
|
|
288
|
+
|  |  |
|
|
289
|
+
|
|
272
290
|
Copa shows grey ghost text after your cursor as you type — the best matching command from your database, ranked by frequency and recency. This works like fish shell's autosuggestions or zsh-autosuggestions, with zero plugin dependencies.
|
|
273
291
|
|
|
274
292
|
### How it works
|
|
@@ -281,43 +299,49 @@ $ git pu█sh origin main ← grey ghost text
|
|
|
281
299
|
|
|
282
300
|
### Keybindings
|
|
283
301
|
|
|
284
|
-
| Key
|
|
285
|
-
|
|
286
|
-
| Type chars
|
|
287
|
-
| Backspace
|
|
288
|
-
| **Tab**
|
|
289
|
-
| **Down**
|
|
290
|
-
| **Right arrow**
|
|
291
|
-
|
|
|
292
|
-
|
|
|
293
|
-
|
|
|
294
|
-
|
|
|
302
|
+
| Key | Suggestion showing | No suggestion |
|
|
303
|
+
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
304
|
+
| Type chars | Insert char, re-fetch suggestion | Insert char, fetch suggestion |
|
|
305
|
+
| Backspace | Delete char, **latch** (suppress suggestions) | Delete char normally |
|
|
306
|
+
| **Tab** | `tab_accept=1`: accept full suggestion. `tab_accept=2` (default): open completion menu with suggestion highlighted at top, native completions below | If latched: unlatch + re-fetch suggestion. Else: normal tab completion |
|
|
307
|
+
| **Down** | Open completion menu with suggestion highlighted at top | History navigation |
|
|
308
|
+
| **Right arrow** | Accept one word, re-fetch | Move cursor right |
|
|
309
|
+
| **Cmd+Right / End** | Accept full suggestion | Move to end of line |
|
|
310
|
+
| Enter | Clear suggestion, execute | Execute |
|
|
311
|
+
| Esc | Dismiss suggestion | Normal Esc |
|
|
312
|
+
| Up | Clear suggestion, navigate history | History navigation |
|
|
313
|
+
| Ctrl+R | Clear suggestion, open fzf | Open fzf |
|
|
295
314
|
|
|
296
315
|
### Tab accept mode
|
|
297
316
|
|
|
298
317
|
Copa supports two Tab behaviors when a suggestion is showing:
|
|
299
318
|
|
|
300
319
|
**Menu select** (`tab_accept = 2`, default):
|
|
320
|
+
|
|
301
321
|
1. Press **Tab** — ghost text clears, a completion menu opens with the Copa suggestion highlighted at the top, alongside native completions below
|
|
302
|
-
2. Press **Tab**
|
|
303
|
-
3. Press **
|
|
304
|
-
4.
|
|
322
|
+
2. Press **Tab** to cycle through options, **Shift+Tab** to cycle backward
|
|
323
|
+
3. Press **Enter** or **Space** — accepts the highlighted item
|
|
324
|
+
4. Press **Escape** — cancels the menu, restores your original text
|
|
325
|
+
5. Use **arrow keys** to navigate if you want a different completion
|
|
305
326
|
|
|
306
327
|
This gives you a chance to see alternatives before committing. The Copa suggestion is always the first item in the menu.
|
|
307
328
|
|
|
308
329
|
**Inline accept** (`tab_accept = 1`):
|
|
330
|
+
|
|
309
331
|
- Press **Tab** — the suggestion is accepted directly into your command line. One keystroke, done.
|
|
310
332
|
|
|
311
333
|
### Completion menu navigation
|
|
312
334
|
|
|
313
335
|
When the completion menu is open (from Tab in `tab_accept = 2` mode or from normal tab completion):
|
|
314
336
|
|
|
315
|
-
| Key
|
|
316
|
-
|
|
317
|
-
| **Tab**
|
|
318
|
-
| **
|
|
319
|
-
| **
|
|
320
|
-
| **
|
|
337
|
+
| Key | Action |
|
|
338
|
+
| -------------- | -------------------------------------------- |
|
|
339
|
+
| **Tab** | Cycle forward through completions |
|
|
340
|
+
| **Shift+Tab** | Cycle backward through completions |
|
|
341
|
+
| **Enter** | Accept the highlighted completion (no trailing space added) |
|
|
342
|
+
| **Space** | Accept the highlighted completion and add a space |
|
|
343
|
+
| **Escape** | Cancel — dismiss menu, restore original text |
|
|
344
|
+
| **Arrow keys** | Navigate between completions |
|
|
321
345
|
|
|
322
346
|
### Backspace latch
|
|
323
347
|
|
|
@@ -441,6 +465,8 @@ copa describe 42
|
|
|
441
465
|
|
|
442
466
|
Generates a description for a specific command by ID. Same accept/edit flow as `fix --auto`.
|
|
443
467
|
|
|
468
|
+

|
|
469
|
+
|
|
444
470
|
## Script Metadata Protocol
|
|
445
471
|
|
|
446
472
|
Copa recognizes `#@` headers in script files (checked in the first 50 lines):
|
|
@@ -470,12 +496,12 @@ Flags:
|
|
|
470
496
|
|
|
471
497
|
### Supported headers
|
|
472
498
|
|
|
473
|
-
| Header
|
|
474
|
-
|
|
475
|
-
| `#@ Description: <text>`
|
|
476
|
-
| `#@ Usage: <text>`
|
|
477
|
-
| `#@ Purpose: <text>`
|
|
478
|
-
| `#@ Flag: <flag>: <description>` | Document a flag/option (repeatable)
|
|
499
|
+
| Header | Effect |
|
|
500
|
+
| -------------------------------- | ----------------------------------------------- |
|
|
501
|
+
| `#@ Description: <text>` | Sets the command description (highest priority) |
|
|
502
|
+
| `#@ Usage: <text>` | Usage / invocation syntax |
|
|
503
|
+
| `#@ Purpose: <text>` | Why the script exists / when to use it |
|
|
504
|
+
| `#@ Flag: <flag>: <description>` | Document a flag/option (repeatable) |
|
|
479
505
|
|
|
480
506
|
Scripts without `#@` headers still work — Copa falls back to legacy patterns (`# Description:`, `# Purpose:`, Python docstrings, generic comments).
|
|
481
507
|
|
|
@@ -488,6 +514,8 @@ copa scan --dir ~/bin # scan a specific directory
|
|
|
488
514
|
|
|
489
515
|
## Sharing
|
|
490
516
|
|
|
517
|
+

|
|
518
|
+
|
|
491
519
|
Export a group as a `.copa` file:
|
|
492
520
|
|
|
493
521
|
```bash
|
|
@@ -510,25 +538,25 @@ copa share sync /path/to/team/copa-files/
|
|
|
510
538
|
|
|
511
539
|
Copa ships with ready-to-use `.copa` files in the [`examples/`](examples/) directory:
|
|
512
540
|
|
|
513
|
-
| File
|
|
514
|
-
|
|
515
|
-
| [`git.copa`](examples/git.copa)
|
|
516
|
-
| [`docker.copa`](examples/docker.copa)
|
|
517
|
-
| [`python-dev.copa`](examples/python-dev.copa)
|
|
518
|
-
| [`npm.copa`](examples/npm.copa)
|
|
519
|
-
| [`network.copa`](examples/network.copa)
|
|
520
|
-
| [`curl-http.copa`](examples/curl-http.copa)
|
|
521
|
-
| [`ssh-remote.copa`](examples/ssh-remote.copa)
|
|
522
|
-
| [`adb.copa`](examples/adb.copa)
|
|
523
|
-
| [`aws.copa`](examples/aws.copa)
|
|
524
|
-
| [`terraform.copa`](examples/terraform.copa)
|
|
525
|
-
| [`k8s.copa`](examples/k8s.copa)
|
|
526
|
-
| [`systemd.copa`](examples/systemd.copa)
|
|
527
|
-
| [`sysadmin.copa`](examples/sysadmin.copa)
|
|
528
|
-
| [`process-monitoring.copa`](examples/process-monitoring.copa) | Process management and debugging
|
|
529
|
-
| [`disk-files.copa`](examples/disk-files.copa)
|
|
530
|
-
| [`tmux.copa`](examples/tmux.copa)
|
|
531
|
-
| [`homebrew.copa`](examples/homebrew.copa)
|
|
541
|
+
| File | Description |
|
|
542
|
+
| ------------------------------------------------------------- | -------------------------------------- |
|
|
543
|
+
| [`git.copa`](examples/git.copa) | Essential Git commands |
|
|
544
|
+
| [`docker.copa`](examples/docker.copa) | Docker container management |
|
|
545
|
+
| [`python-dev.copa`](examples/python-dev.copa) | Python development workflow |
|
|
546
|
+
| [`npm.copa`](examples/npm.copa) | Node.js package management |
|
|
547
|
+
| [`network.copa`](examples/network.copa) | Network diagnostics |
|
|
548
|
+
| [`curl-http.copa`](examples/curl-http.copa) | HTTP requests and API testing |
|
|
549
|
+
| [`ssh-remote.copa`](examples/ssh-remote.copa) | SSH, SCP, and remote server management |
|
|
550
|
+
| [`adb.copa`](examples/adb.copa) | Android Debug Bridge |
|
|
551
|
+
| [`aws.copa`](examples/aws.copa) | AWS CLI cloud infrastructure |
|
|
552
|
+
| [`terraform.copa`](examples/terraform.copa) | Terraform infrastructure-as-code |
|
|
553
|
+
| [`k8s.copa`](examples/k8s.copa) | Kubernetes cluster management |
|
|
554
|
+
| [`systemd.copa`](examples/systemd.copa) | Linux service management |
|
|
555
|
+
| [`sysadmin.copa`](examples/sysadmin.copa) | System administration |
|
|
556
|
+
| [`process-monitoring.copa`](examples/process-monitoring.copa) | Process management and debugging |
|
|
557
|
+
| [`disk-files.copa`](examples/disk-files.copa) | Disk usage and file management |
|
|
558
|
+
| [`tmux.copa`](examples/tmux.copa) | Terminal multiplexer sessions |
|
|
559
|
+
| [`homebrew.copa`](examples/homebrew.copa) | Homebrew package manager (macOS) |
|
|
532
560
|
|
|
533
561
|
Load any of them:
|
|
534
562
|
|
|
@@ -569,29 +597,96 @@ alias copa-bt='copa fzf-list --set bluetooth | fzf'
|
|
|
569
597
|
|
|
570
598
|
```json
|
|
571
599
|
{
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
600
|
+
"copa_version": "1.0",
|
|
601
|
+
"name": "bluetooth",
|
|
602
|
+
"description": "Bluetooth commands for Android devices",
|
|
603
|
+
"author": "markstanford",
|
|
604
|
+
"commands": [
|
|
605
|
+
{
|
|
606
|
+
"command": "adb shell cmd bluetooth_manager enable",
|
|
607
|
+
"description": "Enable Bluetooth",
|
|
608
|
+
"tags": ["bt", "android"]
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
"command": "flash_all",
|
|
612
|
+
"description": "Flash AOSP build to device",
|
|
613
|
+
"tags": ["aosp"],
|
|
614
|
+
"flags": {
|
|
615
|
+
"-w, --wipe": "Wipe userdata before flashing",
|
|
616
|
+
"--skip <parts>": "Skip specific partitions"
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
],
|
|
620
|
+
"recipes": [
|
|
621
|
+
{
|
|
622
|
+
"name": "bt-debug",
|
|
623
|
+
"description": "Enable BT and start logging",
|
|
624
|
+
"steps": [
|
|
625
|
+
{"command": "adb shell cmd bluetooth_manager enable", "description": "Enable BT"},
|
|
626
|
+
{"command": "adb logcat -s bt_btif | tee bt.log", "description": "Start BT logging"}
|
|
627
|
+
]
|
|
628
|
+
}
|
|
629
|
+
]
|
|
592
630
|
}
|
|
593
631
|
```
|
|
594
632
|
|
|
633
|
+
## Recipes
|
|
634
|
+
|
|
635
|
+

|
|
636
|
+
|
|
637
|
+
Recipes are named, ordered sequences of commands — like a script, but tracked and shareable through Copa.
|
|
638
|
+
|
|
639
|
+
### Creating recipes
|
|
640
|
+
|
|
641
|
+
```bash
|
|
642
|
+
# Simple recipe
|
|
643
|
+
copa recipe add deploy \
|
|
644
|
+
-s 'npm run build' \
|
|
645
|
+
-s 'docker build -t app .' \
|
|
646
|
+
-s 'docker push app'
|
|
647
|
+
|
|
648
|
+
# With descriptions (use :: separator)
|
|
649
|
+
copa recipe add deploy \
|
|
650
|
+
-d "Full production deploy" \
|
|
651
|
+
-g devops \
|
|
652
|
+
-s 'npm run build :: Build the project' \
|
|
653
|
+
-s 'npm run test :: Run test suite' \
|
|
654
|
+
-s 'docker push app :: Push to registry'
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### Running recipes
|
|
658
|
+
|
|
659
|
+
```bash
|
|
660
|
+
# Run all steps sequentially
|
|
661
|
+
copa recipe run deploy
|
|
662
|
+
|
|
663
|
+
# Preview without executing
|
|
664
|
+
copa recipe run deploy --dry-run
|
|
665
|
+
|
|
666
|
+
# Continue past failures
|
|
667
|
+
copa recipe run deploy --no-stop-on-error
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
### Managing recipes
|
|
671
|
+
|
|
672
|
+
```bash
|
|
673
|
+
copa recipe list # List all recipes
|
|
674
|
+
copa recipe list --json # JSON output
|
|
675
|
+
copa recipe show deploy # Show steps
|
|
676
|
+
copa recipe remove deploy # Delete a recipe
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
### Sharing recipes
|
|
680
|
+
|
|
681
|
+
Recipes are included in `.copa` files automatically — when you export a group, its recipes come along:
|
|
682
|
+
|
|
683
|
+
```bash
|
|
684
|
+
copa share export devops -o devops.copa # includes recipes in that group
|
|
685
|
+
copa share load devops.copa # imports commands AND recipes
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
See `examples/docker.copa` and `examples/deploy.copa` for recipe examples.
|
|
689
|
+
|
|
595
690
|
## MCP Server (Claude Code integration)
|
|
596
691
|
|
|
597
692
|
Copa includes an MCP server so Claude Code can search and add commands.
|
|
@@ -606,24 +701,37 @@ Add to your Claude Code MCP config (`.mcp.json` in your project or home dir):
|
|
|
606
701
|
|
|
607
702
|
```json
|
|
608
703
|
{
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
}
|
|
704
|
+
"mcpServers": {
|
|
705
|
+
"copa": {
|
|
706
|
+
"command": "python3",
|
|
707
|
+
"args": ["-m", "copa.mcp_server"]
|
|
614
708
|
}
|
|
709
|
+
}
|
|
615
710
|
}
|
|
616
711
|
```
|
|
617
712
|
|
|
618
713
|
Available MCP tools:
|
|
714
|
+
|
|
619
715
|
- `copa_search` — search commands by keyword
|
|
620
716
|
- `copa_list_commands` — list commands ranked by score
|
|
621
717
|
- `copa_list_groups` — list all groups
|
|
622
718
|
- `copa_get_stats` — usage statistics
|
|
623
719
|
- `copa_add_command` — add a command
|
|
624
720
|
- `copa_update_description` — update a description
|
|
721
|
+
- `copa_delete_command` — delete a command by ID
|
|
722
|
+
- `copa_set_group` — set or change a command's group
|
|
723
|
+
- `copa_update_flags` — update flag documentation for a command
|
|
724
|
+
- `copa_pin_command` — pin or unpin a command
|
|
625
725
|
- `copa_create_group` — create a group with commands
|
|
626
726
|
- `copa_bulk_add` — bulk add commands
|
|
727
|
+
- `copa_share_load` — load a .copa file as a shared set
|
|
728
|
+
- `copa_share_list` — list all loaded shared sets
|
|
729
|
+
- `copa_share_remove` — remove a shared set
|
|
730
|
+
- `copa_export_group` — export a group as a .copa file
|
|
731
|
+
- `copa_recipe_list` — list all recipes
|
|
732
|
+
- `copa_recipe_show` — show a recipe's steps
|
|
733
|
+
- `copa_recipe_add` — create a recipe from ordered steps
|
|
734
|
+
- `copa_recipe_remove` — remove a recipe
|
|
627
735
|
|
|
628
736
|
## Configuration
|
|
629
737
|
|
|
@@ -636,12 +744,7 @@ Copa is configured via `~/.copa/config.toml`. All settings are optional — Copa
|
|
|
636
744
|
# Values are fzf key names: ctrl-<letter>, alt-<letter>, ctrl-/
|
|
637
745
|
# ctrl-r and enter are reserved and cannot be reassigned
|
|
638
746
|
[keys]
|
|
639
|
-
|
|
640
|
-
merge_output = "ctrl-o" # append 2>&1
|
|
641
|
-
pipe = "ctrl-x" # append |
|
|
642
|
-
redirect = "ctrl-t" # append >
|
|
643
|
-
chain = "ctrl-a" # append &&
|
|
644
|
-
suppress = "ctrl-/" # append 2>/dev/null
|
|
747
|
+
compose = "ctrl-x" # open compose submenu (|, &&, >, &, 2>&1, 2>/dev/null)
|
|
645
748
|
describe = "ctrl-d" # LLM describe
|
|
646
749
|
group = "ctrl-g" # assign group (inline modal)
|
|
647
750
|
flags = "ctrl-f" # edit flags
|
|
@@ -661,65 +764,75 @@ enabled = true # set to false to disable
|
|
|
661
764
|
min_length = 2 # minimum chars before querying
|
|
662
765
|
tab_accept = 2 # 1 = accept directly, 2 = open menu first
|
|
663
766
|
color = 242 # ghost text color (256-color palette)
|
|
767
|
+
directory_aware = true # boost suggestions from the current directory
|
|
664
768
|
|
|
665
|
-
#
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
continue = ["pipe", "chain", "redirect"] # default: |, &&, > re-open fzf
|
|
769
|
+
# Fzf layout
|
|
770
|
+
[layout]
|
|
771
|
+
height = "80%" # fzf height (default: 80%)
|
|
772
|
+
preview_size = "40%" # preview pane width (default: 40%)
|
|
670
773
|
```
|
|
671
774
|
|
|
672
|
-
###
|
|
775
|
+
### Compose submenu
|
|
673
776
|
|
|
674
|
-
|
|
777
|
+

|
|
675
778
|
|
|
676
|
-
|
|
677
|
-
- `pipe` (`|`) — continue
|
|
678
|
-
- `chain` (`&&`) — continue
|
|
679
|
-
- `redirect` (`>`) — continue
|
|
779
|
+
Press **Ctrl+X** while a command is highlighted to open the compose submenu — a numbered menu of shell operators:
|
|
680
780
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
781
|
+
```
|
|
782
|
+
Compose: 1)| 2)&& 3)> 4)& 5)2>&1 6)2>/dev/null
|
|
783
|
+
Select [1-6]:
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
| # | Operator | Behavior | What happens |
|
|
787
|
+
|---|---------------|------------|-------------------------------------------------------------|
|
|
788
|
+
| 1 | `\|` | continue | Appends `\|` and re-opens fzf to select the next command |
|
|
789
|
+
| 2 | `&&` | continue | Appends `&&` and re-opens fzf to chain another command |
|
|
790
|
+
| 3 | `>` | continue | Appends `>` and re-opens fzf for the target |
|
|
791
|
+
| 4 | `&` | close | Appends `&` and closes — run in background |
|
|
792
|
+
| 5 | `2>&1` | close | Appends `2>&1` and closes — merge stderr |
|
|
793
|
+
| 6 | `2>/dev/null` | close | Appends `2>/dev/null` and closes — suppress stderr |
|
|
794
|
+
|
|
795
|
+
"Continue" operators re-open fzf so you can build multi-command pipelines. "Close" operators place the final command in your prompt.
|
|
685
796
|
|
|
686
797
|
When chaining, the prompt shows your accumulated command: `copa [git pull && ]>`.
|
|
687
798
|
|
|
688
|
-
|
|
799
|
+
## End-to-End Workflow
|
|
689
800
|
|
|
690
|
-
|
|
691
|
-
[composition]
|
|
692
|
-
continue = []
|
|
693
|
-
```
|
|
801
|
+

|
|
694
802
|
|
|
695
803
|
## CLI Reference
|
|
696
804
|
|
|
697
|
-
| Command
|
|
698
|
-
|
|
699
|
-
| `copa setup`
|
|
700
|
-
| `copa add "cmd" -d "desc" -g group -f "flag: desc"`
|
|
701
|
-
| `copa edit ID [-d desc] [-g group] [-f flags] [--pin]`
|
|
702
|
-
| `copa remove ID`
|
|
703
|
-
| `copa pin ID`
|
|
704
|
-
| `copa unpin ID`
|
|
705
|
-
| `copa list [-g group] [-s source] [--set name] [--json]` | List by score
|
|
706
|
-
| `copa search "query" [-g group] [--set name] [--json]`
|
|
707
|
-
| `copa create -g group [-o file]`
|
|
708
|
-
| `copa stats`
|
|
709
|
-
| `copa doctor`
|
|
710
|
-
| `copa sync`
|
|
711
|
-
| `copa scan [--dir path]`
|
|
712
|
-
| `copa evolve [-k 20] [--auto]`
|
|
713
|
-
| `copa fix [--auto]`
|
|
714
|
-
| `copa describe ID`
|
|
715
|
-
| `copa configure`
|
|
716
|
-
| `copa share export GROUP -o file`
|
|
717
|
-
| `copa share load SOURCE`
|
|
718
|
-
| `copa share list`
|
|
719
|
-
| `copa share sync DIR`
|
|
720
|
-
| `copa import FILE [-g group]`
|
|
721
|
-
| `copa
|
|
722
|
-
| `copa
|
|
805
|
+
| Command | Purpose |
|
|
806
|
+
| -------------------------------------------------------- | ----------------------------------------------------------- |
|
|
807
|
+
| `copa setup` | Interactive setup wizard |
|
|
808
|
+
| `copa add "cmd" -d "desc" -g group -f "flag: desc"` | Save a command (with optional flags) |
|
|
809
|
+
| `copa edit ID [-d desc] [-g group] [-f flags] [--pin]` | Edit a command's metadata |
|
|
810
|
+
| `copa remove ID` | Remove a command |
|
|
811
|
+
| `copa pin ID` | Pin a command to the top |
|
|
812
|
+
| `copa unpin ID` | Unpin a command |
|
|
813
|
+
| `copa list [-g group] [-s source] [--set name] [--json]` | List by score |
|
|
814
|
+
| `copa search "query" [-g group] [--set name] [--json]` | FTS search |
|
|
815
|
+
| `copa create -g group [-o file]` | Create a .copa file from a group |
|
|
816
|
+
| `copa stats` | Usage statistics |
|
|
817
|
+
| `copa doctor` | Check setup and diagnose issues |
|
|
818
|
+
| `copa sync` | Import from zsh history |
|
|
819
|
+
| `copa scan [--dir path]` | Import script metadata from $PATH |
|
|
820
|
+
| `copa evolve [-k 20] [--auto]` | Auto-add frequent commands (with optional LLM descriptions) |
|
|
821
|
+
| `copa fix [--auto]` | Add missing descriptions (with optional LLM) |
|
|
822
|
+
| `copa describe ID` | Generate description for one command |
|
|
823
|
+
| `copa configure` | Set LLM backend (claude/ollama) |
|
|
824
|
+
| `copa share export GROUP -o file` | Export group |
|
|
825
|
+
| `copa share load SOURCE` | Load shared set |
|
|
826
|
+
| `copa share list` | List shared sets |
|
|
827
|
+
| `copa share sync DIR` | Sync .copa files from dir |
|
|
828
|
+
| `copa import FILE [-g group]` | Import commands from markdown |
|
|
829
|
+
| `copa recipe add NAME -s 'cmd' [-s 'cmd' ...]` | Create a multi-step recipe |
|
|
830
|
+
| `copa recipe list [--json]` | List all recipes |
|
|
831
|
+
| `copa recipe show NAME` | Show a recipe's steps |
|
|
832
|
+
| `copa recipe run NAME [--dry-run]` | Run a recipe's steps sequentially |
|
|
833
|
+
| `copa recipe remove NAME` | Remove a recipe |
|
|
834
|
+
| `copa reset` | Wipe database and start fresh (keeps config) |
|
|
835
|
+
| `copa uninstall` | Remove Copa data and show cleanup steps |
|
|
723
836
|
|
|
724
837
|
## How Scoring Works
|
|
725
838
|
|
|
@@ -729,6 +842,8 @@ score = 2.0 * log(1 + frequency) + 8.0 * 0.5^(age_seconds / 3_days)
|
|
|
729
842
|
|
|
730
843
|
Pinned commands get a +1000 bonus. The 3-day half-life means commands used in the last few days are strongly favored — a command used today scores ~8.0 recency, after 3 days ~4.0, after a week ~1.6.
|
|
731
844
|
|
|
845
|
+
When `directory_aware = true` (default), commands get a bonus based on where you are: +5.0 for the same directory, +2.0 for a parent or child directory. This means `git push` suggests your project's branch, not another repo's.
|
|
846
|
+
|
|
732
847
|
## License
|
|
733
848
|
|
|
734
849
|
MIT
|