Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Pipeline Design 1

Seth Ford edited this page Feb 8, 2026 · 2 revisions

Now I have everything I need. Let me produce the ADR. I notice an important conflict between the original plan and the existing design document — the plan proposes inlining the completion logic, while the design document (Pipeline-Design-1.md) recommends delegating to install-completions.sh. There's also a critical .npmignore issue. Let me write the ADR.

Design: Add shell completion installation to shipwright init

Context

Shipwright has shell completions for bash, zsh, and fish in completions/ and a standalone installer at scripts/install-completions.sh (64 lines). However, the primary onboarding command shipwright init does not install completions. Users must discover and run the standalone script separately.

Current state:

  • completions/_shipwright (zsh), completions/shipwright.bash, completions/shipwright.fish — full subcommand/flag coverage
  • scripts/install-completions.sh — detects $SHELL, copies to per-user dirs, installs for all three aliases (shipwright, sw, cct), warns about fpath
  • scripts/cct (CLI router, line 160-243) — no completions case in main()
  • scripts/cct-init.sh (439 lines) — installs tmux, overlay, templates, settings, hooks, CLAUDE.md, deploy — no completions
  • install.sh line 690 references shipwright completions install but the command doesn't exist
  • .npmignore line 8 excludes scripts/install-completions.sh from npm packages, but the completions/ directory itself is not excluded (it ships)

Constraints:

  • Bash 3.2 compatibility — no declare -A, no readarray, no ${var,,}/${var^^}
  • set -euo pipefail in all scripts
  • Output via info(), success(), warn(), error() helpers
  • cct-init.sh is designed as non-interactive ("one command, no prompts")

Decision

Delegate to install-completions.sh from cct-init.sh rather than inlining the shell-detection logic. Also wire up shipwright completions install as a standalone CLI subcommand.

Approach — three changes:

  1. scripts/cct-init.sh — Insert a # ─── Shell Completions section between the CLAUDE.md per-repo block (line 275) and the tmux reload (line 277). Guard with [[ -x "$SCRIPT_DIR/install-completions.sh" ]]. Call with || true so init never fails on completion errors.

  2. scripts/cct — Add a completions) case in main() that execs $SCRIPT_DIR/install-completions.sh "$@". Add completions to show_help().

  3. install.sh — Add install-completions.sh to the subcommand scripts copied to $BIN_DIR (line 384 list), and copy the completions/ source directory to $HOME/.shipwright/completions/ so the script works when invoked from ~/.local/bin/.

Error handling:

  • cct-init.sh catches failures with || true — completions are nice-to-have, not blocking
  • Standalone shipwright completions install surfaces errors directly
  • If completions/ source directory is missing (e.g., npm install where it wasn't packaged), install-completions.sh fails on its cd at line 8 — caught by || true in init, shown as error in standalone

Idempotency: install-completions.sh uses cp unconditionally (quick overwrite). The plan's cmp -s approach would add value for messaging ("already installed" vs "installed"), but adds complexity. Recommend keeping the simple cp — completions are tiny files and overwriting is harmless. The zsh fpath check already uses grep -q to avoid duplicate .zshrc entries.

Path resolution risk: When install-completions.sh is copied to ~/.local/bin/, its SCRIPT_DIR/../completions resolves to ~/.local/completions which doesn't exist. Fix by also copying completions/ to ~/.shipwright/completions/ in install.sh, and adding a fallback in install-completions.sh:

COMPLETIONS_DIR="$(cd "$SCRIPT_DIR/../completions" 2>/dev/null && pwd)" \
 || COMPLETIONS_DIR="$HOME/.shipwright/completions"

Alternatives Considered

  1. Inline completion logic into cct-init.sh (the plan's approach) — Pros: self-contained, no external script dependency, can add cmp -s idempotency naturally / Cons: duplicates 64 lines of shell-detection logic already in install-completions.sh, creates two copies to maintain, doesn't give users a standalone completions command. The plan proposes single-file-only changes but this leaves the existing install-completions.sh orphaned and divergent.

  2. Only add completions subcommand, skip init integration — Pros: minimal change (router only) / Cons: new users still miss completions during onboarding, which defeats the purpose.

  3. Remove install-completions.sh and only inline — Pros: single source of truth / Cons: breaks install.sh's reference at line 690, breaks install-remote.sh which calls it at line 125-127, breaks Homebrew formula expectations. Too many consumers.

Implementation Plan

  • Files to create: None
  • Files to modify:
    • scripts/cct-init.sh — Add ~8-line Shell Completions section at line 276 (after CLAUDE.md per-repo, before tmux reload)
    • scripts/cct — Add completions) case in main() (~2 lines at line 227). Add entry in show_help() (~1 line at line 87)
    • install.sh — Add install-completions.sh to the script install loop (line 384). Add completions/ directory copy to ~/.shipwright/completions/ (~4 lines after line 451)
    • scripts/install-completions.sh — Add fallback path resolution for COMPLETIONS_DIR (line 8, ~2 line change) so it works from ~/.local/bin/
  • Dependencies: None new
  • Risk areas:
    • .npmignore excludes install-completions.sh (line 8) — npm users won't have the standalone installer. The completions/ directory is shipped, so init could fallback to inline logic for npm installs, but the simplest fix is to remove line 8 from .npmignore. This should be a conscious decision.
    • install-completions.sh path resolution when run from ~/.local/bin/ — mitigated by the COMPLETIONS_DIR fallback and copying completions to ~/.shipwright/completions/
    • Homebrew installs bypass both init and install.sh — Homebrew formula already handles completions at lines 54-58 via bash_completion.install, zsh_completion.install, fish_completion.install. No change needed there.

Validation Criteria

  • shipwright init installs completions for the current shell without prompting, and shows success/warn output
  • shipwright init succeeds when completions/ directory is missing (graceful warn + skip)
  • shipwright init succeeds when install-completions.sh is missing (graceful warn + skip)
  • shipwright completions install works as a standalone command
  • shipwright help lists completions in the command list
  • Running shipwright init twice doesn't produce errors or duplicate .zshrc entries
  • After init, shipwright <TAB> shows subcommands in the user's shell
  • install.sh copies install-completions.sh and completions/ to appropriate locations
  • install-completions.sh works correctly when invoked from ~/.local/bin/ (fallback path)
  • All scripts remain Bash 3.2 compatible
  • npm test passes with no regressions
  • Decide whether to remove install-completions.sh from .npmignore (line 8) — if kept, npm users only get completions via init with inline fallback; if removed, standalone command also works for npm installs

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /