Multi-Machine-Sync: Alle Claude-Konfigurationen ins Repo aufnehmen

- Agents (test-runner, security-audit, n8n-architect) ins Repo verschoben
- dotfiles/ hinzugefügt: CLAUDE.md, settings.json, statusline-command.sh
- bootstrap.sh erstellt: Einrichtung per git clone + einem Befehl
- SETUP.md auf 2-Schritt-Setup vereinfacht

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-19 11:14:42 +02:00
co-authored by Claude Sonnet 4.6
parent 7590dc48fa
commit 3b72368674
8 changed files with 388 additions and 50 deletions
+48
View File
@@ -0,0 +1,48 @@
# Globale CLAUDE.md
## Sprache
Alle Texte, Kommentare und Kommunikation auf Deutsch. Technische Begriffe und Code-Bezeichner bleiben im Original.
## Entwicklungsprinzipien
- **Single Responsibility:** Jede Datei, jede Funktion hat genau eine Aufgabe
- **Keine toten Code-Pfade:** Unbenutzte Imports, Variablen, Funktionen sofort entfernen
- **Aussagekraeftige Namen:** Sprechende Bezeichner statt `handleClick`, `process`
- **Keine Magic Numbers:** Konstanten mit Namen versehen
- **DRY mit Augenmass:** Shared Utilities nur bei echtem Mehrfachgebrauch
- **Fail Fast:** Fehlende/ungueltige Konfiguration muss beim Start eine Exception werfen
- **Keine generischen `try/except`:** Spezifische Exceptions fangen
- **Logging statt print:** `logger` verwenden
- **Testpflicht:** Kein Code ohne zugehoerigen Test
- **Security by Default:** Input-Validierung, Auth-Checks, sichere Defaults. Sicherheitskritische Pfade durch Tests absichern
- **String-Eingaben trimmen:** Alle String-Felder beim Anlegen/Update in Services/Schemas trimmen (leading/trailing Whitespace entfernen). Leerstrings werden zu `None`, wenn das Feld optional ist. Verhindert Sortier-/Vergleichs-/Suchfehler durch unsichtbare Zeichen
- **Kleine Funktionen, keine Kommentare fuer Offensichtliches**
## Code-Konventionen
- **Backend:** Ruff, Type Hints, async, Pydantic-Schemas, Lifespan statt `on_event`
- **Frontend:** `<script setup>`, ESLint+Prettier, Mobile First, `defineEmits` camelCase / Template kebab-case
- **DB:** Jede Schema-Aenderung braucht eine Alembic-Migration
- **Architektur:** `api/``services/` + `models/`, nie umgekehrt. HTTPException nur in `api/`. Eager-Loading in der API-Schicht. Frontend: Props down, Events up
- **Docker Compose:** Jeder Service: `TZ=Europe/Berlin`, Logging 5 MB (`json-file`, `max-size: 5m`, `max-file: 3`), Watchtower-Label default deaktiviert
## Agenten-Workflow
Nach jeder Story automatisch ausfuehren: **test-runner****security-audit**. Erst wenn beide ohne kritische Befunde durchlaufen, gilt die Story als abgeschlossen.
## Pull Requests
PRs muessen jedes Akzeptanzkriterium einzeln als Checkbox auflisten und bestaetigen, wie es verifiziert wurde. Review-Feedback als separater Commit (nicht amenden).
## Git-Workflow
Niemals direkt auf `main` committen. Alle Aenderungen ueber Feature-Branches und PRs.
## Gitea-Integration
Instanz: `https://gitea.troeger-net.org`. Bot-User `claude-code`, Token: `GITEA_TOKEN=$(secret-tool lookup user claude-code token gitea)`. Bot hat nur Collaborator-Rechte.
## MCP
Bei Frameworks/Bibliotheken immer Context-7-Dokumentation abrufen (resolve-library-id / query-docs).
+50
View File
@@ -0,0 +1,50 @@
{
"permissions": {
"allow": [
"Bash(npm run build:*)",
"Bash(grep:*)",
"Bash(xargs:*)",
"WebSearch",
"Bash(npm install)",
"Bash(curl:*)",
"Bash(ls:*)",
"Bash(python3:*)"
],
"defaultMode": "default"
},
"statusLine": {
"type": "command",
"command": "bash ~/.claude/statusline-command.sh"
},
"enabledPlugins": {
"typescript-lsp@claude-plugins-official": true,
"frontend-design@claude-plugins-official": true,
"context7@claude-plugins-official": true,
"code-review@claude-plugins-official": true,
"code-simplifier@claude-plugins-official": true
},
"language": "German",
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "bash /mnt/projekte/claude-workflow/hooks/auto-format.sh"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "bash /mnt/projekte/claude-workflow/hooks/verify-on-stop.sh"
}
]
}
]
}
}
+54
View File
@@ -0,0 +1,54 @@
#!/bin/bash
# Read JSON input from stdin
input=$(cat)
# Extract data from JSON
current_dir=$(echo "$input" | jq -r '.workspace.current_dir // empty')
model=$(echo "$input" | jq -r '.model.display_name // "?"')
total_input=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0')
total_output=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0')
context_size=$(echo "$input" | jq -r '.context_window.context_window_size // 200000')
used_percent=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d'.' -f1)
cost_usd=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
# Calculate total tokens in K format
total_tokens=$(( (total_input + total_output) / 1000 ))
# Format cost (show cents if < $1, otherwise dollars)
# Use LC_NUMERIC=C to ensure decimal point handling
cost_cents=$(LC_NUMERIC=C awk "BEGIN {printf \"%.0f\", $cost_usd * 100}")
if [ "$cost_cents" -lt 100 ]; then
cost_formatted="${cost_cents}¢"
else
cost_dollars=$(LC_NUMERIC=C awk "BEGIN {printf \"%.2f\", $cost_usd}")
cost_formatted="\$${cost_dollars}"
fi
# Get user and hostname
user=$(whoami)
host=$(hostname -s)
# Get git branch if in a git repository
git_branch=""
if [ -n "$current_dir" ] && [ -d "$current_dir/.git" ] || git -C "$current_dir" rev-parse --git-dir > /dev/null 2>&1; then
branch=$(git -C "$current_dir" branch --show-current 2>/dev/null)
[ -n "$branch" ] && git_branch=" \033[33m($branch)\033[00m"
fi
# Check for debian_chroot
chroot_prefix=""
if [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
chroot_prefix="(${debian_chroot})"
fi
# Format context limit in K
context_limit_k=$(( context_size / 1000 ))
# Output status line
# Format: user@host:dir (branch) | Model | Tokens/Limit | Cost
printf "${chroot_prefix}\033[32m${user}@${host}\033[00m:\033[34m${current_dir}\033[00m${git_branch}"
printf " \033[90m|\033[00m \033[36m${model}\033[00m"
printf " \033[90m|\033[00m \033[35m${total_tokens}K/${context_limit_k}K (${used_percent}%%)\033[00m"
printf " \033[90m|\033[00m \033[33m${cost_formatted}\033[00m"