copa-cli 0.8.0__tar.gz → 0.9.5__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.
Files changed (39) hide show
  1. {copa_cli-0.8.0 → copa_cli-0.9.5}/PKG-INFO +239 -164
  2. {copa_cli-0.8.0 → copa_cli-0.9.5}/README.md +238 -163
  3. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/cli.py +2 -1
  4. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/cli_internal.py +52 -5
  5. copa_cli-0.9.5/copa/cli_recipe.py +196 -0
  6. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/config.py +38 -58
  7. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/copa.zsh +180 -51
  8. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/db.py +152 -10
  9. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/fzf.py +39 -1
  10. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/mcp_server.py +57 -0
  11. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/models.py +72 -1
  12. copa_cli-0.9.5/copa/scoring.py +73 -0
  13. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/sharing.py +23 -1
  14. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa_cli.egg-info/PKG-INFO +239 -164
  15. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa_cli.egg-info/SOURCES.txt +1 -0
  16. {copa_cli-0.8.0 → copa_cli-0.9.5}/pyproject.toml +1 -1
  17. {copa_cli-0.8.0 → copa_cli-0.9.5}/tests/test_modal.py +34 -88
  18. copa_cli-0.8.0/copa/scoring.py +0 -45
  19. {copa_cli-0.8.0 → copa_cli-0.9.5}/LICENSE +0 -0
  20. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/__init__.py +0 -0
  21. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/__main__.py +0 -0
  22. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/cli_common.py +0 -0
  23. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/cli_llm.py +0 -0
  24. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/cli_share.py +0 -0
  25. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/evolve.py +0 -0
  26. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/history.py +0 -0
  27. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/llm.py +0 -0
  28. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa/scanner.py +0 -0
  29. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa_cli.egg-info/dependency_links.txt +0 -0
  30. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa_cli.egg-info/entry_points.txt +0 -0
  31. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa_cli.egg-info/requires.txt +0 -0
  32. {copa_cli-0.8.0 → copa_cli-0.9.5}/copa_cli.egg-info/top_level.txt +0 -0
  33. {copa_cli-0.8.0 → copa_cli-0.9.5}/setup.cfg +0 -0
  34. {copa_cli-0.8.0 → copa_cli-0.9.5}/tests/test_cli_and_sharing.py +0 -0
  35. {copa_cli-0.8.0 → copa_cli-0.9.5}/tests/test_db.py +0 -0
  36. {copa_cli-0.8.0 → copa_cli-0.9.5}/tests/test_fzf.py +0 -0
  37. {copa_cli-0.8.0 → copa_cli-0.9.5}/tests/test_models.py +0 -0
  38. {copa_cli-0.8.0 → copa_cli-0.9.5}/tests/test_polish.py +0 -0
  39. {copa_cli-0.8.0 → copa_cli-0.9.5}/tests/test_scanner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copa-cli
3
- Version: 0.8.0
3
+ Version: 0.9.5
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,14 +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
- ![Copa Setup](demos/01-setup.gif)
39
+ ![Copa Demo](demos/00-hero.gif)
40
40
 
41
41
  ## Features
42
42
 
43
- - **Smart ranking** — commands scored by `2*log(1+freq) + 8*0.5^(age/3d)`, so frequent *and* recent commands float to the top
43
+ - **Smart ranking** — commands scored by `2*log(1+freq) + 8*0.5^(age/3d)`, so frequent _and_ recent commands float to the top
44
44
  - **FTS search** — full-text search across commands and their descriptions
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
+ - **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
47
47
  - **Auto-evolution** — `copa evolve` finds your most-used commands from zsh history and promotes them
48
48
  - **LLM descriptions** — `copa fix --auto` uses Claude or ollama to generate descriptions for undescribed commands
49
49
  - **Script protocol** — `#@ Description:` / `#@ Usage:` / `#@ Purpose:` / `#@ Flag:` headers in your scripts are auto-detected by `copa scan` across all `$PATH` directories
@@ -51,6 +51,8 @@ Copa tracks the commands you run, ranks them by frequency and recency, and gives
51
51
  - **Inline suggestions** — ghost text appears as you type; Tab accepts or opens a completion menu with the suggestion highlighted
