feat: add --update flag to refresh instructions without full setup

curl ... | bash -s -- --update pulls the latest .ai/ files and exits
without scanning projects or touching docs templates.

Bootstrap captures the pre-pull commit hash and forwards it to local
mode; local mode compares with HEAD and either reports "already up to
date" or prints new commit messages with git log --oneline.

FR-1.5 added to apply-requirements.md. README and apply.md updated.
This commit is contained in:
moilanik 2026-03-04 10:00:11 +02:00
parent a85c7dc0fb
commit 93b859f508
4 changed files with 42 additions and 10 deletions

View File

@ -20,7 +20,11 @@ Good instructions are what make that possible — they allow AI to produce outpu
Run this from your dev root — the folder where all your projects live: Run this from your dev root — the folder where all your projects live:
```bash ```bash
# Full setup: clone/pull + scan all projects + create/refresh docs templates
curl -fsSL https://gitea.nikos-dev.keskikuja.site/niko/ai-superpower/raw/branch/main/apply.sh | bash curl -fsSL https://gitea.nikos-dev.keskikuja.site/niko/ai-superpower/raw/branch/main/apply.sh | bash
# Update instructions only: pull latest .ai/ files, skip all project setup
curl -fsSL https://gitea.nikos-dev.keskikuja.site/niko/ai-superpower/raw/branch/main/apply.sh | bash -s -- --update
``` ```
This script **must be run via `curl | bash`** from your dev root. Running it directly will fail with instructions to use the curl command. This script **must be run via `curl | bash`** from your dev root. Running it directly will fail with instructions to use the curl command.

View File

