diff --git a/claude-sync b/claude-sync new file mode 100755 index 0000000..a87df7f --- /dev/null +++ b/claude-sync @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# claude-sync — git pull before Claude, commit+push after. +# Safe on conflicts: never merges/forces; just reports and lets you resolve. +# The MiniTerm app cd's into the project dir first, so git runs on the CWD. +set -uo pipefail + +# Aus dem GUI gestartet (ghostty-App) erbt der Prozess nur den launchd-PATH +# (/usr/bin:/bin:…) — ~/.local/bin fehlt, also würde `claude` unten nicht +# gefunden und das Skript sofort enden. Eigenes Verzeichnis (dort liegt der +# claude-Symlink) voranstellen. +self_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +export PATH="$self_dir:$PATH" + +ok() { printf '\033[1;32m✓ %s\033[0m\n' "$*"; } # green +note() { printf '\033[1;36m· %s\033[0m\n' "$*"; } # cyan +warn() { printf '\033[1;33m⚠ %s\033[0m\n' "$*"; } # yellow + +# --- Is this a git repo with a remote? ------------------------------------- +if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then + warn "Kein Git-Repo hier — starte Claude ohne Sync." + exec claude "$@" +fi +have_remote=0 +git remote get-url origin >/dev/null 2>&1 && have_remote=1 +branch=$(git rev-parse --abbrev-ref HEAD) + +# --- PULL before start ------------------------------------------------------ +if [[ "$have_remote" -eq 1 ]]; then + git fetch --quiet origin "$branch" 2>/dev/null || true + if git rev-parse --verify --quiet "origin/$branch" >/dev/null; then + behind=$(git rev-list --count "HEAD..origin/$branch" 2>/dev/null || echo 0) + if [[ "$behind" -eq 0 ]]; then + ok "git pull: bereits aktuell ($branch)." + elif git merge --ff-only "origin/$branch" >/dev/null 2>&1; then + ok "git pull: $behind Commit(s) geholt ($branch)." + else + warn "git pull übersprungen — kein sauberer Fast-Forward (lokale Änderungen oder divergierte History). Bitte manuell lösen." + fi + else + note "Kein Remote-Branch '$branch' — Pull übersprungen." + fi +else + note "Kein origin-Remote — Sync übersprungen." +fi + +# --- run Claude ------------------------------------------------------------- +claude "$@" +claude_rc=$? + +# --- PUSH after end --------------------------------------------------------- +if [[ "$have_remote" -eq 1 ]]; then + # Commit any working-tree changes (CLAUDE.md, memories, ...) so they can be pushed. + if [[ -n "$(git status --porcelain)" ]]; then + git add -A + git commit --quiet -m "claude sync: $(date '+%Y-%m-%d %H:%M')" && \ + note "Änderungen committed." + fi + if git rev-parse --abbrev-ref --symbolic-full-name '@{u}' >/dev/null 2>&1; then + ahead=$(git rev-list --count '@{u}..HEAD' 2>/dev/null || echo 0) + if [[ "$ahead" -eq 0 ]]; then + note "git push: nichts zu pushen." + elif git push --quiet 2>/dev/null; then + ok "git push: $ahead Commit(s) gepusht." + else + warn "git push abgelehnt — Remote hat neue Commits. Bitte manuell mergen/pushen." + fi + else + if git push --quiet -u origin "$branch" 2>/dev/null; then + ok "git push: Upstream gesetzt und gepusht." + else + warn "Kein Upstream gesetzt, automatischer Push fehlgeschlagen — bitte einmal manuell pushen." + fi + fi +fi + +exit "$claude_rc"