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.mddirectories (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
# 1. Check we're in a git repo with the right remote
git remote -v | grep -q "bastionclaw" && echo "OK: correct repo" || echo "ERROR: not a bastionclaw repo"
# 2. Check for uncommitted changes
git status --porcelain | head -20
# 3. Get current version
node -p "require('./package.json').version"
# 4. Check the remote exists
git remote -v
If there are uncommitted changes, ask the user:
AskUserQuestion: "You have uncommitted changes. How should we handle them?"
- Stash them —
git stashbefore update,git stash popafter (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
# Fetch latest from origin
git fetch origin main
# Show what's new
git log --oneline HEAD..origin/main | head -30
# Count changes
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:
# Files changed in the update
git diff --stat HEAD..origin/main
Categorize the changes by zone:
# Red Zone changes (will be applied automatically)
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
# Yellow Zone changes (need merge check)
git diff --name-only HEAD..origin/main | grep -E '^groups/(main|global)/CLAUDE\.md$|^container/skills/'
# Green Zone files (should NOT appear — if they do, flag it)
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:
# Check if user has modified groups/main/CLAUDE.md from what we shipped
# Get the version from the merge base (what was shipped when user last updated)
MERGE_BASE=$(git merge-base HEAD origin/main)
# Check each Yellow Zone file
for file in groups/main/CLAUDE.md groups/global/CLAUDE.md; do
if [ -f "$file" ]; then
# Compare current file to what was in git at merge-base
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:
# Check shipped container skills
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-filethree-way merge
For automatic merge:
# Three-way merge: base (merge-base version) + ours (current) + theirs (upstream)
git show "$MERGE_BASE:$file" > /tmp/base_version
git show "origin/main:$file" > /tmp/upstream_version
cp "$file" /tmp/our_version
# Attempt merge
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"
# Show conflict markers to user
cat /tmp/our_version
fi
Phase 4: Apply the Update
# Create a safety tag before updating
git tag "pre-update-$(date +%Y%m%d-%H%M%S)" HEAD
# Merge origin/main
git merge origin/main --no-edit
If the merge has conflicts:
# Show conflicted files
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:
# 1. Install any new/updated dependencies
npm install
# 2. Build TypeScript
npm run build
# 3. Check for new skills
ls .claude/skills/ | sort
# 4. Check if container needs rebuild
git diff --name-only "pre-update-*"..HEAD -- container/ | head -5
If container files changed:
# Rebuild the container image
./container/build.sh
If UI files changed:
cd ui && npm install && npm run build && cd ..
Database Migrations
Check if the update includes schema changes:
# Look for migration-related changes in db.ts
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
# 1. Check new version
node -p "require('./package.json').version"
# 2. Check build is clean
npm run build 2>&1 | tail -3
# 3. Check service is running
tail -5 logs/bastionclaw.log
# 4. Unstash if we stashed in Phase 1
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:
# Find the safety tag
git tag -l 'pre-update-*' | sort | tail -1
# Roll back to it
git reset --hard <tag-name>
npm install && npm run build
./scripts/restart.sh --build
Tell the user about this option if any step fails.