Files
gstack/docs/uninstall.md
T
Garry Tanandcapy-ai[bot] 490bbd5202 Stop gstack-uninstall deleting a repo's committed .gstack files and unsaved worktrees (GST-2197) (#4241)
* Stop gstack-uninstall deleting a repo's committed .gstack files and unsaved worktrees (GST-2197)

--keep-state now keeps the repo's .gstack/ and .gstack-worktrees/. A plain
uninstall keeps git-tracked .gstack files, removes only ignored state, and
stops before removing anything when a worktree has uncommitted changes
unless --force-worktrees is given.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Keep moved, config-hidden and committed worktree work from gstack-uninstall (GST-2197)

The dirty-worktree guard now checks every checkout on disk under .gstack-worktrees/, pins git status flags so config cannot hide new files, refuses a checkout whose commits no branch or tag holds, and keeps .gstack/ when git cannot list its tracked files.

Review-Finding: p1/red-team#2 reader=red-team
Review-Finding: p1/red-team#3 reader=red-team
Review-Finding: p1/specialist-batched#1 reader=security
Review-Finding: p1/red-team#4 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Make gstack-uninstall list worktree checkouts safely and never run their config (GST-2197)

Checkouts are listed NUL-separated and through a symlinked .gstack-worktrees, only worktrees this repository registered are opened with git, and those git calls turn off fsmonitor, hooks and optional index writes.

Review-Finding: v1/adversarial-native#1 reader=adversarial-native
Review-Finding: v1/adversarial-native#5 reader=adversarial-native
Review-Finding: v1/adversarial-native#2 reader=adversarial-native
Review-Loop-Grant: a-f3b2ff8e662e
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Check a .gstack-worktrees that is itself a git repo before gstack-uninstall deletes it (GST-2197)

Review-Finding: fc1/fix-check#1 reader=fix-check
Review-Loop-Grant: a-3b80e7929588
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Document what gstack-uninstall keeps and refuses, and the new --force-worktrees flag (GST-2197)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Stop gstack-uninstall dropping the registration of worktrees it did not delete (GST-2197)

Uninstall ran a repo-wide git worktree prune, which unregistered every worktree whose folder was missing at that moment, including ones outside .gstack-worktrees on an unmounted drive, and left their detached commits unreachable. It now unregisters only the gstack checkouts it just removed.

Review-Finding: p1/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Say that gstack-uninstall does not yet check worktrees nested inside another checkout (GST-2197)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Stop gstack-uninstall deleting checkouts through a .gstack-worktrees symlink that points outside the repo (GST-2197)

Review-Finding: p1/red-team#1 reader=red-team
Review-Finding: p1/red-team#2 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Make gstack-uninstall remove only the link when .gstack-worktrees is a symlink, as before (GST-2197)

Review-Finding: p2/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Drop release-note wording from the gstack-uninstall docs (GST-2197)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
2026-11-09 23:42:47 +00:00

4.6 KiB

Uninstall

Option 1: Run the uninstall script

If gstack is installed on your machine:

~/.claude/skills/gstack/bin/gstack-uninstall

