Commit Graph

2 Commits

Author SHA1 Message Date
jkrperson 1a9970b354 feat(installer): project-only (vendored) install mode
Adds a third install scope: `gstack install --local` vendors gstack into
<cwd>/.claude/skills/gstack/ instead of ~/.claude/skills/gstack/. Surfaces
./setup --local, which upstream deprecated in favor of team mode but still
supports. Guarded with an explicit deprecation notice in both the CLI
output and the interactive wizard confirmation step.

Why expose a deprecated mode:
- Some users genuinely want vendored installs (offline machines, strict
  "one project = one dir" policies, air-gapped CI, forked gstack per repo)
- ./setup already supports it, so the CLI would be lying by omission
- The wizard makes the deprecation cost visible before commit

Changes:
- paths.ts: resolveProjectInstallPaths(dir), findLocalInstall(startDir)
  walking up to find <dir>/.claude/skills/gstack, and a resolveActiveInstall
  helper that returns {paths, mode: "global" | "project-local" | "none"}
  so status/doctor/list/upgrade all detect both install kinds
- install.ts: accepts local + projectDir, routes to project paths, passes
  --local through to ./setup, restricts hosts to claude (matching setup
  behavior), prints deprecation warning
- uninstall.ts: new `gstack uninstall --local` removes the project-local
  install (searches cwd upward), distinct from `--project` which removes
  team-mode config
- wizard.ts: fourth top-level option "Install inside this project only
  (vendored)" with a confirm-before-commit step spelling out the tradeoff
- cli.ts: --local flag on install and uninstall, help text updated
- status: shows "Mode: project-local (vendored)" when applicable, yellow

Tests: +8 (85 total, still green)
- resolveProjectInstallPaths roots correctly
- findLocalInstall at cwd + walks up to parent
- status shows project-local mode when only vendored install exists
- list discovers skills in vendored install
- uninstall --local removes the vendored dir
- uninstall --local exits 1 with clear message when no install present
2026-04-25 03:00:59 +08:00
jkrperson 714e968d69 feat(installer): npx @garrytan/gstack — interactive installer CLI
Adds installer/ — a TypeScript CLI that wraps the existing ./setup bash
script behind a zero-friction `npx` entry point. Replaces the paste-prompt
install flow with an interactive wizard while preserving ./setup as the
source of truth for host registration and symlinks.

Commands:
  install | init | uninstall (--project) | upgrade | doctor
  status | list | enable <skill> | disable <skill>

No-args launches a @clack/prompts wizard that auto-detects git repos +
installed hosts (claude, codex, factory, opencode, kiro), collects
multi-select host + prefix + CLAUDE.md choices, and routes to install or
team-mode init.

The CLI:
- clones garrytan/gstack into ~/.claude/skills/gstack
- shells out to ./setup once per selected host (or --host auto)
- for init, runs ./setup --team + bin/gstack-team-init <required|optional>,
  stages .claude/ + CLAUDE.md
- inserts/updates a fenced <!-- gstack:begin --> block in CLAUDE.md listing
  every discovered skill
- uninstall walks ~/.claude, ~/.codex, ~/.factory, ~/.config/opencode,
  ~/.kiro skills dirs and removes symlinks/dirs pointing into the gstack
  install (canonicalized with fs.realpathSync to handle macOS /var vs
  /private/var), then removes the CLAUDE.md block and scrubs gstack
  PreToolUse hooks from project .claude/settings.json
- preserves ~/.gstack/ session state across uninstalls

Testing:
- 77 tests, bun:test runner, 3s runtime
- Unit: claude-md (11), skills (12), project-config (11), cleanup (12 + a
  /var realpath regression test), paths (9)
- Integration: spawns dist/cli.js against fake HOME fixtures — verifies
  exit codes, enable/disable round-trip + name normalization, uninstall
  scrubs settings.json preserving non-gstack hooks and top-level keys,
  EPIPE handling under `gstack list | head`, wizard intro without TTY

End-to-end dry-run completed via `npm link` and `npm pack` against a real
clone + real build (clone -> browse binary -> Playwright Chromium -> 40
skills linked -> CLAUDE.md written -> doctor green -> uninstall leaves 0
zombies).

Live demo published under @jkresabal/gstack for testing:
  npx @jkresabal/gstack

Upstream publish (after this PR): cd installer && npm publish --access public

Philosophy: thin wrapper. ~2.3K LOC, 16KB packed, two runtime deps
(@clack/prompts + picocolors), Node 18+. No logic duplicated from ./setup.
If ./setup learns a new flag, the CLI surfaces it with one line.
2026-04-25 02:37:27 +08:00