diff --git a/scripts/claude-profile b/scripts/claude-profile index 866803f..6a8da0b 100755 --- a/scripts/claude-profile +++ b/scripts/claude-profile @@ -10,6 +10,29 @@ set -euo pipefail DEFAULT_DIR="$HOME/.claude" PROFILE_PATTERN="$HOME/.claude-*" +# Emit a WezTerm user-var escape sequence to trigger profile-based theming. +# WezTerm decodes the base64 value and fires a 'user-var-changed' event. +# Safe to call in non-WezTerm terminals — the escape sequence is silently ignored. +set_wezterm_profile() { + local profile_name="$1" + printf '\e]1337;SetUserVar=%s=%s\a' CLAUDE_PROFILE "$(printf '%s' "$profile_name" | base64)" +} + +# Reset WezTerm theme when the script exits (e.g., Claude session ends) +reset_wezterm_profile() { + printf '\e]1337;SetUserVar=%s=%s\a' CLAUDE_PROFILE "$(printf '%s' '_reset' | base64)" +} +trap reset_wezterm_profile EXIT + +# Sync all repos before starting a session +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +SYNC_SCRIPT="${SCRIPT_DIR}/sync-repos" +if [[ -x "$SYNC_SCRIPT" ]]; then + echo "Syncing repos..." + "$SYNC_SCRIPT" || echo "Warning: some repos failed to sync (continuing anyway)" + echo "" +fi + # Gather profiles profiles=() for dir in $PROFILE_PATTERN; do @@ -23,8 +46,10 @@ if [[ ${1:-} ]]; then target="$HOME/.claude-$1" if [[ -d "$target" ]]; then export CLAUDE_CONFIG_DIR="$target" + set_wezterm_profile "$1" echo "Using profile: $1 ($target)" - exec claude "${@:2}" + claude "${@:2}" + exit $? else echo "Profile '$1' not found. Create it with: mkdir -p $target" >&2 exit 1 @@ -58,16 +83,15 @@ selected="${options[$((choice - 1))]}" if [[ "$selected" == "default" ]]; then echo "Using default profile ($DEFAULT_DIR)" export CLAUDE_CONFIG_DIR="$DEFAULT_DIR" + set_wezterm_profile "default" else target="$HOME/.claude-$selected" echo "Using profile: $selected ($target)" export CLAUDE_CONFIG_DIR="$target" + set_wezterm_profile "$selected" fi -#set -uo pipefail - # Load the context -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" CONTEXT_LOADER="${SCRIPT_DIR}/context-load" if [[ ! -x "$CONTEXT_LOADER" ]]; then @@ -78,7 +102,7 @@ fi context="$("$CONTEXT_LOADER")" if [[ -n "$context" ]]; then - exec claude --append-system-prompt "$context" "$@" + claude --append-system-prompt "$context" "$@" else - exec claude "$@" + claude "$@" fi diff --git a/scripts/sync-repos b/scripts/sync-repos new file mode 100755 index 0000000..ed2d884 --- /dev/null +++ b/scripts/sync-repos @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +# sync-repos — Pull latest for all git repos under ~/dev/claude +# Usage: +# sync-repos # pull all repos +# sync-repos --dryrun # show what would be pulled +# sync-repos -n # same as --dryrun + +set -euo pipefail + +BASE_DIR="${HOME}/dev/claude" +DRYRUN=false + +if [[ "${1:-}" == "--dryrun" || "${1:-}" == "-n" ]]; then + DRYRUN=true +fi + +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +RED='\033[0;31m' +DIM='\033[2m' +RESET='\033[0m' + +pulled=0 +skipped=0 +failed=0 +dirty=0 + +# Find all git repos (look for .git dirs, max depth 3 to cover projects/ and octopus/) +while IFS= read -r gitdir; do + repo_dir="$(dirname "$gitdir")" + repo_name="${repo_dir#"${BASE_DIR}/"}" + + # Skip if no remote configured + if ! git -C "$repo_dir" remote get-url origin &>/dev/null; then + printf "${DIM} skip %-40s no remote${RESET}\n" "$repo_name" + skipped=$((skipped + 1)) + continue + fi + + # Check for uncommitted changes + if ! git -C "$repo_dir" diff --quiet 2>/dev/null || ! git -C "$repo_dir" diff --cached --quiet 2>/dev/null; then + has_changes=true + else + has_changes=false + fi + + if $DRYRUN; then + branch="$(git -C "$repo_dir" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")" + if $has_changes; then + printf "${YELLOW} dirty %-40s %s (has uncommitted changes)${RESET}\n" "$repo_name" "$branch" + dirty=$((dirty + 1)) + else + printf "${GREEN} pull %-40s %s${RESET}\n" "$repo_name" "$branch" + pulled=$((pulled + 1)) + fi + continue + fi + + # Pull with --ff-only to avoid creating merge commits + branch="$(git -C "$repo_dir" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")" + output="$(git -C "$repo_dir" pull --ff-only 2>&1)" && rc=0 || rc=$? + + if [[ $rc -eq 0 ]]; then + if echo "$output" | grep -q "Already up to date"; then + printf "${DIM} ok %-40s %s (up to date)${RESET}\n" "$repo_name" "$branch" + else + printf "${GREEN} pull %-40s %s${RESET}\n" "$repo_name" "$branch" + fi + pulled=$((pulled + 1)) + else + printf "${RED} FAIL %-40s %s${RESET}\n" "$repo_name" "$branch" + printf "${DIM} %s${RESET}\n" "$output" + failed=$((failed + 1)) + fi + +done < <(find "$BASE_DIR" -maxdepth 4 -name .git -type d 2>/dev/null | sort) + +echo "" +if $DRYRUN; then + echo "Dryrun: ${pulled} would pull, ${dirty} dirty, ${skipped} skipped" +else + echo "Done: ${pulled} pulled, ${failed} failed, ${skipped} skipped" +fi + +[[ $failed -eq 0 ]]