copa-cli 0.4.0__tar.gz → 0.7.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.
Files changed (40) hide show
  1. {copa_cli-0.4.0 → copa_cli-0.7.0}/PKG-INFO +230 -13
  2. {copa_cli-0.4.0 → copa_cli-0.7.0}/README.md +229 -12
  3. copa_cli-0.7.0/copa/cli.py +652 -0
  4. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/cli_internal.py +165 -0
  5. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/cli_llm.py +33 -12
  6. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/config.py +74 -6
  7. copa_cli-0.7.0/copa/copa.zsh +587 -0
  8. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/db.py +3 -0
  9. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa_cli.egg-info/PKG-INFO +230 -13
  10. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa_cli.egg-info/SOURCES.txt +1 -0
  11. {copa_cli-0.4.0 → copa_cli-0.7.0}/pyproject.toml +1 -1
  12. copa_cli-0.7.0/tests/test_modal.py +1053 -0
  13. copa_cli-0.7.0/tests/test_polish.py +211 -0
  14. copa_cli-0.4.0/copa/cli.py +0 -274
  15. copa_cli-0.4.0/copa/copa.zsh +0 -197
  16. copa_cli-0.4.0/tests/test_modal.py +0 -216
  17. {copa_cli-0.4.0 → copa_cli-0.7.0}/LICENSE +0 -0
  18. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/__init__.py +0 -0
  19. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/__main__.py +0 -0
  20. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/cli_common.py +0 -0
  21. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/cli_share.py +0 -0
  22. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/evolve.py +0 -0
  23. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/fzf.py +0 -0
  24. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/history.py +0 -0
  25. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/llm.py +0 -0
  26. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/mcp_server.py +0 -0
  27. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/models.py +0 -0
  28. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/scanner.py +0 -0
  29. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/scoring.py +0 -0
  30. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa/sharing.py +0 -0
  31. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa_cli.egg-info/dependency_links.txt +0 -0
  32. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa_cli.egg-info/entry_points.txt +0 -0
  33. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa_cli.egg-info/requires.txt +0 -0
  34. {copa_cli-0.4.0 → copa_cli-0.7.0}/copa_cli.egg-info/top_level.txt +0 -0
  35. {copa_cli-0.4.0 → copa_cli-0.7.0}/setup.cfg +0 -0
  36. {copa_cli-0.4.0 → copa_cli-0.7.0}/tests/test_cli_and_sharing.py +0 -0
  37. {copa_cli-0.4.0 → copa_cli-0.7.0}/tests/test_db.py +0 -0
  38. {copa_cli-0.4.0 → copa_cli-0.7.0}/tests/test_fzf.py +0 -0
  39. {copa_cli-0.4.0 → copa_cli-0.7.0}/tests/test_models.py +0 -0
  40. {copa_cli-0.4.0 → copa_cli-0.7.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.4.0
3
+ Version: 0.7.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
@@ -46,17 +46,22 @@ Copa tracks the commands you run, ranks them by frequency and recency, and gives
46
46
  - **LLM descriptions** — `copa fix --auto` uses Claude or ollama to generate descriptions for undescribed commands
47
47
  - **Script protocol** — `#@ Description:` / `#@ Usage:` / `#@ Purpose:` / `#@ Flag:` headers in your scripts are auto-detected by `copa scan` across all `$PATH` directories
48
48
  - **Flag documentation** — document command flags with descriptions; flags are searchable, visible in the preview pane, and preserved in `.copa` exports
49
+ - **Inline suggestions** — ghost text appears as you type; Tab accepts or opens a completion menu with the suggestion highlighted
49
50
  - **Groups & Ctrl+G** — organize commands by project, device, or workflow; assign groups inline from the fzf palette with Ctrl+G
51
+ - **Bulk operations** — Ctrl+B enters select mode for batch group assignment, batch deletion, or batch LLM description
50
52
  - **Sharing & `copa create`** — export/import command sets as `.copa` JSON files; `copa create` scaffolds a `.copa` file from an existing group
51
53
  - **Set filtering** — scope list, search, and fzf to a specific shared set with `--set`
52
54
  - **MCP server** — expose your commands to Claude Code (or any MCP client)
53
55
  - **Zero latency** — precmd hook records usage in the background
54
56
 
57
+ > **Note:** Copa requires **zsh**. It is not compatible with bash, fish, or PowerShell.
58
+
55
59
  ## Install
56
60
 
57
61
  ### Prerequisites
58
62
 
59
63
  - **Python 3.12+**
64
+ - **zsh** — Copa's shell integration (precmd hooks, ZLE widgets, inline suggestions) is zsh-only
60
65
  - **fzf** — required for Ctrl+R command palette
61
66
 
62
67
  ```bash
@@ -82,24 +87,47 @@ pip install -e .
82
87
  pip install copa-cli[ollama]
83
88
  ```
84
89
 
85
- ### Shell integration (required)
90
+ ### Setup
91
+
92
+ Run the interactive setup wizard:
93
+
94
+ ```bash
95
+ copa setup
96
+ ```
97
+
98
+ This walks you through everything:
99
+ 1. Checks that **fzf** is installed (tells you how to install if missing)
100
+ 2. Creates the Copa database (`~/.copa/copa.db`)
101
+ 3. Adds shell integration to your `~/.zshrc` (prompts for confirmation)
102
+ 4. Optionally imports your zsh history
86
103
 
87
- Add this line to your `~/.zshrc`:
104
+ Then activate Copa in your current terminal:
88
105
 
89
106
  ```bash
90
- eval "$(copa init zsh)"
107
+ source ~/.zshrc
91
108
  ```
92
109
 
93
- Then restart your shell or run `source ~/.zshrc`. This does three things:
110
+ ### What shell integration does
111
+
112
+ The `eval "$(copa init zsh)"` line added to your `.zshrc` does three things:
94
113
 
95
114
  1. **Records every command you run** — a `precmd` hook silently calls `copa _record` in the background after each command, building up frequency and recency data with zero latency impact.
96
115
  2. **Replaces Ctrl+R** — the default zsh reverse-history-search is replaced with Copa's fzf-powered command palette (see below).
97
116
  3. **Supplements tab completion** — Copa registers as a completer so that any command gets completion candidates from your Copa database. The behavior is configurable (`fallback`, `hybrid`, `always`, or `never`) — see [Tab Completion](#tab-completion).
98
117
 
99
- Initialize the database:
118
+ ### Manual setup
119
+
120
+ If you prefer to set up manually instead of using `copa setup`:
100
121
 
101
122
  ```bash
102
- copa _init
123
+ # Add shell integration to ~/.zshrc
124
+ echo 'eval "$(copa init zsh)"' >> ~/.zshrc
125
+
126
+ # Activate in current terminal
127
+ source ~/.zshrc
128
+
129
+ # Import your history (optional)
130
+ copa sync
103
131
  ```
104
132
 
105
133
  ## Ctrl+R — fzf Command Palette
@@ -148,11 +176,40 @@ While the fzf palette is open, these keys are available:
148
176
  | **Ctrl+N** | Cycle group | Cycles through groups: (all) → group1 → group2 → ... → (all) |
149
177
  | **Ctrl+D** | Describe | Generate/edit a description using LLM (with tty-aware input) |
150
178
  | **Ctrl+F** | Edit flags | Add flag documentation to the highlighted command |
179
+ | **Ctrl+B** | Select mode | Enter multi-select for bulk operations (see below) |
151
180
  | **Ctrl+H** | Toggle header | Show/hide the key hints for more screen space |
152
181
  | **ESC** | Cancel/back | In scope/group mode: returns to command list. Otherwise: closes fzf |
153
182
 
154
183
  Keybindings are configurable via `~/.copa/config.toml`. See [Configuration](#configuration).
155
184
 
185
+ ### Select mode (bulk operations)
186
+
187
+ Press **Ctrl+B** from the Ctrl+R palette to enter **select mode**. This opens a new fzf view with multi-select enabled:
188
+
189
+ - **Tab** toggles selection on individual commands
190
+ - **Ctrl+R** cycles modes (all → frequent → recent) just like the main palette
191
+ - **Enter** confirms your selection and shows the batch action menu
192
+ - **ESC** cancels and returns to your prompt
193
+
194
+ After selecting commands, Copa shows a batch action menu:
195
+
196
+ ```
197
+ Selected 5 command(s).
198
+ g = assign group
199
+ d = delete
200
+ a = auto-describe (LLM)
201
+ q = cancel
202
+ Action:
203
+ ```
204
+
205
+ | Action | What it does |
206
+ |--------|-------------|
207
+ | **g** | Assign all selected commands to a group (or clear their group) |
208
+ | **d** | Delete all selected commands (with confirmation) |
209
+ | **a** | Auto-generate descriptions for all selected commands using your configured LLM backend |
210
+
211
+ 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
+
156
213
  ### Preview pane
157
214
 
158
215
  The right side shows a detail card for the highlighted command: full description, usage, purpose, flag documentation, score breakdown, frequency, last used, source, group, shared set, and tags.
@@ -210,9 +267,85 @@ This works automatically once `copa.zsh` is sourced — no extra setup needed. T
210
267
 
211
268
  Copa's own CLI completions (`copa li<TAB>` → `list`) continue to work as before via Click's built-in completion.
212
269
 
270
+ ## Inline Suggestions (Ghost Text)
271
+
272
+ 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
+
274
+ ### How it works
275
+
276
+ As you type, Copa queries its database for commands starting with your current input and displays the highest-scored match as dim grey text after the cursor. The suggestion updates on every keystroke.
277
+
278
+ ```
279
+ $ git pu█sh origin main ← grey ghost text
280
+ ```
281
+
282
+ ### Keybindings
283
+
284
+ | Key | Suggestion showing | No suggestion |
285
+ |-----|-------------------|---------------|
286
+ | Type chars | Insert char, re-fetch suggestion | Insert char, fetch suggestion |
287
+ | Backspace | Delete char, **latch** (suppress suggestions) | Delete char normally |
288
+ | **Tab** | `tab_accept=1`: accept full suggestion. `tab_accept=2` (default): first Tab highlights suggestion (cyan), second Tab accepts | If latched: unlatch + re-fetch suggestion. Else: normal tab completion |
289
+ | **Down** | Highlight suggestion (enter confirming state) | History navigation |
290
+ | **Right arrow** | Accept one word, re-fetch | Move cursor right |
291
+ | Enter | Clear suggestion, execute | Execute |
292
+ | Esc | Dismiss suggestion | Normal Esc |
293
+ | Up | Clear suggestion, navigate history | History navigation |
294
+ | Ctrl+R | Clear suggestion, open fzf | Open fzf |
295
+
296
+ ### Tab accept mode
297
+
298
+ Copa supports two Tab behaviors when a suggestion is showing:
299
+
300
+ **Menu select** (`tab_accept = 2`, default):
301
+ 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** or **Space** — accepts the highlighted item
303
+ 3. Press **Escape** — cancels the menu, restores your original text
304
+ 4. Use **arrow keys** to navigate if you want a different completion
305
+
306
+ This gives you a chance to see alternatives before committing. The Copa suggestion is always the first item in the menu.
307
+
308
+ **Inline accept** (`tab_accept = 1`):
309
+ - Press **Tab** — the suggestion is accepted directly into your command line. One keystroke, done.
310
+
311
+ ### Completion menu navigation
312
+
313
+ When the completion menu is open (from Tab in `tab_accept = 2` mode or from normal tab completion):
314
+
315
+ | Key | Action |
316
+ |-----|--------|
317
+ | **Tab** | Accept the highlighted completion |
318
+ | **Space** | Accept the highlighted completion |
319
+ | **Escape** | Cancel — dismiss menu, restore original text |
320
+ | **Arrow keys** | Navigate between completions |
321
+
322
+ ### Backspace latch
323
+
324
+ Pressing Backspace clears the current suggestion and **latches** — suppresses further suggestions while you edit. This prevents suggestions from re-appearing as you retype after correcting a mistake. Ctrl+W (backward-kill-word) also latches.
325
+
326
+ Press **Tab** to unlatch and re-enable suggestions. The next new prompt (Enter) also resets the latch automatically.
327
+
328
+ ### Configuration
329
+
330
+ ```toml
331
+ # ~/.copa/config.toml
332
+ [suggest]
333
+ enabled = true # set to false to disable inline suggestions
334
+ min_length = 2 # minimum characters before querying (default: 2)
335
+ tab_accept = 2 # 1 = Tab accepts directly, 2 = Tab opens menu first (default)
336
+ color = 242 # ghost text color (256-color palette, default: 242 mid-grey)
337
+ ```
338
+
339
+ The `color` value is a [256-color palette](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) number. Some useful values: `240` (darker grey), `242` (default mid-grey), `245` (lighter grey), `8` (bright black), `244` (light grey).
340
+
341
+ Inline suggestions are enabled by default. Set `enabled = false` to disable them entirely (zero performance overhead when disabled).
342
+
213
343
  ## Quick Start
214
344
 
215
345
  ```bash
346
+ # Check your setup
347
+ copa doctor
348
+
216
349
  # Import your shell history
217
350
  copa sync
218
351
 
@@ -222,15 +355,24 @@ copa add "adb shell cmd bluetooth_manager enable" -d "Enable Bluetooth" -g bluet
222
355
  # Add a command with flag documentation
223
356
  copa add "flash_all" -d "Flash AOSP build" -f "--wipe: Wipe userdata" -f "-v: Verbose"
224
357
 
225
- # Create a .copa file from a group (or scaffold an empty one)
226
- copa create -g bluetooth
358
+ # Pin your most important commands to the top
359
+ copa pin 42
360
+
361
+ # Edit a command's metadata
362
+ copa edit 42 -d "New description" -g mygroup
227
363
 
228
364
  # List top commands by score
229
365
  copa list
230
366
 
367
+ # List as JSON (for scripting)
368
+ copa list --json
369
+
231
370
  # Search by keyword
232
371
  copa search bluetooth
233
372
 
373
+ # Create a .copa file from a group (or scaffold an empty one)
374
+ copa create -g bluetooth
375
+
234
376
  # Auto-promote frequent commands from history
235
377
  copa evolve -k 20
236
378
 
@@ -356,7 +498,7 @@ copa create -g bluetooth
356
498
  copa share export bluetooth -o bluetooth.copa
357
499
  ```
358
500
 
359
- Share it with your team (via git, fbsource, or any file share):
501
+ Share it with your team (via git, Slack, or any file share):
360
502
 
361
503
  ```bash
362
504
  copa share load bluetooth.copa
@@ -364,6 +506,37 @@ copa share load /path/to/team/commands.copa
364
506
  copa share sync /path/to/team/copa-files/
365
507
  ```
366
508
 
509
+ ### Example shared sets
510
+
511
+ Copa ships with ready-to-use `.copa` files in the [`examples/`](examples/) directory:
512
+
513
+ | File | Description |
514
+ |------|-------------|
515
+ | [`git.copa`](examples/git.copa) | Essential Git commands |
516
+ | [`docker.copa`](examples/docker.copa) | Docker container management |
517
+ | [`python-dev.copa`](examples/python-dev.copa) | Python development workflow |
518
+ | [`npm.copa`](examples/npm.copa) | Node.js package management |
519
+ | [`network.copa`](examples/network.copa) | Network diagnostics |
520
+ | [`curl-http.copa`](examples/curl-http.copa) | HTTP requests and API testing |
521
+ | [`ssh-remote.copa`](examples/ssh-remote.copa) | SSH, SCP, and remote server management |
522
+ | [`adb.copa`](examples/adb.copa) | Android Debug Bridge |
523
+ | [`aws.copa`](examples/aws.copa) | AWS CLI cloud infrastructure |
524
+ | [`terraform.copa`](examples/terraform.copa) | Terraform infrastructure-as-code |
525
+ | [`k8s.copa`](examples/k8s.copa) | Kubernetes cluster management |
526
+ | [`systemd.copa`](examples/systemd.copa) | Linux service management |
527
+ | [`sysadmin.copa`](examples/sysadmin.copa) | System administration |
528
+ | [`process-monitoring.copa`](examples/process-monitoring.copa) | Process management and debugging |
529
+ | [`disk-files.copa`](examples/disk-files.copa) | Disk usage and file management |
530
+ | [`tmux.copa`](examples/tmux.copa) | Terminal multiplexer sessions |
531
+ | [`homebrew.copa`](examples/homebrew.copa) | Homebrew package manager (macOS) |
532
+
533
+ Load any of them:
534
+
535
+ ```bash
536
+ copa share load examples/git.copa
537
+ copa share load examples/docker.copa
538
+ ```
539
+
367
540
  ### Filtering by shared set
368
541
 
369
542
  Once you've loaded shared sets, you can scope commands to just that set:
@@ -474,24 +647,66 @@ group = "ctrl-g" # assign group (inline modal)
474
647
  flags = "ctrl-f" # edit flags
475
648
  filter_group = "ctrl-s" # scope by group (inline modal)
476
649
  cycle_group = "ctrl-n" # cycle through groups
650
+ select = "ctrl-b" # enter select mode (bulk operations)
477
651
  toggle_header = "ctrl-h" # show/hide key hints
478
652
 
479
653
  # Tab completion behavior
480
654
  [completion]
481
655
  mode = "fallback" # fallback | hybrid | always | never
482
656
  branding = true # show "Copa history" group header
657
+
658
+ # Inline suggestions (ghost text)
659
+ [suggest]
660
+ enabled = true # set to false to disable
661
+ min_length = 2 # minimum chars before querying
662
+ tab_accept = 2 # 1 = accept directly, 2 = open menu first
663
+ color = 242 # ghost text color (256-color palette)
664
+
665
+ # Composition key behavior (continue vs close)
666
+ # "continue" keys re-open fzf so you can chain another command
667
+ # All other composition keys close fzf immediately
668
+ [composition]
669
+ continue = ["pipe", "chain", "redirect"] # default: |, &&, > re-open fzf
670
+ ```
671
+
672
+ ### Composition key behavior
673
+
674
+ 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).
675
+
676
+ By default, "connector" operators re-open fzf:
677
+ - `pipe` (`|`) — continue
678
+ - `chain` (`&&`) — continue
679
+ - `redirect` (`>`) — continue
680
+
681
+ And "terminal" operators close fzf:
682
+ - `background` (`&`) — close
683
+ - `merge_output` (`2>&1`) — close
684
+ - `suppress` (`2>/dev/null`) — close
685
+
686
+ When chaining, the prompt shows your accumulated command: `copa [git pull && ]>`.
687
+
688
+ To revert to the old behavior (all keys close immediately), set:
689
+
690
+ ```toml
691
+ [composition]
692
+ continue = []
483
693
  ```
484
694
 
485
695
  ## CLI Reference
486
696
 
487
697
  | Command | Purpose |
488
698
  |---------|---------|
699
+ | `copa setup` | Interactive setup wizard |
489
700
  | `copa add "cmd" -d "desc" -g group -f "flag: desc"` | Save a command (with optional flags) |
490
- | `copa create -g group [-o file]` | Create a .copa file from a group |
491
- | `copa list [-g group] [-s source] [--set name]` | List by score |
492
- | `copa search "query" [-g group] [-s source] [--set name]` | FTS search |
701
+ | `copa edit ID [-d desc] [-g group] [-f flags] [--pin]` | Edit a command's metadata |
493
702
  | `copa remove ID` | Remove a command |
703
+ | `copa pin ID` | Pin a command to the top |
704
+ | `copa unpin ID` | Unpin a command |
705
+ | `copa list [-g group] [-s source] [--set name] [--json]` | List by score |
706
+ | `copa search "query" [-g group] [--set name] [--json]` | FTS search |
707
+ | `copa create -g group [-o file]` | Create a .copa file from a group |
494
708
  | `copa stats` | Usage statistics |
709
+ | `copa doctor` | Check setup and diagnose issues |
495
710
  | `copa sync` | Import from zsh history |
496
711
  | `copa scan [--dir path]` | Import script metadata from $PATH |
497
712
  | `copa evolve [-k 20] [--auto]` | Auto-add frequent commands (with optional LLM descriptions) |
@@ -503,6 +718,8 @@ branding = true # show "Copa history" group header
503
718
  | `copa share list` | List shared sets |
504
719
  | `copa share sync DIR` | Sync .copa files from dir |
505
720
  | `copa import FILE [-g group]` | Import commands from markdown |
721
+ | `copa reset` | Wipe database and start fresh (keeps config) |
722
+ | `copa uninstall` | Remove Copa data and show cleanup steps |
506
723
 
507
724
  ## How Scoring Works
508
725