| name | update |
| description | Update BastionClaw from upstream without overwriting user data, skills, or customizations. Detects conflicts and helps merge. |
| allowed-tools | Bash(*), Read, Edit, Write, Glob, Grep, AskUserQuestion |
Update BastionClaw
UX Rule: Use AskUserQuestion for ALL interactions with the user. Never just output questions as text — always use the tool so the user gets structured prompts with selectable options.
Safely update from the upstream repository while preserving all user data and customizations.
Customization Zone Reference
BastionClaw files are organized into three zones. This skill respects these boundaries during updates.
Green Zone — Safe to Customize (Never Overwritten)
These files are yours. Updates will never touch them.
| Location | What It Is |
|---|
.env | Secrets and configuration |
store/ | Database, auth sessions, all persistent data |
data/ | IPC files, sessions, runtime state |
logs/ | Host and container logs |
groups/*/ (except CLAUDE.md) | Group workspace files, insights, logs, conversations |
groups/{user-created}/ | Entire user-created group directories |
~/.config/bastionclaw/ | Mount allowlist (external to repo) |
workspace/ | YouTube transcripts, skill output |
.claude/projects/ | Claude Code session memory |
container/skills/{user-created}/ | User-added container skills |
.claude/skills/youtube-planner/sources.json | Local YouTube source tracking |
Yellow Zone — Customizable With Care (Merge on Update)
These files ship with defaults but you may have edited them. Updates will detect changes and help you merge.
| Location | What It Is | How Updates Handle It |
|---|
groups/main/CLAUDE.md | Main group system prompt and memory | Three-way merge: your edits preserved, new upstream sections added |
groups/global/CLAUDE.md | Shared memory for all groups | Same three-way merge |
container/skills/ (shipped ones) | Container-side skills (agent-browser, refresh-insights) | Replaced unless you edited them |
| Service files (plist/systemd) | Generated by /setup | Preserved if exists; regenerate with /setup if needed |
Red Zone — Do Not Modify (Replaced on Update)
These files are framework code. Changes here will be overwritten on update.
| Location | What It Is |
|---|
src/**/*.ts | All host TypeScript source |
container/agent-runner/src/**/*.ts | Container agent source |
container/Dockerfile, container/build.sh | Container build files |
.claude/skills/*/SKILL.md (shipped skills) | Skill definitions |
.claude/commands/*.md | Slash commands |
scripts/*.sh, scripts/*.py | Utility scripts |
docs/*.md | Documentation |
package.json, package-lock.json | Dependencies |
tsconfig.json, vitest.config.ts | Build config |
ui/ | Web UI source and build |
.github/ | CI workflows |
CLAUDE.md (root) | Project quick reference |
README.md | Project documentation |
If you need to customize Red Zone behavior, do it through:
- CLAUDE.md files (Yellow Zone) — Change agent behavior, prompts, memory
- Skills — Add new
.claude/skills/{your-skill}/SKILL.md directories (Green Zone, since they're new)
.env — Configuration via environment variables (Green Zone)
- Container skills — Add new directories under
container/skills/ (Green Zone)
Phase 1: Pre-flight Checks
git remote -v | grep -q "bastionclaw" && echo "OK: correct repo" || echo "ERROR: not a bastionclaw repo"
git status --porcelain | head -20
node -p "require('./package.json').version"
git remote -v
If there are uncommitted changes, ask the user:
AskUserQuestion: "You have uncommitted changes. How should we handle them?"
- Stash them —
git stash before update, git stash pop after (Recommended)
- Commit first — Create a commit with current changes before updating
- Abort — Stop the update, let me handle it manually
Phase 2: Fetch and Compare
git fetch origin main
git log --oneline HEAD..origin/main | head -30
echo "$(git rev-list --count HEAD..origin/main) new commits"
If there are no new commits, tell the user they're already up to date and stop.
Show the user a summary of what changed:
git diff --stat HEAD..origin/main
Categorize the changes by zone:
git diff --name-only HEAD..origin/main | grep -E '^(src/|container/agent-runner/|container/Dockerfile|container/build\.sh|scripts/|docs/|ui/|package|tsconfig|vitest|\.github/|\.claude/skills/|\.claude/commands/|CLAUDE\.md|README\.md)' | head -30
git diff --name-only HEAD..origin/main | grep -E '^groups/(main|global)/CLAUDE\.md$|^container/skills/'
git diff --name-only HEAD..origin/main | grep -E '^(\.env|store/|data/|logs/)' && echo "WARNING: Update touches user data files!" || echo "OK: No user data files touched"
Present the summary to the user:
AskUserQuestion: "Here's what the update includes: [summary]. Ready to proceed?"
- Apply update — Merge changes, handle conflicts interactively (Recommended)
- Review details first — Show me the full diff before proceeding
- Abort — Cancel the update
Phase 3: Detect Yellow Zone Conflicts
Before merging, check if the user has modified Yellow Zone files:
MERGE_BASE=$(git merge-base HEAD origin/main)
for file in groups/main/CLAUDE.md groups/global/CLAUDE.md; do
if [ -f "$file" ]; then
if ! git diff --quiet "$MERGE_BASE" -- "$file" 2>/dev/null; then
echo "MODIFIED: $file (user has local changes)"
else
echo "CLEAN: $file (no local changes)"
fi
fi
done
For container skills, check if shipped skills have been modified:
for dir in container/skills/agent-browser container/skills/refresh-insights; do
if [ -d "$dir" ]; then
if ! git diff --quiet "$MERGE_BASE" -- "$dir" 2>/dev/null; then
echo "MODIFIED: $dir (user has local changes)"
fi
fi
done
Handling Yellow Zone Conflicts
For each modified Yellow Zone file that also changed upstream:
- Show the conflict — Display what the user changed vs what upstream changed
- AskUserQuestion with options:
- Keep mine — Preserve your version, skip upstream changes to this file
- Take upstream — Replace with the new upstream version (your changes are lost)
- Merge interactively — Show both versions side-by-side, help combine them
- Merge automatically — Attempt
git merge-file three-way merge
For automatic merge:
git show "$MERGE_BASE:$file" > /tmp/base_version
git show "origin/main:$file" > /tmp/upstream_version
cp "$file" /tmp/our_version
git merge-file /tmp/our_version /tmp/base_version /tmp/upstream_version
if [ $? -eq 0 ]; then
echo "Clean merge — no conflicts"
cp /tmp/our_version "$file"
else
echo "Merge has conflicts — needs manual resolution"
cat /tmp/our_version
fi
Phase 4: Apply the Update
git tag "pre-update-$(date +%Y%m%d-%H%M%S)" HEAD
git merge origin/main --no-edit
If the merge has conflicts:
git diff --name-only --diff-filter=U
For each conflicted file:
- Red Zone files: Accept the upstream version (
git checkout --theirs <file>)
- Yellow Zone files: Use the interactive merge from Phase 3
- Green Zone files: Should not conflict (flag if they do — something is wrong)
After resolving all conflicts:
git add -A && git commit --no-edit
Phase 5: Post-Update Tasks
Run these in order:
npm install
npm run build
ls .claude/skills/ | sort
git diff --name-only "pre-update-*"..HEAD -- container/ | head -5
If container files changed:
./container/build.sh
If UI files changed:
cd ui && npm install && npm run build && cd ..
Database Migrations
Check if the update includes schema changes:
git diff "$(git describe --tags --abbrev=0 --match 'pre-update-*')"..HEAD -- src/db.ts | grep -E 'CREATE TABLE|ALTER TABLE|CREATE INDEX' | head -10
If schema changes are detected, inform the user. The initDatabase() function handles migrations automatically on restart — but mention it so they know.
Restart the Service
./scripts/restart.sh --build
Phase 6: Verify
node -p "require('./package.json').version"
npm run build 2>&1 | tail -3
tail -5 logs/bastionclaw.log
git stash list | head -3
If we stashed changes in Phase 1:
git stash pop
If the stash pop has conflicts, help the user resolve them.
Rollback
If anything goes wrong, the user can roll back:
git tag -l 'pre-update-*' | sort | tail -1
git reset --hard <tag-name>
npm install && npm run build
./scripts/restart.sh --build
Tell the user about this option if any step fails.