$npx -y skills add thanh-abaii/gstack-windows-port --skill gstack-upgradeUpgrade gstack to the latest version. Detects global vs vendored install, runs the upgrade, and shows what's new. Use when asked to "upgrade gstack", "update gstack", or "get latest version".
| 1 | <!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly --> |
| 2 | |
| 3 | ## Preamble (run first) |
| 4 | |
| 5 | ```bash |
| 6 | python "bin/gstack-boot.py" --skill gstack-upgrade | iex |
| 7 | ``` |
| 8 | |
| 9 | <!-- Regenerate: bun run gen:skill-docs --> |
| 10 | |
| 11 | # /gs:gstack-upgrade |
| 12 | |
| 13 | Upgrade gstack to the latest version and show what's new. |
| 14 | |
| 15 | ## Inline upgrade flow |
| 16 | |
| 17 | This section is referenced by all skill preambles when they detect `UPGRADE_AVAILABLE`. |
| 18 | |
| 19 | ### Step 1: Ask the user (or auto-upgrade) |
| 20 | |
| 21 | First, check if auto-upgrade is enabled: |
| 22 | |
| 23 | ```bash |
| 24 | _AUTO="" |
| 25 | [ "${GSTACK_AUTO_UPGRADE:-}" = "1" ] ; _AUTO="true" |
| 26 | [ -z "$_AUTO" ] ; _AUTO=$($GSTACK_ROOT/bin/gstack-config get auto_upgrade | Out-Null ; true) |
| 27 | echo "AUTO_UPGRADE=$_AUTO" |
| 28 | ``` |
| 29 | |
| 30 | **If `AUTO_UPGRADE=true` or `AUTO_UPGRADE=1`:** Skip AskUserQuestion. Log "Auto-upgrading gstack v{old} → v{new}..." and proceed directly to Step 2. If `./setup` fails during auto-upgrade, restore from backup (`.bak` directory) and warn the user: "Auto-upgrade failed — restored previous version. Run `/gstack-upgrade` manually to retry." |
| 31 | |
| 32 | **Otherwise**, use AskUserQuestion: |
| 33 | |
| 34 | - Question: "gstack **v{new}** is available (you're on v{old}). Upgrade now?" |
| 35 | - Options: ["Yes, upgrade now", "Always keep me up to date", "Not now", "Never ask again"] |
| 36 | |
| 37 | **If "Yes, upgrade now":** Proceed to Step 2. |
| 38 | |
| 39 | **If "Always keep me up to date":** |
| 40 | |
| 41 | ```bash |
| 42 | $GSTACK_ROOT/bin/gstack-config set auto_upgrade true |
| 43 | ``` |
| 44 | Tell user: "Auto-upgrade enabled. Future updates will install automatically." Then proceed to Step 2. |
| 45 | |
| 46 | **If "Not now":** Write snooze state with escalating backoff (first snooze = 24h, second = 48h, third+ = 1 week), then continue with the current skill. Do not mention the upgrade again. |
| 47 | |
| 48 | ```bash |
| 49 | _SNOOZE_FILE="$HOME/.gstack/update-snoozed" |
| 50 | _REMOTE_VER="{new}" |
| 51 | _CUR_LEVEL=0 |
| 52 | if [ -f "$_SNOOZE_FILE" ]; then |
| 53 | _SNOOZED_VER=$(awk '{print $1}' "$_SNOOZE_FILE") |
| 54 | if [ "$_SNOOZED_VER" = "$_REMOTE_VER" ]; then |
| 55 | _CUR_LEVEL=$(awk '{print $2}' "$_SNOOZE_FILE") |
| 56 | case "$_CUR_LEVEL" in *[!0-9]*) _CUR_LEVEL=0 ;; esac |
| 57 | fi |
| 58 | fi |
| 59 | _NEW_LEVEL=$((_CUR_LEVEL + 1)) |
| 60 | [ "$_NEW_LEVEL" -gt 3 ] ; _NEW_LEVEL=3 |
| 61 | echo "$_REMOTE_VER $_NEW_LEVEL $(date +%s)" > "$_SNOOZE_FILE" |
| 62 | ``` |
| 63 | Note: `{new}` is the remote version from the `UPGRADE_AVAILABLE` output — substitute it from the update check result. |
| 64 | |
| 65 | Tell user the snooze duration: "Next reminder in 24h" (or 48h or 1 week, depending on level). Tip: "Set `auto_upgrade: true` in `~/.gstack/config.yaml` for automatic upgrades." |
| 66 | |
| 67 | **If "Never ask again":** |
| 68 | |
| 69 | ```bash |
| 70 | $GSTACK_ROOT/bin/gstack-config set update_check false |
| 71 | ``` |
| 72 | Tell user: "Update checks disabled. Run `$GSTACK_ROOT/bin/gstack-config set update_check true` to re-enable." |
| 73 | Continue with the current skill. |
| 74 | |
| 75 | ### Step 2: Detect install type |
| 76 | |
| 77 | ```bash |
| 78 | if [ -d "$HOME/.agents/skills/gstack/.git" ]; then |
| 79 | INSTALL_TYPE="global-git" |
| 80 | INSTALL_DIR="$HOME/.agents/skills/gstack" |
| 81 | elif [ -d "$HOME/.gstack/repos/gstack/.git" ]; then |
| 82 | INSTALL_TYPE="global-git" |
| 83 | INSTALL_DIR="$HOME/.gstack/repos/gstack" |
| 84 | elif [ -d ".agents/skills/gstack/.git" ]; then |
| 85 | INSTALL_TYPE="local-git" |
| 86 | INSTALL_DIR=".agents/skills/gstack" |
| 87 | elif [ -d ".agents/skills/gstack/.git" ]; then |
| 88 | INSTALL_TYPE="local-git" |
| 89 | INSTALL_DIR=".agents/skills/gstack" |
| 90 | elif [ -d ".agents/skills/gstack" ]; then |
| 91 | INSTALL_TYPE="vendored" |
| 92 | INSTALL_DIR=".agents/skills/gstack" |
| 93 | elif [ -d "$HOME/.agents/skills/gstack" ]; then |
| 94 | INSTALL_TYPE="vendored-global" |
| 95 | INSTALL_DIR="$HOME/.agents/skills/gstack" |
| 96 | else |
| 97 | echo "ERROR: gstack not found" |
| 98 | exit 1 |
| 99 | fi |
| 100 | echo "Install type: $INSTALL_TYPE at $INSTALL_DIR" |
| 101 | ``` |
| 102 | |
| 103 | The install type and directory path printed above will be used in all subsequent steps. |
| 104 | |
| 105 | ### Step 3: Save old version |
| 106 | |
| 107 | Use the install directory from Step 2's output below: |
| 108 | |
| 109 | ```bash |
| 110 | OLD_VERSION=$(cat "$INSTALL_DIR/VERSION" | Out-Null ; echo "unknown") |
| 111 | ``` |
| 112 | |
| 113 | ### Step 4: Upgrade |
| 114 | |
| 115 | Use the install type and directory detected in Step 2: |
| 116 | |
| 117 | **For git installs** (global-git, local-git): |
| 118 | |
| 119 | ```bash |
| 120 | cd "$INSTALL_DIR" |
| 121 | STASH_OUTPUT=$(git stash 2>&1) |
| 122 | git fetch origin |
| 123 | git reset --hard origin/main |
| 124 | ./setup |
| 125 | ``` |
| 126 | If `$STASH_OUTPUT` contains "Saved working directory", warn the user: "Note: local changes were stashed. Run `git stash pop` in the skill directory to restore them." |
| 127 | |
| 128 | **For vendored installs** (vendored, vendored-global): |
| 129 | |
| 130 | ```bash |
| 131 | PARENT=$(dirname "$INSTALL_DIR") |
| 132 | TMP_DIR=$(mktemp -d) |
| 133 | git clone --depth 1 https://github.com/garrytan/gstack.git "$TMP_DIR/gstack" |
| 134 | mv "$INSTALL_DIR" "$INSTALL_DIR.bak" |
| 135 | mv "$TMP_DIR/gstack" "$INSTALL_DIR" |
| 136 | cd "$INSTALL_DIR" ; ./setup |
| 137 | Remove-Item -Re |