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.
- {copa_cli-0.3.1 → copa_cli-0.6.0}/PKG-INFO +191 -13
- {copa_cli-0.3.1 → copa_cli-0.6.0}/README.md +190 -12
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/cli.py +196 -4
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/cli_internal.py +165 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/cli_llm.py +33 -12
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/config.py +80 -7
- copa_cli-0.6.0/copa/copa.zsh +578 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/db.py +3 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/PKG-INFO +191 -13
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/SOURCES.txt +1 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/pyproject.toml +1 -1
- copa_cli-0.6.0/tests/test_modal.py +1045 -0
- copa_cli-0.6.0/tests/test_polish.py +211 -0
- copa_cli-0.3.1/copa/copa.zsh +0 -179
- copa_cli-0.3.1/tests/test_modal.py +0 -183
- {copa_cli-0.3.1 → copa_cli-0.6.0}/LICENSE +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/__init__.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/__main__.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/cli_common.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/cli_share.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/evolve.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/fzf.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/history.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/llm.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/mcp_server.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/models.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/scanner.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/scoring.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa/sharing.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/dependency_links.txt +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/entry_points.txt +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/requires.txt +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/copa_cli.egg-info/top_level.txt +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/setup.cfg +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/tests/test_cli_and_sharing.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/tests/test_db.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/tests/test_fzf.py +0 -0
- {copa_cli-0.3.1 → copa_cli-0.6.0}/tests/test_models.py +0 -0
- {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
|
+
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
|
|
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+
|
|
147
|
-
| **Ctrl+
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
#
|
|
204
|
-
copa
|
|
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,
|
|
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
|
|
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
|
|
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+
|
|
117
|
-
| **Ctrl+
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
#
|
|
174
|
-
copa
|
|
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,
|
|
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
|
|
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
|
|