This handles skills, symlinks, harness registrations (the files gstack-harness wrote into OpenClaw, Hermes, a Dot or another harness, from their ledgers, plus the opt-in start hook, which it turns off through the harness's own CLI), global state (~/.gstack/), project-local state, browse daemons, and temp files. Use --keep-state to preserve config and analytics; it also keeps the repo's .gstack/ and .gstack-worktrees/. Use --force to skip confirmation.

A plain uninstall keeps the git-tracked files under .gstack/ (such as ship policy) and removes only the ones git ignores. It stops with exit 2, before removing anything, when a checkout under .gstack-worktrees/ has uncommitted changes, has commits no branch or tag holds, or is not a worktree this repo registered. Pass --force-worktrees to delete those checkouts anyway. When .gstack-worktrees is a symlink, uninstall removes only the link and never follows it, so the folder it points at and the worktrees there are kept. It checks only the top-level checkouts: a worktree created inside another checkout under .gstack-worktrees/ is not checked and is deleted with its parent, so commit or stash its work before you uninstall.

Option 2: Manual removal (no local repo)

If you don't have the repo cloned (e.g. you installed via a Claude Code paste and later deleted the clone):

# 1. Stop browse daemons
pkill -f "gstack.*browse" 2>/dev/null || true

# 2. Remove per-skill directories whose SKILL.md points into gstack/
#    (rm -rf, not rmdir — installed dirs also contain runtime-asset links)
find ~/.claude/skills -mindepth 1 -maxdepth 1 -type d ! -name gstack 2>/dev/null |
while IFS= read -r dir; do
  link="$dir/SKILL.md"
  [ -L "$link" ] || continue
  target=$(readlink "$link" 2>/dev/null) || continue
  case "$target" in
    gstack/*|*/gstack/*)
      rm -rf "$dir"
      ;;
  esac
done
# Directories gstack created carry a .gstack-owned marker (the only signal on
# Windows, where installs are file copies with no symlink to read)
for marker in ~/.claude/skills/*/.gstack-owned; do
  [ -f "$marker" ] && rm -rf "$(dirname "$marker")"
done
# Alias skills install as copies (no symlink to detect) — remove by name
rm -rf ~/.claude/skills/_gstack-command ~/.claude/skills/connect-chrome 2>/dev/null

# 3. Remove gstack
rm -rf ~/.claude/skills/gstack

# 4. Remove global state
rm -rf ~/.gstack

# 5. Remove integrations (skip any you never installed)
rm -rf "${CODEX_HOME:-$HOME/.codex}/skills/gstack"* 2>/dev/null
rm -rf ~/.factory/skills/gstack* 2>/dev/null
rm -rf ~/.kiro/skills/gstack* 2>/dev/null
rm -rf "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/skills/gstack"* "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/skills/.gstack-skills" 2>/dev/null
rm -rf "${HERMES_HOME:-$HOME/.hermes}/skills/gstack" 2>/dev/null
rm -rf ~/.cursor/skills/gstack* 2>/dev/null
rm -rf ~/.config/opencode/skills/gstack* 2>/dev/null
rm -rf ~/.gemini/antigravity-cli/skills/gstack* 2>/dev/null
rm -rf ~/.gemini/skills/gstack* 2>/dev/null

# 6. Remove temp files
rm -f /tmp/gstack-* 2>/dev/null

# 7. Per-project cleanup (run from each project root)
rm -rf .gstack .gstack-worktrees .claude/skills/gstack 2>/dev/null
rm -rf .agents/skills/gstack* .factory/skills/gstack* 2>/dev/null

Manual removal leaves gstack's hook entries behind in ~/.claude/settings.json (the uninstall script removes all of them for you, including entries whose _gstack_source tag was stripped). Edit that file and delete every hook whose command path points into .claude/skills/gstack/: the SessionStart auto-update hook, the AskUserQuestion PreToolUse/PostToolUse hooks, and the Stop hooks (session timeline, plus verify-gate if you opted in). Left in place, they error on every matching event once the install directory is gone.

If you turned on the OpenClaw or Hermes start hook, manual removal also leaves its gstack-start plugin turned on. Turn it off with openclaw config unset plugins.entries.gstack-start or hermes plugins disable gstack-start, then delete ${OPENCLAW_STATE_DIR:-~/.openclaw}/extensions/gstack-start or ${HERMES_HOME:-~/.hermes}/plugins/gstack-start.

Clean up CLAUDE.md

The uninstall script does not edit CLAUDE.md. In each project where gstack was added, remove the ## gstack and ## Skill routing sections.

Playwright

~/Library/Caches/ms-playwright/ (macOS) is left in place because other tools may share it. Remove it if nothing else needs it.

Aside

gstack never installed Aside, so it never uninstalls it. Keep it or remove it like any other app.