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}.
This commit is contained in:
2026-05-25 13:09:47 +03:00
parent 7ca5a5ad3c
commit e871c20272
4 changed files with 72 additions and 5 deletions

View File

@@ -0,0 +1,56 @@
---
title: Install Cross-Platform Parity (PS + Bash)
type: concept
updated: 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.