Skip to content

Commit 1adf3ce

Browse files
noameroncoderabbitai[bot]TabishB
authored
feature/oh-my-zsh-completions (#289)
* shell completions for zsh * after code review changes * expose only postinstall.js script * Replace _openspec "$@" with compdef in zsh-generator.ts to prevent execution during load * Update test/commands/completion.test.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * - Fix dispatcher to use $words instead of $line for subcommand routing - Add __complete endpoint with tab-separated output for safe parsing - Replace brittle awk parsing with __complete in completion helpers - Add uninstall confirmation prompt with --yes flag to skip - Prefer $ZSH env var for Oh My Zsh detection before dir check - Add fpath verification guidance for OMZ installations - Update cli-completion spec to document generate subcommand * improve shell detection and installation handling - Return structured result from detectShell() with shell and detected name - Detect already-installed completions and skip reinstall - Add update detection with automatic backup of previous version - Add debug logging to silent catch blocks for diagnostics - Quote fpath directories to handle paths with spaces - Verify Oh My Zsh fpath configuration and add to .zshrc if needed - Show helpful error for detected but unsupported shells - Update all tests for new detection API --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Tabish Bidiwale <[email protected]>
1 parent 6d3cfe0 commit 1adf3ce

File tree

23 files changed

+5161
-0
lines changed

23 files changed

+5161
-0
lines changed

openspec/changes/archive/2025-11-06-add-shell-completions/design.md

Lines changed: 525 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Add Shell Completions
2+
3+
## Why
4+
5+
OpenSpec CLI commands lack shell completion, forcing users to remember all commands, subcommands, flags, and change/spec IDs manually. This creates friction during daily use and slows developer workflows. Shell completions are a standard expectation for modern CLI tools and significantly improve user experience through:
6+
- Faster command discovery via tab completion
7+
- Reduced cognitive load by removing memorization requirements
8+
- Fewer typos through validated suggestions
9+
- Professional polish expected of production-grade tools
10+
11+
## What Changes
12+
13+
This change adds shell completion support for the OpenSpec CLI, starting with **Zsh (including Oh My Zsh)** and establishing a scalable architecture for future shells (bash, fish, PowerShell). The implementation provides:
14+
15+
1. **New `openspec completion` command** with Zsh generation and installation/uninstallation capabilities
16+
2. **Native Zsh integration** that respects standard Zsh tab completion behavior (single-TAB menu navigation)
17+
3. **Dynamic completion providers** that discover active changes and specs from the current project
18+
4. **Plugin-based architecture** using TypeScript interfaces for easy extension to additional shells in future proposals
19+
5. **Installation automation** for Oh My Zsh (priority) and standard Zsh configurations
20+
6. **Context-aware suggestions** that only activate within OpenSpec-enabled projects
21+
22+
The architecture emphasizes clean TypeScript patterns, composable generators, separation of concerns between shell-specific logic and shared completion data providers, and integration with native shell completion systems. Other shells (bash, fish, PowerShell) are architecturally documented but not implemented in this proposal—they will be added in follow-up changes.
23+
24+
## Deltas
25+
26+
### Delta: New CLI completion specification
27+
- **Spec:** cli-completion
28+
- **Operation:** ADDED
29+
- **Description:** Defines requirements for the new `openspec completion` command including generation, installation, and shell-specific behaviors for Oh My Zsh, bash, fish, and PowerShell.
Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
# CLI Completion Specification
2+
3+
## Purpose
4+
5+
The `openspec completion` command SHALL provide shell completion functionality for all OpenSpec CLI commands, flags, and dynamic values (change IDs, spec IDs), with support for Zsh (including Oh My Zsh) and a scalable architecture ready for future shells (bash, fish, PowerShell). The completion system SHALL integrate with Zsh's native completion behavior rather than attempting to customize the user experience.
6+
7+
## ADDED Requirements
8+
9+
### Requirement: Native Shell Behavior Integration
10+
11+
The completion system SHALL respect and integrate with Zsh's native completion patterns and user interaction model.
12+
13+
#### Scenario: Zsh native completion
14+
15+
- **WHEN** generating Zsh completion scripts
16+
- **THEN** use Zsh completion system with `_arguments`, `_describe`, and `compadd`
17+
- **AND** completions SHALL trigger on single TAB (standard Zsh behavior)
18+
- **AND** display as an interactive menu that users navigate with TAB/arrow keys
19+
- **AND** support Oh My Zsh's enhanced menu styling automatically
20+
21+
#### Scenario: No custom UX patterns
22+
23+
- **WHEN** implementing Zsh completion
24+
- **THEN** do NOT attempt to customize completion trigger behavior
25+
- **AND** do NOT override Zsh-specific navigation patterns
26+
- **AND** ensure completions feel native to experienced Zsh users
27+
28+
### Requirement: Command Structure
29+
30+
The completion command SHALL follow a subcommand pattern for generating and managing completion scripts.
31+
32+
#### Scenario: Available subcommands
33+
34+
- **WHEN** user executes `openspec completion --help`
35+
- **THEN** display available subcommands:
36+
- `zsh` - Generate Zsh completion script
37+
- `install [shell]` - Install completion for Zsh (auto-detects or requires explicit shell)
38+
- `uninstall [shell]` - Remove completion for Zsh (auto-detects or requires explicit shell)
39+
40+
### Requirement: Shell Detection
41+
42+
The completion system SHALL automatically detect the user's current shell environment.
43+
44+
#### Scenario: Detecting Zsh from environment
45+
46+
- **WHEN** no shell is explicitly specified
47+
- **THEN** read the `$SHELL` environment variable
48+
- **AND** extract the shell name from the path (e.g., `/bin/zsh``zsh`)
49+
- **AND** validate the shell is `zsh`
50+
- **AND** throw an error if the shell is not `zsh`, with message indicating only Zsh is currently supported
51+
52+
#### Scenario: Non-Zsh shell detection
53+
54+
- **WHEN** shell path indicates bash, fish, powershell, or other non-Zsh shell
55+
- **THEN** throw error: "Shell '<name>' is not supported yet. Currently supported: zsh"
56+
57+
### Requirement: Completion Generation
58+
59+
The completion command SHALL generate Zsh completion scripts on demand.
60+
61+
#### Scenario: Generating Zsh completion
62+
63+
- **WHEN** user executes `openspec completion zsh`
64+
- **THEN** output a complete Zsh completion script to stdout
65+
- **AND** include completions for all commands: init, list, show, validate, archive, view, update, change, spec, completion
66+
- **AND** include all command-specific flags and options
67+
- **AND** use Zsh's `_arguments` and `_describe` built-in functions
68+
- **AND** support dynamic completion for change and spec IDs
69+
70+
### Requirement: Dynamic Completions
71+
72+
The completion system SHALL provide context-aware dynamic completions for project-specific values.
73+
74+
#### Scenario: Completing change IDs
75+
76+
- **WHEN** completing arguments for commands that accept change names (show, validate, archive)
77+
- **THEN** discover active changes from `openspec/changes/` directory
78+
- **AND** exclude archived changes in `openspec/changes/archive/`
79+
- **AND** return change IDs as completion suggestions
80+
- **AND** only provide suggestions when inside an OpenSpec-enabled project
81+
82+
#### Scenario: Completing spec IDs
83+
84+
- **WHEN** completing arguments for commands that accept spec names (show, validate)
85+
- **THEN** discover specs from `openspec/specs/` directory
86+
- **AND** return spec IDs as completion suggestions
87+
- **AND** only provide suggestions when inside an OpenSpec-enabled project
88+
89+
#### Scenario: Completion caching
90+
91+
- **WHEN** dynamic completions are requested
92+
- **THEN** cache discovered change and spec IDs for 2 seconds
93+
- **AND** reuse cached values for subsequent requests within cache window
94+
- **AND** automatically refresh cache after expiration
95+
96+
#### Scenario: Project detection
97+
98+
- **WHEN** user requests completions outside an OpenSpec project
99+
- **THEN** skip dynamic change/spec ID completions
100+
- **AND** only suggest static commands and flags
101+
102+
### Requirement: Installation Automation
103+
104+
The completion command SHALL automatically install completion scripts into shell configuration files.
105+
106+
#### Scenario: Installing for Oh My Zsh
107+
108+
- **WHEN** user executes `openspec completion install zsh`
109+
- **THEN** detect if Oh My Zsh is installed by checking for `$ZSH` environment variable or `~/.oh-my-zsh/` directory
110+
- **AND** create custom completions directory at `~/.oh-my-zsh/custom/completions/` if it doesn't exist
111+
- **AND** write completion script to `~/.oh-my-zsh/custom/completions/_openspec`
112+
- **AND** ensure `~/.oh-my-zsh/custom/completions` is in `$fpath` by updating `~/.zshrc` if needed
113+
- **AND** display success message with instruction to run `exec zsh` or restart terminal
114+
115+
#### Scenario: Installing for standard Zsh
116+
117+
- **WHEN** user executes `openspec completion install zsh` and Oh My Zsh is not detected
118+
- **THEN** create completions directory at `~/.zsh/completions/` if it doesn't exist
119+
- **AND** write completion script to `~/.zsh/completions/_openspec`
120+
- **AND** add `fpath=(~/.zsh/completions $fpath)` to `~/.zshrc` if not already present
121+
- **AND** add `autoload -Uz compinit && compinit` to `~/.zshrc` if not already present
122+
- **AND** display success message with instruction to run `exec zsh` or restart terminal
123+
124+
#### Scenario: Auto-detecting Zsh for installation
125+
126+
- **WHEN** user executes `openspec completion install` without specifying a shell
127+
- **THEN** detect current shell using shell detection logic
128+
- **AND** install completion if detected shell is Zsh
129+
- **AND** throw error if detected shell is not Zsh
130+
- **AND** display which shell was detected
131+
132+
#### Scenario: Already installed
133+
134+
- **WHEN** completion is already installed for the target shell
135+
- **THEN** display message indicating completion is already installed
136+
- **AND** offer to reinstall/update by overwriting existing files
137+
- **AND** exit with code 0
138+
139+
### Requirement: Uninstallation
140+
141+
The completion command SHALL remove installed completion scripts and configuration.
142+
143+
#### Scenario: Uninstalling Oh My Zsh completion
144+
145+
- **WHEN** user executes `openspec completion uninstall zsh`
146+
- **THEN** remove `~/.oh-my-zsh/custom/completions/_openspec` if Oh My Zsh is detected
147+
- **AND** remove `~/.zsh/completions/_openspec` if standard Zsh setup is detected
148+
- **AND** optionally remove fpath modifications from `~/.zshrc` (with confirmation)
149+
- **AND** display success message
150+
151+
#### Scenario: Auto-detecting Zsh for uninstallation
152+
153+
- **WHEN** user executes `openspec completion uninstall` without specifying a shell
154+
- **THEN** detect current shell and uninstall completion if shell is Zsh
155+
- **AND** throw error if detected shell is not Zsh
156+
157+
#### Scenario: Not installed
158+
159+
- **WHEN** attempting to uninstall completion that isn't installed
160+
- **THEN** display message indicating completion is not installed
161+
- **AND** exit with code 0
162+
163+
### Requirement: Architecture Patterns
164+
165+
The completion implementation SHALL follow clean architecture principles with TypeScript best practices.
166+
167+
#### Scenario: Shell-specific generators
168+
169+
- **WHEN** implementing completion generators
170+
- **THEN** create `ZshCompletionGenerator` class for Zsh
171+
- **AND** implement a common `CompletionGenerator` interface with methods:
172+
- `generate(): string` - Returns complete shell script
173+
- `getInstallPath(): string` - Returns target installation path
174+
- `getConfigFile(): string` - Returns shell configuration file path
175+
- **AND** design interface to be extensible for future shells (bash, fish, powershell)
176+
177+
#### Scenario: Dynamic completion providers
178+
179+
- **WHEN** implementing dynamic completions
180+
- **THEN** create a `CompletionProvider` class that encapsulates project discovery logic
181+
- **AND** implement methods:
182+
- `getChangeIds(): Promise<string[]>` - Discovers active change IDs
183+
- `getSpecIds(): Promise<string[]>` - Discovers spec IDs
184+
- `isOpenSpecProject(): boolean` - Checks if current directory is OpenSpec-enabled
185+
- **AND** implement caching with 2-second TTL using class properties
186+
187+
#### Scenario: Command registry
188+
189+
- **WHEN** defining completable commands
190+
- **THEN** create a centralized `CommandDefinition` type with properties:
191+
- `name: string` - Command name
192+
- `description: string` - Help text
193+
- `flags: FlagDefinition[]` - Available flags
194+
- `acceptsChangeId: boolean` - Whether command takes change ID argument
195+
- `acceptsSpecId: boolean` - Whether command takes spec ID argument
196+
- `subcommands?: CommandDefinition[]` - Nested subcommands
197+
- **AND** export a `COMMAND_REGISTRY` constant with all command definitions
198+
- **AND** generators consume this registry to ensure consistency
199+
200+
#### Scenario: Type-safe shell detection
201+
202+
- **WHEN** implementing shell detection
203+
- **THEN** define a `SupportedShell` type as literal type: `'zsh'`
204+
- **AND** implement `detectShell()` function that returns 'zsh' or throws error
205+
- **AND** design type to be extensible (e.g., future: `'bash' | 'zsh' | 'fish' | 'powershell'`)
206+
207+
### Requirement: Error Handling
208+
209+
The completion command SHALL provide clear error messages for common failure scenarios.
210+
211+
#### Scenario: Unsupported shell
212+
213+
- **WHEN** user requests completion for unsupported shell (bash, fish, powershell, etc.)
214+
- **THEN** display error message: "Shell '<name>' is not supported yet. Currently supported: zsh"
215+
- **AND** exit with code 1
216+
217+
#### Scenario: Permission errors during installation
218+
219+
- **WHEN** installation fails due to file permission issues
220+
- **THEN** display clear error message indicating permission problem
221+
- **AND** suggest using appropriate permissions or alternative installation method
222+
- **AND** exit with code 1
223+
224+
#### Scenario: Missing shell configuration directory
225+
226+
- **WHEN** expected shell configuration directory doesn't exist
227+
- **THEN** create the directory automatically (with user notification)
228+
- **AND** proceed with installation
229+
230+
#### Scenario: Shell not detected
231+
232+
- **WHEN** `openspec completion install` cannot detect current shell or detects non-Zsh shell
233+
- **THEN** display error: "Could not detect Zsh. Please specify explicitly: openspec completion install zsh"
234+
- **AND** exit with code 1
235+
236+
### Requirement: Output Format
237+
238+
The completion command SHALL provide machine-parseable and human-readable output.
239+
240+
#### Scenario: Script generation output
241+
242+
- **WHEN** generating completion script to stdout
243+
- **THEN** output only the completion script content (no extra messages)
244+
- **AND** allow redirection to files: `openspec completion zsh > /path/to/_openspec`
245+
246+
#### Scenario: Installation success output
247+
248+
- **WHEN** installation completes successfully
249+
- **THEN** display formatted success message with:
250+
- Checkmark indicator
251+
- Installation location
252+
- Next steps (shell reload instructions)
253+
- **AND** use colors when terminal supports it (unless `--no-color` is set)
254+
255+
#### Scenario: Verbose installation output
256+
257+
- **WHEN** user provides `--verbose` flag during installation
258+
- **THEN** display detailed steps:
259+
- Shell detection result
260+
- Target file paths
261+
- Configuration modifications
262+
- File creation confirmations
263+
264+
### Requirement: Testing Support
265+
266+
The completion implementation SHALL be testable with unit and integration tests.
267+
268+
#### Scenario: Mock shell environment
269+
270+
- **WHEN** writing tests for shell detection
271+
- **THEN** allow overriding `$SHELL` environment variable
272+
- **AND** use dependency injection for file system operations
273+
274+
#### Scenario: Generator output verification
275+
276+
- **WHEN** testing completion generators
277+
- **THEN** verify generated scripts contain expected patterns
278+
- **AND** test that command registry is properly consumed
279+
- **AND** ensure dynamic completion placeholders are present
280+
281+
#### Scenario: Installation simulation
282+
283+
- **WHEN** testing installation logic
284+
- **THEN** use temporary test directories instead of actual home directories
285+
- **AND** verify file creation without modifying real shell configurations
286+
- **AND** test path resolution logic independently
287+
288+
## Not in Scope
289+
290+
The following shells are **architecturally documented but not implemented** in this proposal. They will be added in future proposals:
291+
292+
- **Bash completion** - Will use bash-completion framework with `_init_completion`, `compgen`, and `COMPREPLY`
293+
- **Fish completion** - Will use Fish's declarative `complete -c` syntax
294+
- **PowerShell completion** - Will use `Register-ArgumentCompleter` with completion result objects
295+
296+
The plugin-based architecture (CompletionGenerator interface, command registry, dynamic providers) is designed to make adding these shells straightforward in follow-up changes.
297+
298+
## Why
299+
300+
Shell completions are essential for professional CLI tools and significantly improve developer experience by reducing friction, errors, and cognitive load during daily workflows.

0 commit comments

Comments
 (0)