copa-cli 0.3.1__tar.gz → 0.6.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 (39) hide show
  1. {copa_cli-0.3.1 → copa_cli-0.6.0}/PKG-INFO +191 -13
  2. {copa_cli-0.3.1 → copa_cli-0.6.0}/README.md +190 -12
  3. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/cli.py +196 -4
  4. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/cli_internal.py +165 -0
  5. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/cli_llm.py +33 -12
  6. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/config.py +80 -7
  7. copa_cli-0.6.0/copa/copa.zsh +578 -0
  8. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/db.py +3 -0
  9. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/PKG-INFO +191 -13
  10. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/SOURCES.txt +1 -0
  11. {copa_cli-0.3.1 → copa_cli-0.6.0}/pyproject.toml +1 -1
  12. copa_cli-0.6.0/tests/test_modal.py +1045 -0
  13. copa_cli-0.6.0/tests/test_polish.py +211 -0
  14. copa_cli-0.3.1/copa/copa.zsh +0 -179
  15. copa_cli-0.3.1/tests/test_modal.py +0 -183
  16. {copa_cli-0.3.1 → copa_cli-0.6.0}/LICENSE +0 -0
  17. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/__init__.py +0 -0
  18. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/__main__.py +0 -0
  19. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/cli_common.py +0 -0
  20. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/cli_share.py +0 -0
  21. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/evolve.py +0 -0
  22. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/fzf.py +0 -0
  23. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/history.py +0 -0
  24. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/llm.py +0 -0
  25. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/mcp_server.py +0 -0
  26. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/models.py +0 -0
  27. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/scanner.py +0 -0
  28. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/scoring.py +0 -0
  29. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/sharing.py +0 -0
  30. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/dependency_links.txt +0 -0
  31. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/entry_points.txt +0 -0
  32. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/requires.txt +0 -0
  33. {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/top_level.txt +0 -0
  34. {copa_cli-0.3.1 → copa_cli-0.6.0}/setup.cfg +0 -0
  35. {copa_cli-0.3.1 → copa_cli-0.6.0}/tests/test_cli_and_sharing.py +0 -0
  36. {copa_cli-0.3.1 → copa_cli-0.6.0}/tests/test_db.py +0 -0
  37. {copa_cli-0.3.1 → copa_cli-0.6.0}/tests/test_fzf.py +0 -0
  38. {copa_cli-0.3.1 → copa_cli-0.6.0}/tests/test_models.py +0 -0
  39. {copa_cli-0.3.1 → copa_cli-0.6.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.1
3
+ Version: 0.6.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
@@ -52,11 +52,14 @@ Copa tracks the commands you run, ranks them by frequency and recency, and gives
52
52
  - **MCP server** — expose your commands to Claude Code (or any MCP client)
53
53
  - **Zero latency** — precmd hook records usage in the background
54
54
 
55
+ > **Note:** Copa requires **zsh**. It is not compatible with bash, fish, or PowerShell.
56
+
55
57
  ## Install
56
58
 
57
59
  ### Prerequisites
58
60
 
59
61
  - **Python 3.12+**
62
+ - **zsh** — Copa's shell integration (precmd hooks, ZLE widgets, inline suggestions) is zsh-only
60
63
  - **fzf** — required for Ctrl+R command palette
61
64
 
62
65
  ```bash
@@ -94,7 +97,7 @@ Then restart your shell or run `source ~/.zshrc`. This does three things:
94
97
 
95
98
  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
99
  2. **Replaces Ctrl+R** — the default zsh reverse-history-search is replaced with Copa's fzf-powered command palette (see below).
97
- 3. **Supplements tab completion** — Copa registers as a fallback completer so that any command gets completion candidates from your Copa database (see [Tab Completion](#tab-completion) below).
100
+ 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
101
 
99
102
  Initialize the database:
100
103
 
@@ -143,11 +146,15 @@ While the fzf palette is open, these keys are available:
143
146
  | **Ctrl+T** | Append `>` | Redirect output |
144
147
  | **Ctrl+A** | Append `&&` | Chain with next command |
145
148
  | **Ctrl+/** | Append `2>/dev/null` | Suppress stderr |
146
- | **Ctrl+G** | Set group | Assign or change the group for the highlighted command |
147
- | **Ctrl+D** | Describe | Generate/edit a description for the highlighted command |
149
+ | **Ctrl+S** | Scope by group | Opens inline group list — Enter filters to that group, ESC returns to all |
150
+ | **Ctrl+G** | Assign group | Opens inline group list — Enter assigns the group to the highlighted command |
151
+ | **Ctrl+N** | Cycle group | Cycles through groups: (all) → group1 → group2 → ... → (all) |
152
+ | **Ctrl+D** | Describe | Generate/edit a description using LLM (with tty-aware input) |
148
153
  | **Ctrl+F** | Edit flags | Add flag documentation to the highlighted command |
154
+ | **Ctrl+H** | Toggle header | Show/hide the key hints for more screen space |
155
+ | **ESC** | Cancel/back | In scope/group mode: returns to command list. Otherwise: closes fzf |
149
156
 
150
- Keybindings are configurable via `~/.copa/config.toml`. See the `[keys]` section.
157
+ Keybindings are configurable via `~/.copa/config.toml`. See [Configuration](#configuration).
151
158
 
152
159
  ### Preview pane
153
160
 
@@ -159,11 +166,29 @@ Selecting a command places it directly into your shell prompt (without executing
159
166
 
160
167
  ## Tab Completion
161
168
 
162
- 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 fallback completer in zsh's completion system.
169
+ 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.
170
+
171
+ ### Completion modes
172
+
173
+ Copa supports four completion modes, configured via `~/.copa/config.toml`:
174
+
175
+ | Mode | Behavior |
176
+ |------|----------|
177
+ | `fallback` | **(default)** Only show Copa completions when native completers found nothing |
178
+ | `hybrid` | Show Copa completions alongside native completions (in a separate group) |
179
+ | `always` | Copa completions replace native completions |
180
+ | `never` | Disable Copa tab completion entirely |
181
+
182
+ ```toml
183
+ # ~/.copa/config.toml
184
+ [completion]
185
+ mode = "fallback" # fallback | hybrid | always | never
186
+ branding = true # show "Copa history" group header
187
+ ```
163
188
 
164
189
  ### How it works
165
190
 
166
- When you press Tab, zsh runs its normal completers first. If Copa's fallback also fires, it queries the Copa database for commands matching what you've typed so far and suggests the next word(s):
191
+ When you press Tab, Copa queries its database for commands matching what you've typed so far and suggests the next word(s):
167
192
 
168
193
  ```
169
194
  $ adb shell dump<TAB>
@@ -188,9 +213,62 @@ This works automatically once `copa.zsh` is sourced — no extra setup needed. T
188
213
 
189
214
  Copa's own CLI completions (`copa li<TAB>` → `list`) continue to work as before via Click's built-in completion.
190
215
 
216
+ ## Inline Suggestions (Ghost Text)
217
+
218
+ 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.
219
+
220
+ ### How it works
221
+
222
+ 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.
223
+
224
+ ```
225
+ $ git pu█sh origin main ← grey ghost text
226
+ ```
227
+
228
+ ### Keybindings
229
+
230
+ | Key | Suggestion showing | No suggestion |
231
+ |-----|-------------------|---------------|
232
+ | Type chars | Insert char, re-fetch suggestion | Insert char, fetch suggestion |
233
+ | Backspace | Delete char, **latch** (suppress suggestions) | Delete char normally |
234
+ | **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 |
235
+ | **Down** | Highlight suggestion (enter confirming state) | History navigation |
236
+ | **Right arrow** | Accept one word, re-fetch | Move cursor right |
237
+ | Enter | Clear suggestion, execute | Execute |
238
+ | Esc | Dismiss suggestion | Normal Esc |
239
+ | Up | Clear suggestion, navigate history | History navigation |
240
+ | Ctrl+R | Clear suggestion, open fzf | Open fzf |
241
+
242
+ ### Tab accept mode
243
+
244
+ By default (`tab_accept = 2`), pressing Tab when a suggestion is showing highlights the ghost text (changes from dim grey to cyan/bold) to indicate it's ready to be accepted. Pressing Tab again accepts it into the buffer. Pressing Esc reverts to dim grey without accepting. This two-step flow gives you a visual confirmation before committing.
245
+
246
+ Set `tab_accept = 1` to restore the old behavior where a single Tab directly accepts the suggestion.
247
+
248
+ ### Backspace latch
249
+
250
+ 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.
251
+
252
+ Press **Tab** to unlatch and re-enable suggestions. The next new prompt (Enter) also resets the latch automatically.
253
+
254
+ ### Configuration
255
+
256
+ ```toml
257
+ # ~/.copa/config.toml
258
+ [suggest]
259
+ enabled = true # set to false to disable inline suggestions
260
+ min_length = 2 # minimum characters before querying (default: 2)
261
+ tab_accept = 2 # 1 = Tab accepts directly, 2 = Tab opens menu first (default)
262
+ ```
263
+
264
+ Inline suggestions are enabled by default. Set `enabled = false` to disable them entirely (zero performance overhead when disabled).
265
+
191
266
  ## Quick Start
192
267
 
193
268
  ```bash
269
+ # Check your setup
270
+ copa doctor
271
+
194
272
  # Import your shell history
195
273
  copa sync
196
274
 
@@ -200,15 +278,24 @@ copa add "adb shell cmd bluetooth_manager enable" -d "Enable Bluetooth" -g bluet
200
278
  # Add a command with flag documentation
201
279
  copa add "flash_all" -d "Flash AOSP build" -f "--wipe: Wipe userdata" -f "-v: Verbose"
202
280
 
203
- # Create a .copa file from a group (or scaffold an empty one)
204
- copa create -g bluetooth
281
+ # Pin your most important commands to the top
282
+ copa pin 42
283
+
284
+ # Edit a command's metadata
285
+ copa edit 42 -d "New description" -g mygroup
205
286
 
206
287
  # List top commands by score
207
288
  copa list
208
289
 
290
+ # List as JSON (for scripting)
291
+ copa list --json
292
+
209
293
  # Search by keyword
210
294
  copa search bluetooth
211
295
 
296
+ # Create a .copa file from a group (or scaffold an empty one)
297
+ copa create -g bluetooth
298
+
212
299
  # Auto-promote frequent commands from history
213
300
  copa evolve -k 20
214
301
 
@@ -334,7 +421,7 @@ copa create -g bluetooth
334
421
  copa share export bluetooth -o bluetooth.copa
335
422
  ```
336
423
 
337
- Share it with your team (via git, fbsource, or any file share):
424
+ Share it with your team (via git, Slack, or any file share):
338
425
 
339
426
  ```bash
340
427
  copa share load bluetooth.copa
@@ -342,6 +429,27 @@ copa share load /path/to/team/commands.copa
342
429
  copa share sync /path/to/team/copa-files/
343
430
  ```
344
431
 
432
+ ### Example shared sets
433
+
434
+ Copa ships with ready-to-use `.copa` files in the [`examples/`](examples/) directory:
435
+
436
+ | File | Description |
437
+ |------|-------------|
438
+ | [`git.copa`](examples/git.copa) | Essential Git commands |
439
+ | [`docker.copa`](examples/docker.copa) | Docker container management |
440
+ | [`python-dev.copa`](examples/python-dev.copa) | Python development workflow |
441
+ | [`network.copa`](examples/network.copa) | Network diagnostics |
442
+ | [`adb.copa`](examples/adb.copa) | Android Debug Bridge |
443
+ | [`k8s.copa`](examples/k8s.copa) | Kubernetes cluster management |
444
+ | [`sysadmin.copa`](examples/sysadmin.copa) | System administration |
445
+
446
+ Load any of them:
447
+
448
+ ```bash
449
+ copa share load examples/git.copa
450
+ copa share load examples/docker.copa
451
+ ```
452
+
345
453
  ### Filtering by shared set
346
454
 
347
455
  Once you've loaded shared sets, you can scope commands to just that set:
@@ -430,16 +538,85 @@ Available MCP tools:
430
538
  - `copa_create_group` — create a group with commands
431
539
  - `copa_bulk_add` — bulk add commands
432
540
 
541
+ ## Configuration
542
+
543
+ Copa is configured via `~/.copa/config.toml`. All settings are optional — Copa uses sensible defaults.
544
+
545
+ ```toml
546
+ # ~/.copa/config.toml
547
+
548
+ # Keybindings for the Ctrl+R fzf palette
549
+ # Values are fzf key names: ctrl-<letter>, alt-<letter>, ctrl-/
550
+ # ctrl-r and enter are reserved and cannot be reassigned
551
+ [keys]
552
+ background = "ctrl-v" # append &
553
+ merge_output = "ctrl-o" # append 2>&1
554
+ pipe = "ctrl-x" # append |
555
+ redirect = "ctrl-t" # append >
556
+ chain = "ctrl-a" # append &&
557
+ suppress = "ctrl-/" # append 2>/dev/null
558
+ describe = "ctrl-d" # LLM describe
559
+ group = "ctrl-g" # assign group (inline modal)
560
+ flags = "ctrl-f" # edit flags
561
+ filter_group = "ctrl-s" # scope by group (inline modal)
562
+ cycle_group = "ctrl-n" # cycle through groups
563
+ toggle_header = "ctrl-h" # show/hide key hints
564
+
565
+ # Tab completion behavior
566
+ [completion]
567
+ mode = "fallback" # fallback | hybrid | always | never
568
+ branding = true # show "Copa history" group header
569
+
570
+ # Inline suggestions (ghost text)
571
+ [suggest]
572
+ enabled = true # set to false to disable
573
+ min_length = 2 # minimum chars before querying
574
+ tab_accept = 2 # 1 = accept directly, 2 = open menu first
575
+
576
+ # Composition key behavior (continue vs close)
577
+ # "continue" keys re-open fzf so you can chain another command
578
+ # All other composition keys close fzf immediately
579
+ [composition]
580
+ continue = ["pipe", "chain", "redirect"] # default: |, &&, > re-open fzf
581
+ ```
582
+
583
+ ### Composition key behavior
584
+
585
+ 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).
586
+
587
+ By default, "connector" operators re-open fzf:
588
+ - `pipe` (`|`) — continue
589
+ - `chain` (`&&`) — continue
590
+ - `redirect` (`>`) — continue
591
+
592
+ And "terminal" operators close fzf:
593
+ - `background` (`&`) — close
594
+ - `merge_output` (`2>&1`) — close
595
+ - `suppress` (`2>/dev/null`) — close
596
+
597
+ When chaining, the prompt shows your accumulated command: `copa [git pull && ]>`.
598
+
599
+ To revert to the old behavior (all keys close immediately), set:
600
+
601
+ ```toml
602
+ [composition]
603
+ continue = []
604
+ ```
605
+
433
606
  ## CLI Reference
434
607
 
435
608
  | Command | Purpose |
436
609
  |---------|---------|
437
610
  | `copa add "cmd" -d "desc" -g group -f "flag: desc"` | Save a command (with optional flags) |
438
- | `copa create -g group [-o file]` | Create a .copa file from a group |
439
- | `copa list [-g group] [-s source] [--set name]` | List by score |
440
- | `copa search "query" [-g group] [-s source] [--set name]` | FTS search |
611
+ | `copa edit ID [-d desc] [-g group] [-f flags] [--pin]` | Edit a command's metadata |
441
612
  | `copa remove ID` | Remove a command |
613
+ | `copa pin ID` | Pin a command to the top |
614
+ | `copa unpin ID` | Unpin a command |
615
+ | `copa list [-g group] [-s source] [--set name] [--json]` | List by score |
616
+ | `copa search "query" [-g group] [--set name] [--json]` | FTS search |
617
+ | `copa create -g group [-o file]` | Create a .copa file from a group |
442
618
  | `copa stats` | Usage statistics |
619
+ | `copa doctor` | Check setup and diagnose issues |
443
620
  | `copa sync` | Import from zsh history |
444
621
  | `copa scan [--dir path]` | Import script metadata from $PATH |
445
622
  | `copa evolve [-k 20] [--auto]` | Auto-add frequent commands (with optional LLM descriptions) |
@@ -451,6 +628,7 @@ Available MCP tools:
451
628
  | `copa share list` | List shared sets |
452
629
  | `copa share sync DIR` | Sync .copa files from dir |
453
630
  | `copa import FILE [-g group]` | Import commands from markdown |
631
+ | `copa uninstall` | Remove Copa data and show cleanup steps |
454
632
 
455
633
  ## How Scoring Works
456
634
 
@@ -22,11 +22,14 @@ Copa tracks the commands you run, ranks them by frequency and recency, and gives
22
22
  - **MCP server** — expose your commands to Claude Code (or any MCP client)
23
23
  - **Zero latency** — precmd hook records usage in the background
24
24
 
25
+ > **Note:** Copa requires **zsh**. It is not compatible with bash, fish, or PowerShell.
26
+
25
27
  ## Install
26
28
 
27
29
  ### Prerequisites
28
30
 
29
31
  - **Python 3.12+**
32
+ - **zsh** — Copa's shell integration (precmd hooks, ZLE widgets, inline suggestions) is zsh-only
30
33
  - **fzf** — required for Ctrl+R command palette
31
34
 
32
35
  ```bash
@@ -64,7 +67,7 @@ Then restart your shell or run `source ~/.zshrc`. This does three things:
64
67
 
65
68
  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.
66
69
  2. **Replaces Ctrl+R** — the default zsh reverse-history-search is replaced with Copa's fzf-powered command palette (see below).
67
- 3. **Supplements tab completion** — Copa registers as a fallback completer so that any command gets completion candidates from your Copa database (see [Tab Completion](#tab-completion) below).
70
+ 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).
68
71
 
69
72
  Initialize the database:
70
73
 
@@ -113,11 +116,15 @@ While the fzf palette is open, these keys are available:
113
116
  | **Ctrl+T** | Append `>` | Redirect output |
114
117
  | **Ctrl+A** | Append `&&` | Chain with next command |
115
118
  | **Ctrl+/** | Append `2>/dev/null` | Suppress stderr |
116
- | **Ctrl+G** | Set group | Assign or change the group for the highlighted command |
117
- | **Ctrl+D** | Describe | Generate/edit a description for the highlighted command |
119
+ | **Ctrl+S** | Scope by group | Opens inline group list — Enter filters to that group, ESC returns to all |
120
+ | **Ctrl+G** | Assign group | Opens inline group list — Enter assigns the group to the highlighted command |
121
+ | **Ctrl+N** | Cycle group | Cycles through groups: (all) → group1 → group2 → ... → (all) |
122
+ | **Ctrl+D** | Describe | Generate/edit a description using LLM (with tty-aware input) |
118
123
  | **Ctrl+F** | Edit flags | Add flag documentation to the highlighted command |
124
+ | **Ctrl+H** | Toggle header | Show/hide the key hints for more screen space |
125
+ | **ESC** | Cancel/back | In scope/group mode: returns to command list. Otherwise: closes fzf |
119
126
 
120
- Keybindings are configurable via `~/.copa/config.toml`. See the `[keys]` section.
127
+ Keybindings are configurable via `~/.copa/config.toml`. See [Configuration](#configuration).
121
128
 
122
129
  ### Preview pane
123
130
 
@@ -129,11 +136,29 @@ Selecting a command places it directly into your shell prompt (without executing
129
136
 
130
137
  ## Tab Completion
131
138
 
132
- 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 fallback completer in zsh's completion system.
139
+ 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.
140
+
141
+ ### Completion modes
142
+
143
+ Copa supports four completion modes, configured via `~/.copa/config.toml`:
144
+
145
+ | Mode | Behavior |
146
+ |------|----------|
147
+ | `fallback` | **(default)** Only show Copa completions when native completers found nothing |
148
+ | `hybrid` | Show Copa completions alongside native completions (in a separate group) |
149
+ | `always` | Copa completions replace native completions |
150
+ | `never` | Disable Copa tab completion entirely |
151
+
152
+ ```toml
153
+ # ~/.copa/config.toml
154
+ [completion]
155
+ mode = "fallback" # fallback | hybrid | always | never
156
+ branding = true # show "Copa history" group header
157
+ ```
133
158
 
134
159
  ### How it works
135
160
 
136
- When you press Tab, zsh runs its normal completers first. If Copa's fallback also fires, it queries the Copa database for commands matching what you've typed so far and suggests the next word(s):
161
+ When you press Tab, Copa queries its database for commands matching what you've typed so far and suggests the next word(s):
137
162
 
138
163
  ```
139
164
  $ adb shell dump<TAB>
@@ -158,9 +183,62 @@ This works automatically once `copa.zsh` is sourced — no extra setup needed. T
158
183
 
159
184
  Copa's own CLI completions (`copa li<TAB>` → `list`) continue to work as before via Click's built-in completion.
160
185
 
186
+ ## Inline Suggestions (Ghost Text)
187
+
188
+ 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.
189
+
190
+ ### How it works
191
+
192
+ 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.
193
+
194
+ ```
195
+ $ git pu█sh origin main ← grey ghost text
196
+ ```
197
+
198
+ ### Keybindings
199
+
200
+ | Key | Suggestion showing | No suggestion |
201
+ |-----|-------------------|---------------|
202
+ | Type chars | Insert char, re-fetch suggestion | Insert char, fetch suggestion |
203
+ | Backspace | Delete char, **latch** (suppress suggestions) | Delete char normally |
204
+ | **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 |
205
+ | **Down** | Highlight suggestion (enter confirming state) | History navigation |
206
+ | **Right arrow** | Accept one word, re-fetch | Move cursor right |
207
+ | Enter | Clear suggestion, execute | Execute |
208
+ | Esc | Dismiss suggestion | Normal Esc |
209
+ | Up | Clear suggestion, navigate history | History navigation |
210
+ | Ctrl+R | Clear suggestion, open fzf | Open fzf |
211
+
212
+ ### Tab accept mode
213
+
214
+ By default (`tab_accept = 2`), pressing Tab when a suggestion is showing highlights the ghost text (changes from dim grey to cyan/bold) to indicate it's ready to be accepted. Pressing Tab again accepts it into the buffer. Pressing Esc reverts to dim grey without accepting. This two-step flow gives you a visual confirmation before committing.
215
+
216
+ Set `tab_accept = 1` to restore the old behavior where a single Tab directly accepts the suggestion.
217
+
218
+ ### Backspace latch
219
+
220
+ 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.
221
+
222
+ Press **Tab** to unlatch and re-enable suggestions. The next new prompt (Enter) also resets the latch automatically.
223
+
224
+ ### Configuration
225
+
226
+ ```toml
227
+ # ~/.copa/config.toml
228
+ [suggest]
229
+ enabled = true # set to false to disable inline suggestions
230
+ min_length = 2 # minimum characters before querying (default: 2)
231
+ tab_accept = 2 # 1 = Tab accepts directly, 2 = Tab opens menu first (default)
232
+ ```
233
+
234
+ Inline suggestions are enabled by default. Set `enabled = false` to disable them entirely (zero performance overhead when disabled).
235
+
161
236
  ## Quick Start
162
237
 
163
238
  ```bash
239
+ # Check your setup
240
+ copa doctor
241
+
164
242
  # Import your shell history
165
243
  copa sync
166
244
 
@@ -170,15 +248,24 @@ copa add "adb shell cmd bluetooth_manager enable" -d "Enable Bluetooth" -g bluet
170
248
  # Add a command with flag documentation
171
249
  copa add "flash_all" -d "Flash AOSP build" -f "--wipe: Wipe userdata" -f "-v: Verbose"
172
250
 
173
- # Create a .copa file from a group (or scaffold an empty one)
174
- copa create -g bluetooth
251
+ # Pin your most important commands to the top
252
+ copa pin 42
253
+
254
+ # Edit a command's metadata
255
+ copa edit 42 -d "New description" -g mygroup
175
256
 
176
257
  # List top commands by score
177
258
  copa list
178
259
 
260
+ # List as JSON (for scripting)
261
+ copa list --json
262
+
179
263
  # Search by keyword
180
264
  copa search bluetooth
181
265
 
266
+ # Create a .copa file from a group (or scaffold an empty one)
267
+ copa create -g bluetooth
268
+
182
269
  # Auto-promote frequent commands from history
183
270
  copa evolve -k 20
184
271
 
@@ -304,7 +391,7 @@ copa create -g bluetooth
304
391
  copa share export bluetooth -o bluetooth.copa
305
392
  ```
306
393
 
307
- Share it with your team (via git, fbsource, or any file share):
394
+ Share it with your team (via git, Slack, or any file share):
308
395
 
309
396
  ```bash
310
397
  copa share load bluetooth.copa
@@ -312,6 +399,27 @@ copa share load /path/to/team/commands.copa
312
399
  copa share sync /path/to/team/copa-files/
313
400
  ```
314
401
 
402
+ ### Example shared sets
403
+
404
+ Copa ships with ready-to-use `.copa` files in the [`examples/`](examples/) directory:
405
+
406
+ | File | Description |
407
+ |------|-------------|
408
+ | [`git.copa`](examples/git.copa) | Essential Git commands |
409
+ | [`docker.copa`](examples/docker.copa) | Docker container management |
410
+ | [`python-dev.copa`](examples/python-dev.copa) | Python development workflow |
411
+ | [`network.copa`](examples/network.copa) | Network diagnostics |
412
+ | [`adb.copa`](examples/adb.copa) | Android Debug Bridge |
413
+ | [`k8s.copa`](examples/k8s.copa) | Kubernetes cluster management |
414
+ | [`sysadmin.copa`](examples/sysadmin.copa) | System administration |
415
+
416
+ Load any of them:
417
+
418
+ ```bash
419
+ copa share load examples/git.copa
420
+ copa share load examples/docker.copa
421
+ ```
422
+
315
423
  ### Filtering by shared set
316
424
 
317
425
  Once you've loaded shared sets, you can scope commands to just that set:
@@ -400,16 +508,85 @@ Available MCP tools:
400
508
  - `copa_create_group` — create a group with commands
401
509
  - `copa_bulk_add` — bulk add commands
402
510
 
511
+ ## Configuration
512
+
513
+ Copa is configured via `~/.copa/config.toml`. All settings are optional — Copa uses sensible defaults.
514
+
515
+ ```toml
516
+ # ~/.copa/config.toml
517
+
518
+ # Keybindings for the Ctrl+R fzf palette
519
+ # Values are fzf key names: ctrl-<letter>, alt-<letter>, ctrl-/
520
+ # ctrl-r and enter are reserved and cannot be reassigned
521
+ [keys]
522
+ background = "ctrl-v" # append &
523
+ merge_output = "ctrl-o" # append 2>&1
524
+ pipe = "ctrl-x" # append |
525
+ redirect = "ctrl-t" # append >
526
+ chain = "ctrl-a" # append &&
527
+ suppress = "ctrl-/" # append 2>/dev/null
528
+ describe = "ctrl-d" # LLM describe
529
+ group = "ctrl-g" # assign group (inline modal)
530
+ flags = "ctrl-f" # edit flags
531
+ filter_group = "ctrl-s" # scope by group (inline modal)
532
+ cycle_group = "ctrl-n" # cycle through groups
533
+ toggle_header = "ctrl-h" # show/hide key hints
534
+
535
+ # Tab completion behavior
536
+ [completion]
537
+ mode = "fallback" # fallback | hybrid | always | never
538
+ branding = true # show "Copa history" group header
539
+
540
+ # Inline suggestions (ghost text)
541
+ [suggest]
542
+ enabled = true # set to false to disable
543
+ min_length = 2 # minimum chars before querying
544
+ tab_accept = 2 # 1 = accept directly, 2 = open menu first
545
+
546
+ # Composition key behavior (continue vs close)
547
+ # "continue" keys re-open fzf so you can chain another command
548
+ # All other composition keys close fzf immediately
549
+ [composition]
550
+ continue = ["pipe", "chain", "redirect"] # default: |, &&, > re-open fzf
551
+ ```
552
+
553
+ ### Composition key behavior
554
+
555
+ 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).
556
+
557
+ By default, "connector" operators re-open fzf:
558
+ - `pipe` (`|`) — continue
559
+ - `chain` (`&&`) — continue
560
+ - `redirect` (`>`) — continue
561
+
562
+ And "terminal" operators close fzf:
563
+ - `background` (`&`) — close
564
+ - `merge_output` (`2>&1`) — close
565
+ - `suppress` (`2>/dev/null`) — close
566
+
567
+ When chaining, the prompt shows your accumulated command: `copa [git pull && ]>`.
568
+
569
+ To revert to the old behavior (all keys close immediately), set:
570
+
571
+ ```toml
572
+ [composition]
573
+ continue = []
574
+ ```
575
+
403
576
  ## CLI Reference
