scripts: add claude-start/stop worktree wrappers #19

Merged
k.renner merged 1 commits from chore/claude-worktree-scripts into master 2026-06-15 09:09:57 +00:00
2 changed files with 100 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
set -euo pipefail
# Create (or reuse) a git worktree for the homelab repo and launch Claude Code in it.
#
# Usage:
# scripts/claude-start.sh <name> [base-branch] [-- <extra claude args>]
#
# Creates a sibling worktree at <parent>/homelab-<name> on a new branch <name>
# (branched from <base-branch>, default: master), then runs `claude` inside it.
# If the worktree already exists it is reused. Clean up afterwards with
# scripts/claude-stop.sh <name>.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MAIN_REPO="$(dirname "$(git -C "$SCRIPT_DIR" rev-parse --path-format=absolute --git-common-dir)")"
PARENT="$(dirname "$MAIN_REPO")"
PREFIX="$(basename "$MAIN_REPO")"
command -v claude >/dev/null || { echo "claude CLI not found in PATH"; exit 1; }
NAME="${1:-}"
[ -n "$NAME" ] || { echo "usage: $(basename "$0") <name> [base-branch] [-- <claude args>]"; exit 1; }
shift
BASE_BRANCH="master"
if [ $# -gt 0 ] && [ "$1" != "--" ]; then
BASE_BRANCH="$1"; shift
fi
[ "${1:-}" = "--" ] && shift # drop the separator; remaining args are passed to claude
WORKTREE="$PARENT/$PREFIX-$NAME"
BRANCH="$NAME"
if [ -d "$WORKTREE" ]; then
echo "Reusing existing worktree: $WORKTREE"
else
echo "Creating worktree: $WORKTREE (branch: $BRANCH, base: $BASE_BRANCH)"
git -C "$MAIN_REPO" fetch --quiet origin "$BASE_BRANCH" 2>/dev/null || true
if git -C "$MAIN_REPO" show-ref --verify --quiet "refs/heads/$BRANCH"; then
git -C "$MAIN_REPO" worktree add "$WORKTREE" "$BRANCH"
else
git -C "$MAIN_REPO" worktree add -b "$BRANCH" "$WORKTREE" "$BASE_BRANCH"
fi
fi
echo "Launching claude in $WORKTREE"
cd "$WORKTREE"
exec claude "$@"
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -euo pipefail
# Remove a homelab worktree created by scripts/claude-start.sh.
#
# Usage:
# scripts/claude-stop.sh <name> [--force] [--delete-branch]
#
# Removes the sibling worktree <parent>/homelab-<name>. Refuses if the worktree
# has uncommitted/untracked changes unless --force is given. With --delete-branch
# the local branch <name> is also deleted (only if fully merged; combine with
# --force to hard-delete an unmerged branch).
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MAIN_REPO="$(dirname "$(git -C "$SCRIPT_DIR" rev-parse --path-format=absolute --git-common-dir)")"
PARENT="$(dirname "$MAIN_REPO")"
PREFIX="$(basename "$MAIN_REPO")"
NAME="${1:-}"
[ -n "$NAME" ] || { echo "usage: $(basename "$0") <name> [--force] [--delete-branch]"; exit 1; }
shift
FORCE=""
DELETE_BRANCH=""
for arg in "$@"; do
case "$arg" in
--force) FORCE="--force" ;;
--delete-branch) DELETE_BRANCH=1 ;;
*) echo "unknown option: $arg"; exit 1 ;;
esac
done
WORKTREE="$PARENT/$PREFIX-$NAME"
BRANCH="$NAME"
[ -d "$WORKTREE" ] || { echo "no such worktree: $WORKTREE"; exit 1; }
echo "Removing worktree: $WORKTREE"
git -C "$MAIN_REPO" worktree remove ${FORCE:+$FORCE} "$WORKTREE"
git -C "$MAIN_REPO" worktree prune
if [ -n "$DELETE_BRANCH" ]; then
if [ -n "$FORCE" ]; then
echo "Deleting branch (force): $BRANCH"
git -C "$MAIN_REPO" branch -D "$BRANCH"
else
echo "Deleting branch (if merged): $BRANCH"
git -C "$MAIN_REPO" branch -d "$BRANCH"
fi
fi
echo "Done."