52
52
  - **Groups & Ctrl+G** — organize commands by project, device, or workflow; assign groups inline from the fzf palette with Ctrl+G
53
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
54
56
  - **Sharing & `copa create`** — export/import command sets as `.copa` JSON files; `copa create` scaffolds a `.copa` file from an existing group
55
57
  - **Set filtering** — scope list, search, and fzf to a specific shared set with `--set`
56
58
  - **MCP server** — expose your commands to Claude Code (or any MCP client)
@@ -98,6 +100,7 @@ copa setup
98
100
  ```
99
101
 
100
102
  This walks you through everything:
103
+
101
104
  1. Checks that **fzf** is installed (tells you how to install if missing)
102
105
  2. Creates the Copa database (`~/.copa/copa.db`)
103
106
  3. Adds shell integration to your `~/.zshrc` (prompts for confirmation)
@@ -156,35 +159,34 @@ This is the key difference from plain zsh Ctrl+R: you're not just searching raw
156
159
 
157
160
  The header shows available modes. Press **Ctrl+R** again while fzf is open to cycle:
158
161
 
159
- | Mode | Sort order | Use case |
160
- |------|-----------|----------|
161
- | `all` | Score (frequency + recency) | Default — best commands float to top |
162
- | `frequent` | Frequency only | Find your most-used commands |
163
- | `recent` | Last used time | Find commands you ran recently |
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 |
164
168
 
165
169
  ### Keybindings
166
170
 
167
171
  While the fzf palette is open, these keys are available:
168
172
 
169
- | Key | Action | Effect |
170
- |-----|--------|--------|
171
- | **Ctrl+R** | Cycle mode | all → frequent → recent → all |
172
- | **Ctrl+V** | Append `&` | Run selected command in background |
173
- | **Ctrl+O** | Append `2>&1` | Merge stderr into stdout |
174
- | **Ctrl+X** | Append `\|` | Pipe into next command |
175
- | **Ctrl+T** | Append `>` | Redirect output |
176
- | **Ctrl+A** | Append `&&` | Chain with next command |
177
- | **Ctrl+/** | Append `2>/dev/null` | Suppress stderr |
178
- | **Ctrl+S** | Scope by group | Opens inline group list — Enter filters to that group, ESC returns to all |
179
- | **Ctrl+G** | Assign group | Opens inline group list — Enter assigns the group to the highlighted command |
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 |
180
179
 
181
180
  ![Groups and Scoping](demos/05-groups-and-scoping.gif)
182
- | **Ctrl+N** | Cycle group | Cycles through groups: (all) → group1 → group2 → ... → (all) |
183
- | **Ctrl+D** | Describe | Generate/edit a description using LLM (with tty-aware input) |
184
- | **Ctrl+F** | Edit flags | Add flag documentation to the highlighted command |
185
- | **Ctrl+B** | Select mode | Enter multi-select for bulk operations (see below) |
186
- | **Ctrl+H** | Toggle header | Show/hide the key hints for more screen space |
187
- | **ESC** | Cancel/back | In scope/group mode: returns to command list. Otherwise: closes fzf |
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 |
188
190
 
189
191
  Keybindings are configurable via `~/.copa/config.toml`. See [Configuration](#configuration).
190
192
 
@@ -210,11 +212,11 @@ Selected 5 command(s).
210
212
  Action:
211
213
  ```
212
214
 
213
- | Action | What it does |
214
- |--------|-------------|
215
- | **g** | Assign all selected commands to a group (or clear their group) |
216
- | **d** | Delete all selected commands (with confirmation) |
217
- | **a** | Auto-generate descriptions for all selected commands using your configured LLM backend |
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 |
218
220
 
219
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.
220
222
 
@@ -238,12 +240,12 @@ Copa supplements zsh's built-in tab completion for **any** command — not just
238
240
 
239
241
  Copa supports four completion modes, configured via `~/.copa/config.toml`:
240
242
 
