Skip to content

feat: Add shell completion installation and setup commands - #630

Merged
razor-x merged 2 commits into
mainfrom
claude/seam-completion-install-jisy37
Aug 18, 2026
Merged

feat: Add shell completion installation and setup commands#630
razor-x merged 2 commits into
mainfrom
claude/seam-completion-install-jisy37

Conversation

@razor-x

@razor-x razor-x commented Aug 18, 2026

Copy link
Copy Markdown
Member

Summary

This PR adds the ability to install and configure shell completions for bash, fish, and zsh directly from the CLI, rather than requiring manual installation or system package management.

Key Changes

  • New completion installation module (src/lib/completion/install.ts):

    • detectShell(): Detects the current shell from the SHELL environment variable
    • resolveCompletionTarget(): Determines where completions should be installed based on shell type and environment variables (e.g., ZDOTDIR for zsh, XDG_CONFIG_HOME for fish)
    • installCompletion(): Handles the actual installation, with idempotent behavior for config files (appends only once) and overwrites for completion files owned by the CLI
    • Proper handling of shell-specific config locations and edge cases (e.g., bash on macOS vs Linux)
  • New completion setup rendering (src/lib/render/completion/render-loader.ts):

    • renderCompletionSetup(): Generates the snippet users add to their shell config
    • renderCompletionStub(): Generates the loader for system packages (moved from index.ts)
    • completionSetupMarker: Constant used to detect already-installed snippets
    • Separate setup snippets for each shell with lazy-loading behavior
  • Enhanced completion command (src/lib/commands/local/completion.ts):

    • New --install flag: Automatically installs completions into the detected shell's config
    • New --manual flag: Prints the setup snippet for manual installation
    • readCompletionAction(): Parses which action to perform (print, install, manual, or loader)
    • resolveCompletionShell(): Determines the target shell from arguments or environment
    • installCompletionForShell(): Orchestrates the installation and reports results
    • printCompletionSetup(): Prints the snippet with instructions
  • Refactored completion rendering (src/lib/render/completion/):

    • Extracted shell type definitions to new shell.ts module
    • Moved loader and setup rendering to dedicated render-loader.ts
    • Updated index.ts to re-export from new modules
  • Comprehensive test coverage (test/completion/install.test.ts):

    • Tests for shell detection with various SHELL values
    • Tests for target resolution with environment variables
    • Tests for idempotent installation behavior
    • Tests for shell-specific notes (e.g., zsh compinit detection)
  • CLI integration (src/bin/cli.ts):

    • Routes completion command to new action handlers
    • Validates arguments against the detected shell's command definition
  • Documentation updates (README.md):

    • Added shell completion section with installation instructions
    • Documented --install, --manual, and --loader flags
    • Explained the lazy-loading behavior and schema freshness benefits

Notable Implementation Details

  • Idempotent installation: Config files are checked for the completionSetupMarker before appending, preventing duplicate snippets
  • Lazy loading: The setup snippet runs seam completion on first use, ensuring completions always match the current CLI schema
  • Shell-specific handling:
    • Fish uses a dedicated completion file (loaded on demand)
    • Zsh respects ZDOTDIR and can initialize compinit if needed
    • Bash prefers .bashrc on Linux but falls back to .bash_profile on macOS
  • Safe evaluation: All loaders validate the first line of the completion script before evaluating it, preventing execution of error messages

https://claude.ai/code/session_01NS3fVoYWNDEQWAhrp3PnPj

@razor-x
razor-x force-pushed the claude/seam-completion-install-jisy37 branch 4 times, most recently from 14646c8 to d3ae8aa Compare August 18, 2026 05:08
Installing completions meant knowing where each shell keeps them. Do that
instead.

'seam completion --install' works out which shell it was run from, or takes
one as an argument, and adds a line loading the completion loader to that
shell's config, or writes the loader itself for fish, which loads a
completion file on demand. It is safe to repeat, since a config that
already has the line is left alone. Installing by hand is the same line:

  echo 'eval "$(seam completion --loader zsh 2> /dev/null)"' >> ~/.zshrc

The shell comes from the process that ran the command rather than from
SHELL, which names the login shell and so answers bash for every shell
started from one. The loader is asked for quietly because a shell config
runs it on every new shell: an older seam that cannot print a loader, or
no seam at all, then completes nothing rather than reporting itself over
and over at a prompt.

The loader keeps its job of being what a system package installs, and now
also survives being evaluated by a shell config. It could not be before:
the zsh loader declared a local outside a function, which is an error
anywhere but the completion function it was assumed to be, and registered
nothing when it was not one. Bash gains the same, registering its own
completion so that it needs neither the bash-completion package nor a
config entry, and completing on demand wherever bash is new enough to.

The zsh loader never runs compinit: that would override the dumpfile and
options the shell owner chose. It registers once the completion system is
up, and --install says so when nothing in the config turns it on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NS3fVoYWNDEQWAhrp3PnPj
@razor-x
razor-x force-pushed the claude/seam-completion-install-jisy37 branch from d3ae8aa to c1d209c Compare August 18, 2026 05:26
Comment thread README.md Outdated
@razor-x razor-x changed the title Add shell completion installation and setup commands feat: Add shell completion installation and setup commands Aug 18, 2026
@razor-x
razor-x marked this pull request as ready for review August 18, 2026 05:29
@razor-x
razor-x merged commit 467faf5 into main Aug 18, 2026
14 checks passed
@razor-x
razor-x deleted the claude/seam-completion-install-jisy37 branch August 18, 2026 05:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants