diff --git a/scripts/claude-start.sh b/scripts/claude-start.sh new file mode 100755 index 00000000..cbeb0d67 --- /dev/null +++ b/scripts/claude-start.sh @@ -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 [base-branch] [-- ] +# +# Creates a sibling worktree at /homelab- on a new branch +# (branched from , default: master), then runs `claude` inside it. +# If the worktree already exists it is reused. Clean up afterwards with +# scripts/claude-stop.sh . + +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") [base-branch] [-- ]"; 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 "$@" diff --git a/scripts/claude-stop.sh b/scripts/claude-stop.sh new file mode 100755 index 00000000..5a9ec496 --- /dev/null +++ b/scripts/claude-stop.sh @@ -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 [--force] [--delete-branch] +# +# Removes the sibling worktree /homelab-. Refuses if the worktree +# has uncommitted/untracked changes unless --force is given. With --delete-branch +# the local branch 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") [--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."