241
- | Mode | Behavior |
242
- |------|----------|
243
+ | Mode | Behavior |
244
+ | ---------- | ----------------------------------------------------------------------------- |
243
245
  | `fallback` | **(default)** Only show Copa completions when native completers found nothing |
244
- | `hybrid` | Show Copa completions alongside native completions (in a separate group) |
245
- | `always` | Copa completions replace native completions |
246
- | `never` | Disable Copa tab completion entirely |
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 |
247
249
 
248
250
  ```toml
249
251
  # ~/.copa/config.toml
@@ -281,8 +283,8 @@ Copa's own CLI completions (`copa li<TAB>` → `list`) continue to work as befor
281
283
 
282
284
  ## Inline Suggestions (Ghost Text)
283
285
 
284
- | Tab Mode 1 (direct accept) | Tab Mode 2 (menu select, default) |
285
- |---|---|
286
+ | Tab Mode 1 (direct accept) | Tab Mode 2 (menu select, default) |
287
+ | -------------------------------------------------- | -------------------------------------------------- |
286
288
  | ![Tab Mode 1](demos/02a-suggestions-tab-mode1.gif) | ![Tab Mode 2](demos/02b-suggestions-tab-mode2.gif) |
287
289
 
288
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.
@@ -297,44 +299,49 @@ $ git pu█sh origin main ← grey ghost text
297
299
 
298
300
  ### Keybindings
299
301
 
300
- | Key | Suggestion showing | No suggestion |
301
- |-----|-------------------|---------------|
302
- | Type chars | Insert char, re-fetch suggestion | Insert char, fetch suggestion |
303
- | Backspace | Delete char, **latch** (suppress suggestions) | Delete char normally |
304
- | **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 |
305
- | **Down** | Open completion menu with suggestion highlighted at top | History navigation |
306
- | **Right arrow** | Accept one word, re-fetch | Move cursor right |
307
- | **Cmd+Right / End** | Accept full suggestion | Move to end of line |
308
- | Enter | Clear suggestion, execute | Execute |
309
- | Esc | Dismiss suggestion | Normal Esc |
310
- | Up | Clear suggestion, navigate history | History navigation |
311
- | Ctrl+R | Clear suggestion, open fzf | Open fzf |
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 |
312
314
 
313
315
  ### Tab accept mode
314
316
 
315
317
  Copa supports two Tab behaviors when a suggestion is showing:
316
318
 
317
319
  **Menu select** (`tab_accept = 2`, default):
320
+
318
321
  1. Press **Tab** — ghost text clears, a completion menu opens with the Copa suggestion highlighted at the top, alongside native completions below
319
- 2. Press **Tab** or **Space** accepts the highlighted item
320
- 3. Press **Escape** — cancels the menu, restores your original text
321
- 4. Use **arrow keys** to navigate if you want a different completion
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
322
326
 
323
327
  This gives you a chance to see alternatives before committing. The Copa suggestion is always the first item in the menu.
324
328
 
325
329
  **Inline accept** (`tab_accept = 1`):
330
+
326
331
  - Press **Tab** — the suggestion is accepted directly into your command line. One keystroke, done.
327
332
 
328
333
  ### Completion menu navigation
329
334
 
330
335
  When the completion menu is open (from Tab in `tab_accept = 2` mode or from normal tab completion):
331
336
 
332
- | Key | Action |
333
- |-----|--------|
334
- | **Tab** | Accept the highlighted completion |
335
- | **Space** | Accept the highlighted completion |
336
- | **Escape** | Cancel dismiss menu, restore original text |
337
- | **Arrow keys** | Navigate between completions |
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 |
338
345
 
339
346
  ### Backspace latch
340
347
 
@@ -489,12 +496,12 @@ Flags:
489
496
 
490
497
  ### Supported headers
491
498
 
492
- | Header | Effect |
493
- |--------|--------|
494
- | `#@ Description: <text>` | Sets the command description (highest priority) |
495
- | `#@ Usage: <text>` | Usage / invocation syntax |
496
- | `#@ Purpose: <text>` | Why the script exists / when to use it |
497
- | `#@ 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) |
498
505
 
499
506
  Scripts without `#@` headers still work — Copa falls back to legacy patterns (`# Description:`, `# Purpose:`, Python docstrings, generic comments).
