Files
claude-skills/.wiki/concepts/install-cross-platform.md
vitya e871c20272 docs(install): .wiki concept page for install-cross-platform parity
Closes 3/3 acceptance of [install-ps1]:
- (a) install.ps1 existed
- (b) --prune flag shipped in 6cf0e98
- (c) concept page now written

.wiki/concepts/install-cross-platform.md captures:
- why two scripts (PS for native-Win, sh for Linux/Mac)
- parity contract (shared invariants, flag-naming convention)
- --prune design choices and rejected alternatives
- scope boundary (install-side only; dist/.skill prune is separate)

Index + log updated per .wiki/CLAUDE.md schema.

STATUS.md: [install-ps1] 🟢, new  task
[install-ps1-build-prune-followup] filed for the analogous
flag on build.{sh,ps1}.
2026-05-25 13:11:10 +03:00

4.3 KiB

title, type, updated
title type updated
Install Cross-Platform Parity (PS + Bash) concept 2026-05-25

Install Cross-Platform Parity (PS + Bash)

Sibling concept to install-portability.md (POSIX-shell compat). This one is about the paired-script parity contract between scripts/install.ps1 (PowerShell) and scripts/install.sh (bash).

Why two scripts

Windows hosts running CC outside a git-bash terminal have no reliable bash. Native PowerShell call (pwsh ./scripts/install.ps1) is the friction-free path. Linux / macOS users get bash. Both audiences are first-class — claude-skills is multi-machine by design (see project_deployment_goal memory).

Single-script "use bash everywhere" was rejected: forces every Windows user to install git-bash before bootstrap, contradicts "tool-light install path".

Parity contract

Both scripts MUST:

  • Read sources from <repo>/skills/<name>/.
  • Install to $CLAUDE_SKILLS_DIR if set, else ~/.claude/skills/.
  • Accept a name-list (positional in bash, -Names in PS); no args = all.
  • Skip with a warning when skills/<name>/ is missing or has no SKILL.md.
  • Idempotent: rm -rf (or Remove-Item -Recurse -Force) the destination, then copy fresh.
  • Print one installed: <name> -> <path> line per successfully installed skill.

Flag naming follows the host shell's convention — POSIX --prune in bash, PascalCase -Prune switch in PowerShell. Behaviour identical.

The --prune / -Prune flag

Added 2026-05-25 (commit 6cf0e98). Motivating case: after retiring using-synology-ops the installed dir ~/.claude/skills/using-synology-ops/ lingered until manual rm — the install scripts had no notion of stale-cleanup.

Behaviour: after the install loop, walk $target/* and remove any dir whose name is not in skills/*.

Design choices and their rejected alternatives:

  • Combined flag, not standalone mode. Single invocation does both. Alternative (install --prune-only) was rejected — adds a mode that nobody asked for; users wanting "just cleanup" can pass an empty name list (install.sh --prune with no positional args still walks the prune step at the end, no-op'ing the install loop because all source skills resolve to no-op overwrites of fresh installs).

  • Global scan, ignores name filter. Even when called as install.sh foo --prune, the prune step scans the full target against the full source. Rationale: stale-cleanup is a global concern. A user who explicitly opts into prune wants the cleanup to be useful — a names-filtered prune ("only prune dirs that match the name list AND are missing from source") rarely matches anyone's mental model.

  • Print-and-delete, no confirmation prompt. Each removal prints pruning: <name> (not in skills/) -> <path>. Confirmation prompts would block automation (CI, batch reinstalls). Visibility comes from the printed line; users wanting a dry-run pass -WhatIf in PowerShell (the cmdlet already supports it) or pipe to echo in bash (trivial to grep ^pruning: before running for real).

  • Default off. Must be passed explicitly. Idempotent re-installs (the common case) don't suddenly delete anything.

What --prune does NOT do

  • It does not remove dist/<name>.skill artefacts. That's a build concern, not install. The matching --prune flag on build.sh / build.ps1 is a separate task ([install-ps1] acceptance was scoped to install scripts; dist/ is a build artefact directory).
  • It does not touch plugin-installed skills under ~/.claude/plugins/<plugin>/skills/<name>/. Those are managed by the plugin system, not this repo.
  • It does not warn if the about-to-be-deleted dir contains user-edited content. The contract is that ~/.claude/skills/<name>/ is a managed copy of skills/<name>/ — anything else is user-error.

Test evidence

Both scripts smoke-tested 2026-05-25 on disposable target dirs (env-overridden CLAUDE_SKILLS_DIR). Pre-populated with 2 fake stale dirs, ran full install + prune, verified: stale dirs removed, all real skills installed, retired using-synology-ops absent. No automated test fixture in the repo — install scripts are wrapper-style, smoke-test evidence in the 6cf0e98 commit body suffices under the [skip-tdd: wrapper] carve-out.

[archive-roundtrip-test] (still on the board) is a candidate place to add a real fixture once it lands.