404
577
 
405
578
  | Command | Purpose |
406
579
  |---------|---------|
407
580
  | `copa add "cmd" -d "desc" -g group -f "flag: desc"` | Save a command (with optional flags) |
408
- | `copa create -g group [-o file]` | Create a .copa file from a group |
409
- | `copa list [-g group] [-s source] [--set name]` | List by score |
410
- | `copa search "query" [-g group] [-s source] [--set name]` | FTS search |
581
+ | `copa edit ID [-d desc] [-g group] [-f flags] [--pin]` | Edit a command's metadata |
411
582
  | `copa remove ID` | Remove a command |
583
+ | `copa pin ID` | Pin a command to the top |
584
+ | `copa unpin ID` | Unpin a command |
585
+ | `copa list [-g group] [-s source] [--set name] [--json]` | List by score |
586
+ | `copa search "query" [-g group] [--set name] [--json]` | FTS search |
587
+ | `copa create -g group [-o file]` | Create a .copa file from a group |
412
588
  | `copa stats` | Usage statistics |
589
+ | `copa doctor` | Check setup and diagnose issues |
413
590
  | `copa sync` | Import from zsh history |
414
591
  | `copa scan [--dir path]` | Import script metadata from $PATH |
415
592
  | `copa evolve [-k 20] [--auto]` | Auto-add frequent commands (with optional LLM descriptions) |
@@ -421,6 +598,7 @@ Available MCP tools:
421
598
  | `copa share list` | List shared sets |
422
599
  | `copa share sync DIR` | Sync .copa files from dir |
423
600
  | `copa import FILE [-g group]` | Import commands from markdown |
601
+ | `copa uninstall` | Remove Copa data and show cleanup steps |
424
602
 
425
603
  ## How Scoring Works
426
604