@ -14,9 +14,17 @@ How `apply.sh` sets up and maintains AI instructions across all projects. See [R
curl -fsSL https://gitea.nikos-dev.keskikuja.site/niko/ai-superpower/raw/branch/main/apply.sh | bash curl -fsSL https://gitea.nikos-dev.keskikuja.site/niko/ai-superpower/raw/branch/main/apply.sh | bash
``` ```
**Bootstrap phase** — when piped through bash, `BASH_SOURCE[0]` is empty. The script uses this to detect the bootstrap context, then clones (or pulls) the repo and re-execs the local `apply.sh --bootstrapped DEV_ROOT`. **Bootstrap phase** — when piped through bash, `BASH_SOURCE[0]` is empty. The script uses this to detect the bootstrap context, then clones (or pulls) the repo and re-execs the local `apply.sh --bootstrapped DEV_ROOT`, forwarding any flags.
**Local phase** — runs with `--bootstrapped` flag. Scans dev root recursively for `.git` directories and runs per-project setup for each one found. **`--update` flag** — pass `--update` to skip all project setup and only pull the latest instructions:
```bash
curl -fsSL .../apply.sh | bash -s -- --update
```
The git pull still runs in bootstrap; local mode detects the flag at `$3`, prints the commit hash, and exits immediately. No projects are scanned, no docs touched.
**Local phase** — runs with `--bootstrapped` flag (without `--update`). Scans dev root recursively for `.git` directories and runs per-project setup for each one found.
## Project detection ## Project detection

View File

@ -10,15 +10,18 @@ RAW_URL="https://gitea.nikos-dev.keskikuja.site/niko/ai-superpower/raw/branch/ma
if [[ -z "${BASH_SOURCE[0]:-}" ]]; then if [[ -z "${BASH_SOURCE[0]:-}" ]]; then
DEV_ROOT="$PWD" # capture before exec replaces the process DEV_ROOT="$PWD" # capture before exec replaces the process
TARGET="$DEV_ROOT/$REPO_NAME" TARGET="$DEV_ROOT/$REPO_NAME"
EXTRA_FLAGS="${1:-}" # pass through --update if provided
if [[ -d "$TARGET" ]]; then if [[ -d "$TARGET" ]]; then
echo "→ updating $REPO_NAME ..." PREV_COMMIT="$(git -C "$TARGET" rev-parse --short HEAD 2>/dev/null || echo "")"
git -C "$TARGET" pull || { echo "✗ git pull failed"; exit 1; } echo "\u2192 updating $REPO_NAME ..."
git -C "$TARGET" pull || { echo "\u2717 git pull failed"; exit 1; }
else else
echo "→ cloning $REPO_NAME into $TARGET ..." PREV_COMMIT=""
git clone "$REPO_URL" "$TARGET" || { echo "✗ git clone failed"; exit 1; } echo "\u2192 cloning $REPO_NAME into $TARGET ..."
git clone "$REPO_URL" "$TARGET" || { echo "\u2717 git clone failed"; exit 1; }
fi fi
# Pass DEV_ROOT explicitly — local mode must not guess it from script location # Pass DEV_ROOT and PREV_COMMIT explicitly
exec bash "$TARGET/apply.sh" --bootstrapped "$DEV_ROOT" exec bash "$TARGET/apply.sh" --bootstrapped "$DEV_ROOT" ${EXTRA_FLAGS:+"$EXTRA_FLAGS"} "$PREV_COMMIT"
fi fi
# ── Guard — block direct invocation ────────────────────────────────────────── # ── Guard — block direct invocation ──────────────────────────────────────────
@ -26,7 +29,8 @@ if [[ "${1:-}" != "--bootstrapped" ]]; then
echo "✗ do not run this script directly." echo "✗ do not run this script directly."
echo " run from your dev root folder:" echo " run from your dev root folder:"
echo "" echo ""
echo " curl -fsSL $RAW_URL | bash" echo " curl -fsSL $RAW_URL | bash # full setup"
echo " curl -fsSL $RAW_URL | bash -s -- --update # update instructions only"
echo "" echo ""
exit 1 exit 1
fi fi
@ -36,7 +40,22 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEV_ROOT="${2:?DEV_ROOT not passed — re-run via curl}" DEV_ROOT="${2:?DEV_ROOT not passed — re-run via curl}"
AI_TARGET="$SCRIPT_DIR/.ai" AI_TARGET="$SCRIPT_DIR/.ai"
TEMPLATE_MARKER="<!-- ai-superpower:template" TEMPLATE_MARKER="<!-- ai-superpower:template"
# ── --update mode: instructions only, skip project setup ────────────────────
# git pull already ran in bootstrap; compare commits and report changes
if [[ "${3:-}" == "--update" ]]; then
COMMIT="$(git -C "$SCRIPT_DIR" rev-parse --short HEAD 2>/dev/null || echo "unknown")"
PREV_COMMIT="${4:-}"
echo ""
if [[ -z "$PREV_COMMIT" || "$PREV_COMMIT" == "$COMMIT" ]]; then
echo " version: $COMMIT (already up to date)"
else
echo " version: $PREV_COMMIT$COMMIT"
echo " new commits:"
git -C "$SCRIPT_DIR" log --oneline "${PREV_COMMIT}..HEAD" | sed 's/^/ /'
fi
echo ""
exit 0
fi
# Counters # Counters
cnt_found=0 cnt_found=0
cnt_no_docs=0 cnt_no_docs=0

View File

@ -14,6 +14,7 @@ A single bash script that gives any developer AI superpowers across all their pr
- **FR-1.2** If `ai-superpower/` does not exist in `$PWD`: clone the repo there - **FR-1.2** If `ai-superpower/` does not exist in `$PWD`: clone the repo there
- **FR-1.3** If `ai-superpower/` already exists: run `git pull` to update it - **FR-1.3** If `ai-superpower/` already exists: run `git pull` to update it
- **FR-1.4** After clone/pull: re-exec the local copy of `apply.sh` with `--bootstrapped DEV_ROOT` and stdin reopened from `/dev/tty` so interactive prompts work even when piped through curl - **FR-1.4** After clone/pull: re-exec the local copy of `apply.sh` with `--bootstrapped DEV_ROOT` and stdin reopened from `/dev/tty` so interactive prompts work even when piped through curl
- **FR-1.5** If `--update` is passed as the first argument (`curl ... | bash -s -- --update`): forward it through the re-exec along with the commit hash captured before `git pull`; local mode detects the flag at `$3`, compares `$4` (pre-pull commit) with the current HEAD, and either reports "already up to date" or prints new commit messages with `git log --oneline`; skips all project scanning and setup
### FR-2 Project discovery ### FR-2 Project discovery