500
507
 
@@ -531,25 +538,25 @@ copa share sync /path/to/team/copa-files/
531
538
 
532
539
  Copa ships with ready-to-use `.copa` files in the [`examples/`](examples/) directory:
533
540
 
534
- | File | Description |
535
- |------|-------------|
536
- | [`git.copa`](examples/git.copa) | Essential Git commands |
537
- | [`docker.copa`](examples/docker.copa) | Docker container management |
538
- | [`python-dev.copa`](examples/python-dev.copa) | Python development workflow |
539
- | [`npm.copa`](examples/npm.copa) | Node.js package management |
540
- | [`network.copa`](examples/network.copa) | Network diagnostics |
541
- | [`curl-http.copa`](examples/curl-http.copa) | HTTP requests and API testing |
542
- | [`ssh-remote.copa`](examples/ssh-remote.copa) | SSH, SCP, and remote server management |
543
- | [`adb.copa`](examples/adb.copa) | Android Debug Bridge |
544
- | [`aws.copa`](examples/aws.copa) | AWS CLI cloud infrastructure |
545
- | [`terraform.copa`](examples/terraform.copa) | Terraform infrastructure-as-code |
546
- | [`k8s.copa`](examples/k8s.copa) | Kubernetes cluster management |
547
- | [`systemd.copa`](examples/systemd.copa) | Linux service management |
548
- | [`sysadmin.copa`](examples/sysadmin.copa) | System administration |
549
- | [`process-monitoring.copa`](examples/process-monitoring.copa) | Process management and debugging |
550
- | [`disk-files.copa`](examples/disk-files.copa) | Disk usage and file management |
551
- | [`tmux.copa`](examples/tmux.copa) | Terminal multiplexer sessions |
552
- | [`homebrew.copa`](examples/homebrew.copa) | Homebrew package manager (macOS) |
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) |
553
560
 
554
561
  Load any of them:
555
562
 
@@ -590,29 +597,96 @@ alias copa-bt='copa fzf-list --set bluetooth | fzf'
590
597
 
591
598
  ```json
592
599
  {
593
- "copa_version": "1.0",
594
- "name": "bluetooth",
595
- "description": "Bluetooth commands for Android devices",
596
- "author": "markstanford",
597
- "commands": [
598
- {
599
- "command": "adb shell cmd bluetooth_manager enable",
600
- "description": "Enable Bluetooth",
601
- "tags": ["bt", "android"]
602
- },
603
- {
604
- "command": "flash_all",
605
- "description": "Flash AOSP build to device",
606
- "tags": ["aosp"],
607
- "flags": {
608
- "-w, --wipe": "Wipe userdata before flashing",
609
- "--skip <parts>": "Skip specific partitions"
610
- }
611
- }
612
- ]
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
+ ]
613
630
  }
614
631
  ```
615
632
 
633
+ ## Recipes
634
+
635
+ ![Recipes Demo](demos/12-recipes.gif)
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
+
616
690
  ## MCP Server (Claude Code integration)
617
691
 
618
692
  Copa includes an MCP server so Claude Code can search and add commands.
@@ -627,16 +701,17 @@ Add to your Claude Code MCP config (`.mcp.json` in your project or home dir):
627
701
 
628
702
  ```json
629
703
  {
630
- "mcpServers": {
631
- "copa": {
632
- "command": "python3",
633
- "args": ["-m", "copa.mcp_server"]
634
- }
704
+ "mcpServers": {
705
+ "copa": {
706
+ "command": "python3",
707
+ "args": ["-m", "copa.mcp_server"]
635
708
  }
709
+ }
636
710
  }
637
711
  ```
638
712
 
639
713
  Available MCP tools:
714
+
640
715
  - `copa_search` — search commands by keyword
641
716
  - `copa_list_commands` — list commands ranked by score
642
717
  - `copa_list_groups` — list all groups
@@ -653,6 +728,10 @@ Available MCP tools:
653
728
  - `copa_share_list` — list all loaded shared sets
654
729
  - `copa_share_remove` — remove a shared set
