sync: global→pool, pool-guard raus, Session-Watcher-Setup, verbotenes Wort Ehrlich
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
# Allgemeine Vorgaben
|
||||
|
||||
- Sachlicher Ton, normales ruhiges Deutsch. Kein Motivieren, Loben oder Bedauern, keine Werbe-/Selbst-Slogans.
|
||||
- So knapp wie möglich: nur Fakten, keine Füllabsätze, keine Wiederholung meiner Aussagen, keine Annahmen über den Kontext.
|
||||
- Nur handeln, wenn ich es ausdrücklich sage. Sonst nur antworten/erklären.
|
||||
- Eine konkrete Frage NUR beantworten — exakt das Gefragte, nicht mehr. Ja/Nein-Frage = Ja/Nein. Kein Entwerfen, keine Optionen, keine Lösung, kein Vorschlag, keine ungefragte Recherche/Investigation — auch nicht, wenn etwas falsch, gefährlich oder verbesserungswürdig aussieht. Ein auffälliger Punkt wird höchstens in einem Halbsatz benannt, nicht ausgearbeitet.
|
||||
- Keine Vorschläge für weiteres Vorgehen oder was man sonst noch machen könnte.
|
||||
- Positiv formulieren: beschreiben, was der Code tut / was getan wurde — nicht, was man nicht tut. Negationsketten vermeiden.
|
||||
- Bei Unsicherheit „weiß ich nicht" / „unklar" sagen, statt mit generischem Text aufzufüllen.
|
||||
|
||||
# Rückfragen
|
||||
|
||||
- Antworten NIE mit einer Rückfrage oder einem Angebot beenden (kein „soll ich", „willst du", „ich kann auch…").
|
||||
- Rückfragen nur, wenn die Aufgabe ohne Klärung nicht lösbar ist — und dann am Anfang, nie am Ende.
|
||||
- Keine rhetorischen Fragen.
|
||||
|
||||
# Expertise — ich und Dritte
|
||||
|
||||
- Mich als Experten behandeln. Keine Grundlagen, Fachbegriffe oder Definitionen ungefragt erklären; kein „X bedeutet…", keine Einordnung von Begriffen, die ich selbst verwende.
|
||||
- Kein fehlendes Wissen unterstellen. Bei unklarem Wissensstand kurz fragen oder direkt auf hohem Niveau einsteigen.
|
||||
- Keine selbstverständlichen Voraussetzungen oder Trivial-Caveats anhängen (z. B. „braucht Admin-Rechte", „muss installiert sein", „erfordert Schreibzugriff"). Was ein Fachmann mit 25 Jahren Erfahrung ohnehin weiß, weglassen. Denselben Hinweis nie wiederholen.
|
||||
- Auch Dritten, über die wir sprechen, Kompetenz unterstellen. Bei „Warum"-Fragen die plausible fachliche Abwägung rekonstruieren; keine Dummheit oder Unwissen ohne Beleg unterstellen.
|
||||
|
||||
# Anker
|
||||
|
||||
- Diese Datei ist die Quelle für `~/.claude/CLAUDE.md` (Symlink). Änderungen direkt hier in `~/claude-projects/pool/CLAUDE.md` vornehmen, nicht über den Symlink-Pfad.
|
||||
- Anker für projektübergreifend Gemeinsames (Checklisten, Notizen, Memory, geteilte Dateien) ist `~/claude-projects/robotunits`. Solche Dateien gehören dorthin, nicht unter `~/projects/...`.
|
||||
- Projektspezifisches (z. B. SessionStart-Hooks) bleibt im jeweiligen Projekt unter dessen `.claude/settings.json` — nicht global.
|
||||
|
||||
# Handeln / Plan
|
||||
|
||||
- Vor verändernden Aktionen (Install, neue Dependencies, neue Dateien, Commit, Multi-File-Edit) erst kurz den Plan zeigen (was + warum), dann Go abwarten.
|
||||
- NUR SUCHEN, WENN AUSDRÜCKLICH ANGEWIESEN. Keine eigenmächtigen Such-, Erkundungs- oder Datei-Befehle (Bash, grep, find, ls, which, Tool-Suchen, Agenten). Auch nach einem fehlgeschlagenen Befehl nicht selbsttätig weitersuchen. Eine Ja/Nein- oder Faktenfrage wird beantwortet, nicht durch Suchen „belegt". Suchen erst auf ausdrückliche Anweisung.
|
||||
|
||||
# Kein defensiver Code
|
||||
|
||||
- Keine Sicherheits-/Defensiv-Logik einbauen, die ich nicht ausdrücklich anordne: keine Fallbacks, keine try/catch-Auffangschichten, keine Default-Werte, keine if/else-Absicherungen, keine Existenz-/Null-Checks „zur Sicherheit".
|
||||
- Genau und nur das umsetzen, was ich sage — nichts ergänzen, nichts „robuster" machen.
|
||||
- Wenn etwas kaputt ist, soll es sichtbar kaputt sein (laut scheitern), nicht still abgefangen oder weggebügelt werden.
|
||||
- Hängende oder ungewöhnlich lange laufende Befehle, Timeouts und fehlenden Zugriff/Berechtigung sofort explizit melden („hängt", „dauert zu lange", „kein Zugriff") und stoppen — nicht still abwarten oder verschlucken.
|
||||
|
||||
# PROD-Umgebungen
|
||||
|
||||
- Jede Interaktion mit einer PROD-Umgebung (Cluster, Pods, Deployments, Secrets) nur auf ausdrückliche Ansage. Ohne explizite Nennung von „PROD" bezieht sich jede Aktion auf DEV/den aktuellen Kontext.
|
||||
- Das gilt auch für reine Lese-/Statusabfragen — die Lese-Ausnahme greift bei PROD nicht.
|
||||
|
||||
# Git
|
||||
|
||||
- KEIN Hinweis auf Claude in Commit-Messages: kein „Co-Authored-By: Claude", kein „Generated with Claude Code", keine Claude-Trailer oder -Erwähnungen. Gilt für alle Repos, auch in PR-Beschreibungen.
|
||||
|
||||
# Verbotene Wörter und Phrasen
|
||||
|
||||
Nie verwenden, weder in Texten noch in Antworten:
|
||||
- „Der Clou" / „Der Witz" / „Der Hit" / „Die Pointe"
|
||||
- Sinngleiche Effekthascherei: „der Knaller", „das Highlight", „der Wow-Effekt", „die Sensation"
|
||||
- Englische Technikbegriffe nicht holprig eindeutschen (z. B. nicht „spritzen" für *inject*).
|
||||
- „Ehrlich" als Einleitung oder Anrede (z. B. „Ehrlich gesagt", „Ehrlich zum …") — stattdessen direkt die Aussage.
|
||||
Executable
+84
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
# git-sync — add/commit/pull --rebase/push.
|
||||
# git-sync alle Repos aus permissions.additionalDirectories
|
||||
# git-sync <dir> [message] ein einzelnes Repo
|
||||
# Safe: rebaset auf den Remote, kein Merge, kein force-push; Konflikte werden
|
||||
# gemeldet (Rebase abgebrochen), nicht automatisch aufgelöst.
|
||||
set -uo pipefail
|
||||
|
||||
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
|
||||
|
||||
sync_one() {
|
||||
local dir=$1 msg=${2:-} label branch ahead behind
|
||||
case "$dir" in "~") dir="$HOME" ;; "~/"*) dir="$HOME/${dir#"~/"}" ;; esac
|
||||
label=$(basename "$dir")
|
||||
|
||||
if ! git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
warn "$label: kein Git-Repo — übersprungen."; return 0
|
||||
fi
|
||||
branch=$(git -C "$dir" rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# add/commit
|
||||
if [ -n "$(git -C "$dir" status --porcelain)" ]; then
|
||||
git -C "$dir" add -A
|
||||
[ -z "$msg" ] && msg="git-sync: $(date '+%Y-%m-%d %H:%M')"
|
||||
if git -C "$dir" commit --quiet -m "$msg"; then
|
||||
note "$label: committed — $msg"
|
||||
else
|
||||
warn "$label: commit fehlgeschlagen."; return 0
|
||||
fi
|
||||
else
|
||||
note "$label: keine Änderungen."
|
||||
fi
|
||||
|
||||
# pull --rebase, dann push
|
||||
if ! git -C "$dir" remote get-url origin >/dev/null 2>&1; then
|
||||
note "$label: kein origin-Remote — push übersprungen."; return 0
|
||||
fi
|
||||
|
||||
if git -C "$dir" rev-parse --abbrev-ref --symbolic-full-name '@{u}' >/dev/null 2>&1; then
|
||||
git -C "$dir" fetch --quiet 2>/dev/null || true
|
||||
behind=$(git -C "$dir" rev-list --count 'HEAD..@{u}' 2>/dev/null || echo 0)
|
||||
if [ "$behind" -gt 0 ]; then
|
||||
if git -C "$dir" pull --rebase --quiet 2>/dev/null; then
|
||||
note "$label: $behind Commit(s) per Rebase integriert."
|
||||
else
|
||||
git -C "$dir" rebase --abort >/dev/null 2>&1 || true
|
||||
warn "$label: Pull/Rebase-Konflikt — bitte manuell lösen. Push übersprungen."; return 0
|
||||
fi
|
||||
fi
|
||||
ahead=$(git -C "$dir" rev-list --count '@{u}..HEAD' 2>/dev/null || echo 0)
|
||||
if [ "$ahead" -eq 0 ]; then
|
||||
note "$label: nichts zu pushen."
|
||||
elif git -C "$dir" push --quiet 2>/dev/null; then
|
||||
ok "$label: $ahead Commit(s) gepusht ($branch)."
|
||||
else
|
||||
warn "$label: push abgelehnt — Remote voraus. Manuell prüfen."
|
||||
fi
|
||||
else
|
||||
if git -C "$dir" push --quiet -u origin "$branch" 2>/dev/null; then
|
||||
ok "$label: Upstream gesetzt und gepusht ($branch)."
|
||||
else
|
||||
warn "$label: kein Upstream, push fehlgeschlagen — einmal manuell pushen."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# --- dispatch --------------------------------------------------------------
|
||||
if [ $# -ge 1 ]; then
|
||||
sync_one "$1" "${2:-}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ohne Argument: alle additionalDirectories aus den Settings (cwd + User)
|
||||
dirs=$(for f in .claude/settings.json .claude/settings.local.json "$HOME/.claude/settings.json"; do
|
||||
[ -f "$f" ] && jq -r '.permissions.additionalDirectories[]?' "$f" 2>/dev/null
|
||||
done | sort -u)
|
||||
if [ -z "$dirs" ]; then
|
||||
note "keine additionalDirectories gefunden (cwd: $PWD)"; exit 0
|
||||
fi
|
||||
while IFS= read -r d; do
|
||||
[ -n "$d" ] && sync_one "$d"
|
||||
done <<< "$dirs"
|
||||
Executable
+55
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env bash
|
||||
# new-project — scaffold a new claude-projects project + matching ~/projects dir,
|
||||
# register it, then commit & push claude-projects.
|
||||
# Usage: new-project <name>
|
||||
set -euo pipefail
|
||||
|
||||
name=${1:?usage: new-project <name>}
|
||||
case "$name" in
|
||||
*/* | *" "* | .*) echo "ungültiger Name: $name" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
cproot="$HOME/claude-projects"
|
||||
root="$cproot/$name"
|
||||
[ -e "$root" ] && { echo "existiert bereits: $root" >&2; exit 1; }
|
||||
|
||||
# 1. Code-Verzeichnis unter ~/projects
|
||||
mkdir -p "$HOME/projects/$name"
|
||||
|
||||
# 2. claude-projects-Scaffold
|
||||
mkdir -p "$root/.claude" "$root/memory"
|
||||
|
||||
cat > "$root/.claude/settings.json" <<EOF
|
||||
{
|
||||
"autoMemoryDirectory": "~/claude-projects/$name/memory",
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Edit(~/projects/$name/**)",
|
||||
"Edit(~/claude-projects/$name/**)"
|
||||
],
|
||||
"additionalDirectories": [
|
||||
"~/projects/$name"
|
||||
]
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
cat > "$root/.claude/settings.local.json" <<'EOF'
|
||||
{
|
||||
"permissions": {
|
||||
"allow": []
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
printf '# Memory Index\n' > "$root/memory/MEMORY.md"
|
||||
|
||||
# 3. claude-projects committen & pushen (nur den neuen Projektordner)
|
||||
git -C "$cproot" add "$name"
|
||||
git -C "$cproot" commit -q -m "new project: $name"
|
||||
git -C "$cproot" push -q
|
||||
|
||||
echo "angelegt:"
|
||||
echo " ~/projects/$name (Code-Verzeichnis)"
|
||||
echo " ~/claude-projects/$name (.claude/settings*, memory/MEMORY.md)"
|
||||
echo " registriert in additionalDirectories + Edit-Regeln, committet & gepusht"
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
description: Commit + Push aller persistent konfigurierten Projekt-Repos
|
||||
---
|
||||
|
||||
Führe genau dieses eine Kommando aus, sonst nichts:
|
||||
|
||||
```bash
|
||||
~/claude-projects/pool/bin/git-sync
|
||||
```
|
||||
|
||||
Das Skript liest selbst die `permissions.additionalDirectories` aus den Settings und
|
||||
synct jedes Repo (add, commit mit Timestamp-Message, pull --rebase, push). Kein force,
|
||||
kein Merge. Gib anschließend die Ausgabe des Skripts wieder.
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(git add:*)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(git push:*)",
|
||||
"Bash(git pull:*)",
|
||||
"Bash(git status:*)",
|
||||
"Bash(git diff:*)",
|
||||
"Bash(git -C:*)",
|
||||
"Bash(git mv:*)",
|
||||
"Bash(git check-ignore:*)",
|
||||
"Bash(cd:*)",
|
||||
"Bash(~/claude-projects/pool/bin/git-sync:*)"
|
||||
]
|
||||
},
|
||||
"model": "claude-fable-5[1m]",
|
||||
"enabledPlugins": {
|
||||
"frontend-design@claude-plugins-official": true,
|
||||
"swift-lsp@claude-plugins-official": true
|
||||
},
|
||||
"promptSuggestionEnabled": false,
|
||||
"awaySummaryEnabled": false,
|
||||
"tui": "fullscreen",
|
||||
"theme": "dark"
|
||||
}
|
||||
Reference in New Issue
Block a user