655
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
656
735
 
657
736
  ## Configuration
658
737
 
@@ -665,12 +744,7 @@ Copa is configured via `~/.copa/config.toml`. All settings are optional — Copa
665
744
  # Values are fzf key names: ctrl-<letter>, alt-<letter>, ctrl-/
666
745
  # ctrl-r and enter are reserved and cannot be reassigned
667
746
  [keys]
668
- background = "ctrl-v" # append &
669
- merge_output = "ctrl-o" # append 2>&1
670
- pipe = "ctrl-x" # append |
671
- redirect = "ctrl-t" # append >
672
- chain = "ctrl-a" # append &&
673
- suppress = "ctrl-/" # append 2>/dev/null
747
+ compose = "ctrl-x" # open compose submenu (|, &&, >, &, 2>&1, 2>/dev/null)
674
748
  describe = "ctrl-d" # LLM describe
675
749
  group = "ctrl-g" # assign group (inline modal)
676
750
  flags = "ctrl-f" # edit flags
@@ -690,71 +764,70 @@ enabled = true # set to false to disable
690
764
  min_length = 2 # minimum chars before querying
691
765
  tab_accept = 2 # 1 = accept directly, 2 = open menu first
692
766
  color = 242 # ghost text color (256-color palette)
767
+ directory_aware = true # boost suggestions from the current directory
693
768
 
694
- # Composition key behavior (continue vs close)
695
- # "continue" keys re-open fzf so you can chain another command
696
- # All other composition keys close fzf immediately
697
- [composition]
698
- 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%)
699
773
  ```
700
774
 
701
- ### Composition key behavior
775
+ ### Compose submenu
702
776
 
703
777
  ![Composition](demos/08-composition.gif)
704
778
 
705
- When you press a composition key (like Ctrl-A for `&&`), Copa can either **close fzf** (placing the command + operator in your prompt) or **continue** (appending the operator and re-opening fzf so you can select the next command to chain).
779
+ Press **Ctrl+X** while a command is highlighted to open the compose submenu an fzf-powered operator picker with arrow keys, Tab, and highlighting:
706
780
 
707
- By default, "connector" operators re-open fzf:
708
- - `pipe` (`|`) — continue
709
- - `chain` (`&&`) continue
710
- - `redirect` (`>`) continue
781
+ | Operator | Behavior | What happens |
782
+ |---------------|------------|-------------------------------------------------------------|
783
+ | `\|` | continue | Appends `\|` and re-opens fzf to select the next command |
784
+ | `&&` | continue | Appends `&&` and re-opens fzf to chain another command |
785
+ | `>` | continue | Appends `>` and re-opens fzf for the target |
786
+ | `&` | close | Appends `&` and closes — run in background |
787
+ | `2>&1` | close | Appends `2>&1` and closes — merge stderr |
788
+ | `2>/dev/null` | close | Appends `2>/dev/null` and closes — suppress stderr |
711
789
 
712
- And "terminal" operators close fzf:
713
- - `background` (`&`) — close
714
- - `merge_output` (`2>&1`) — close
715
- - `suppress` (`2>/dev/null`) — close
790
+ "Continue" operators re-open fzf so you can build multi-command pipelines. "Close" operators place the final command in your prompt. Press **Esc** to cancel and return to the main palette.
716
791
 
717
792
  When chaining, the prompt shows your accumulated command: `copa [git pull && ]>`.
718
793
 
719
- To revert to the old behavior (all keys close immediately), set:
720
-
721
- ```toml
722
- [composition]
723
- continue = []
724
- ```
725
-
726
794
  ## End-to-End Workflow
727
795
 
728
796
  ![Workflow](demos/11-workflow.gif)
729
797
 
730
798
  ## CLI Reference
731
799
 
732
- | Command | Purpose |
733
- |---------|---------|
734
- | `copa setup` | Interactive setup wizard |
735
- | `copa add "cmd" -d "desc" -g group -f "flag: desc"` | Save a command (with optional flags) |
736
- | `copa edit ID [-d desc] [-g group] [-f flags] [--pin]` | Edit a command's metadata |
737
- | `copa remove ID` | Remove a command |
738
- | `copa pin ID` | Pin a command to the top |
739
- | `copa unpin ID` | Unpin a command |
740
- | `copa list [-g group] [-s source] [--set name] [--json]` | List by score |
741
- | `copa search "query" [-g group] [--set name] [--json]` | FTS search |
742
- | `copa create -g group [-o file]` | Create a .copa file from a group |
743
- | `copa stats` | Usage statistics |
744
- | `copa doctor` | Check setup and diagnose issues |
745
- | `copa sync` | Import from zsh history |
746
- | `copa scan [--dir path]` | Import script metadata from $PATH |
747
- | `copa evolve [-k 20] [--auto]` | Auto-add frequent commands (with optional LLM descriptions) |
748
- | `copa fix [--auto]` | Add missing descriptions (with optional LLM) |
749
- | `copa describe ID` | Generate description for one command |
750
- | `copa configure` | Set LLM backend (claude/ollama) |
751
- | `copa share export GROUP -o file` | Export group |
752
- | `copa share load SOURCE` | Load shared set |
753
- | `copa share list` | List shared sets |
754
- | `copa share sync DIR` | Sync .copa files from dir |
755
- | `copa import FILE [-g group]` | Import commands from markdown |
756
- | `copa reset` | Wipe database and start fresh (keeps config) |
757
- | `copa uninstall` | Remove Copa data and show cleanup steps |
800
+ | Command | Purpose |
801
+ | -------------------------------------------------------- | ----------------------------------------------------------- |
802
+ | `copa setup` | Interactive setup wizard |
803
+ | `copa add "cmd" -d "desc" -g group -f "flag: desc"` | Save a command (with optional flags) |
804
+ | `copa edit ID [-d desc] [-g group] [-f flags] [--pin]` | Edit a command's metadata |
805
+ | `copa remove ID` | Remove a command |
806
+ | `copa pin ID` | Pin a command to the top |
807
+ | `copa unpin ID` | Unpin a command |
808
+ | `copa list [-g group] [-s source] [--set name] [--json]` | List by score |
809
+ | `copa search "query" [-g group] [--set name] [--json]` | FTS search |
810
+ | `copa create -g group [-o file]` | Create a .copa file from a group |
811
+ | `copa stats` | Usage statistics |
812
+ | `copa doctor` | Check setup and diagnose issues |
813
+ | `copa sync` | Import from zsh history |
814
+ | `copa scan [--dir path]` | Import script metadata from $PATH |
815
+ | `copa evolve [-k 20] [--auto]` | Auto-add frequent commands (with optional LLM descriptions) |
816
+ | `copa fix [--auto]` | Add missing descriptions (with optional LLM) |
817
+ | `copa describe ID` | Generate description for one command |
818
+ | `copa configure` | Set LLM backend (claude/ollama) |
819
+ | `copa share export GROUP -o file` | Export group |
820
+ | `copa share load SOURCE` | Load shared set |
821
+ | `copa share list` | List shared sets |
822
+ | `copa share sync DIR` | Sync .copa files from dir |
823
+ | `copa import FILE [-g group]` | Import commands from markdown |
824
+ | `copa recipe add NAME -s 'cmd' [-s 'cmd' ...]` | Create a multi-step recipe |
825
+ | `copa recipe list [--json]` | List all recipes |
826
+ | `copa recipe show NAME` | Show a recipe's steps |
827
+ | `copa recipe run NAME [--dry-run]` | Run a recipe's steps sequentially |
828
+ | `copa recipe remove NAME` | Remove a recipe |
829
+ | `copa reset` | Wipe database and start fresh (keeps config) |
830
+ | `copa uninstall` | Remove Copa data and show cleanup steps |
758
831
 
759
832
  ## How Scoring Works
760
833
 
@@ -764,6 +837,8 @@ score = 2.0 * log(1 + frequency) + 8.0 * 0.5^(age_seconds / 3_days)
764
837
 
765
838
  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.
766
839
 
840
+ 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.
841
+
767
842
  ## License
768
843
 
769
844
  MIT