Claude Code automatisch ausführen: Headless mit launchd
Claude Code ohne Chatfenster: mit claude -p, festen Werkzeugrechten und launchd jeden Morgen einen Projektbericht erstellen und aufs Handy schicken.
Von Nathan Base
Claude Code kennen die meisten als Agenten, mit dem sie im Terminal chatten. Weniger bekannt ist, dass er auch ohne Chatfenster arbeitet: Du gibst ihm eine Aufgabe als Kommandozeilen-Argument, er erledigt sie, gibt das Ergebnis aus und beendet sich. Damit wird Claude Code zu einem Baustein in Skripten und lässt sich zeitgesteuert starten.
So entsteht zum Beispiel ein Bericht, der jeden Morgen auf Deinem Handy liegt: Was hat sich gestern im Projekt getan, gibt es neue Sicherheitswarnungen bei den Abhängigkeiten, welche TODOs sind liegen geblieben. Diese Anleitung baut genau das auf dem Mac, mit claude -p, eng gefassten Rechten und launchd als Zeitsteuerung. Grundlage ist die offizielle Dokumentation zum Headless-Modus.
Voraussetzungen
- Claude Code ist auf dem Mac installiert und funktioniert. Wie Du ihn einrichtest, steht in Anleitung: Claude Code auf dem Mac installieren & nutzen.
- Ein Claude-Abo oder ein API-Schlüssel aus der Claude Console.
- Für die Benachrichtigung aufs Handy optional ein ntfy-Server, wie ihn Push-Benachrichtigungen selbst hosten mit ntfy beschreibt.
So funktioniert der Headless-Modus
Der Schalter -p steht für „print“. Claude Code bearbeitet die Aufgabe, gibt die Antwort aus und beendet sich:
claude -p "Fasse die Datei README.md in drei Sätzen zusammen"Wenn Du das im Ordner eines Projekts ausführst, liest Claude die Datei und gibt die Zusammenfassung im Terminal aus. Im Headless-Modus gibt es niemanden, der Rückfragen zu Berechtigungen beantworten kann. Deshalb legst Du vorher fest, welche Werkzeuge Claude ohne Nachfrage nutzen darf:
claude -p "Zeig mir die letzten fünf Commits mit kurzer Einordnung" --allowedTools "Bash(git log *)"--allowedTools folgt der Syntax der Berechtigungsregeln. Bash(git log *) erlaubt jeden Befehl, der mit git log beginnt, und sonst nichts. Laut Doku ist das Leerzeichen vor dem Sternchen wichtig, ohne es würden auch Befehle wie git logsomething passen.
Schritt 1: Einen Token für Skripte erzeugen
Für automatische Läufe ohne Browser-Anmeldung erzeugst Du einen langlebigen Token, der an Dein Abo gebunden ist:
claude setup-tokenDer Befehl öffnet eine Anmeldung im Browser und gibt danach einen Token im Terminal aus, ohne ihn zu speichern. Leg ihn im macOS-Schlüsselbund ab, damit er nicht im Klartext in einem Skript steht:
security add-generic-password -a "$USER" -s claude-code-token -wDer Befehl fragt nach dem Passwort, hier fügst Du den Token ein. Claude Code liest ihn später aus der Umgebungsvariablen CLAUDE_CODE_OAUTH_TOKEN.
Nutzt Du statt eines Abos die API, legst Du stattdessen Deinen API-Schlüssel ab und verwendest später die Variable ANTHROPIC_API_KEY. Dann kannst Du zusätzlich den Schalter --bare setzen, den die Doku für Skripte empfiehlt. Er überspringt Hooks, Plugins und Projektdateien wie CLAUDE.md und startet dadurch schneller. Mit einem Abo-Token funktioniert --bare nicht, weil dieser Modus keine Anmeldedaten aus dem Abo liest.
Schritt 2: Das Skript für den Morgenbericht
Lege das Skript an:
mkdir -p ~/bin ~/Berichte
nano ~/bin/claude-morgen.shFüge diesen Inhalt ein und passe den Projektpfad an:
#!/bin/zsh
set -e
export CLAUDE_CODE_OAUTH_TOKEN=$(security find-generic-password -s claude-code-token -w)
cd ~/Projekte/website
BERICHT=~/Berichte/$(date +%F).md
~/.local/bin/claude -p "Erstelle einen kurzen Morgenbericht auf Deutsch für dieses Projekt. \
1. Fasse die Commits der letzten 24 Stunden zusammen. \
2. Prüfe mit npm audit, ob es Sicherheitswarnungen gibt, und nenne nur die mit hoher Dringlichkeit. \
3. Liste TODO-Kommentare im Ordner src auf, die älter als eine Woche sind. \
Antworte in höchstens 15 Zeilen." \
--allowedTools "Read,Grep,Glob,Bash(git log *),Bash(git blame *),Bash(npm audit *)" \
--permission-mode dontAsk \
--max-turns 20 \
--output-format text > "$BERICHT"
curl -s -H "Title: Morgenbericht" -H "Authorization: Bearer tk_DEIN_TOKEN" \
-T "$BERICHT" -H "Filename: bericht.md" https://ntfy.example.com/claudeWas die einzelnen Teile tun:
- Die erste
export-Zeile holt den Token aus dem Schlüsselbund. --allowedToolserlaubt nur Lesen, Suchen und drei genau umrissene Befehle. Claude kann damit nichts verändern, nichts installieren und nichts löschen.--permission-mode dontAsklehnt alles ab, was nicht ausdrücklich erlaubt ist, statt auf eine Antwort zu warten, die nie kommt.--max-turns 20begrenzt die Zahl der Arbeitsschritte. Ohne Grenze kann sich ein Agent in Ausnahmefällen festbeißen und Kontingent verbrauchen.- Die Ausgabe landet als Markdown-Datei mit Datum im Ordner
Berichte, undcurlschickt sie als Anhang an ntfy.
~/.local/bin/claude ist der Pfad, den der native Installer von Claude Code verwendet. Prüfe Deinen mit which claude und trag ihn vollständig ein, denn launchd kennt Deinen normalen Suchpfad nicht. Mach das Skript ausführbar und probiere es einmal von Hand aus:
chmod +x ~/bin/claude-morgen.sh
~/bin/claude-morgen.shNach ein bis zwei Minuten liegt der Bericht im Ordner und auf dem Handy.
Schritt 3: Jeden Morgen automatisch starten
Am Mac übernimmt launchd die Zeitsteuerung. Es hat gegenüber cron den Vorteil, dass es Läufe nachholt, die der Mac im Ruhezustand verpasst hat. Die vollständige Anleitung mit allen Details steht in Hintergrund-Jobs am Mac mit launchd statt cron. Hier die Kurzfassung: Leg die Datei ~/Library/LaunchAgents/de.deinname.claude-morgen.plist an, mit diesem Inhalt und Deinem Benutzernamen statt deinname:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>de.deinname.claude-morgen</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>/Users/deinname/bin/claude-morgen.sh</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>7</integer>
<key>Minute</key>
<integer>30</integer>
</dict>
<key>StandardErrorPath</key>
<string>/Users/deinname/Library/Logs/claude-morgen.log</string>
</dict>
</plist>Lade den Job:
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/de.deinname.claude-morgen.plistAb jetzt läuft der Bericht jeden Morgen um 7:30 Uhr, oder direkt nach dem Aufwachen, falls der Mac geschlafen hat.
Weitere Ideen für automatische Läufe
Das Muster lässt sich auf viele Aufgaben übertragen. Wichtig ist, dass sie lesen und berichten, aber nichts unbeaufsichtigt verändern:
- Logdateien zusammenfassen: Fehler der letzten Nacht aus einem Server-Log herausziehen und in drei Sätzen erklären.
- Abhängigkeiten prüfen: neue Hauptversionen wichtiger Pakete finden und die Breaking Changes aus den Changelogs zusammenfassen.
- Dokumentation aktuell halten: prüfen, ob die README noch zu den Befehlen in
package.jsonpasst, und Abweichungen auflisten.
Sicherheit: worauf Du achten musst
Ein Agent, der unbeaufsichtigt läuft, braucht engere Grenzen als einer, dem Du zuschaust:
- Nur lesende Werkzeuge erlauben.
Edit,Writeund ein pauschalesBashgehören nicht in einen automatischen Lauf. Soll Claude doch etwas ändern, lass ihn einen Vorschlag schreiben, den Du morgens prüfst. - Auf fremde Inhalte achten. Liest der Agent Dateien oder Webseiten, die andere geschrieben haben, könnten darin Anweisungen versteckt sein. Mit eng gefassten Werkzeugrechten bleibt der mögliche Schaden klein.
- Kosten im Blick behalten. Jeder Lauf verbraucht Kontingent Deines Abos oder kostet bei der API Geld.
--max-turnsund kurze Aufgaben halten das im Rahmen.
Typische Fehler
Im Log steht, dass keine Anmeldung gefunden wurde. Der Token kommt nicht an. Prüfe mit security find-generic-password -s claude-code-token -w, ob er im Schlüsselbund liegt. Läuft der Job, bevor Du Dich angemeldet hast, ist der Schlüsselbund noch gesperrt.
Der Bericht ist leer oder endet mitten im Satz. Claude ist an --max-turns gestoßen oder ein Werkzeug wurde abgelehnt. Starte das Skript von Hand mit --output-format json statt text, dann siehst Du in der Ausgabe, wo es hakte.
command not found: claude. launchd kennt den Pfad nicht. Trag den vollständigen Pfad aus which claude ins Skript ein.
Fazit
Mit claude -p, eng gesetzten Werkzeugrechten und launchd wird Claude Code vom Chatpartner zum stillen Helfer, der jeden Morgen die Routinearbeit erledigt, bevor Du den Rechner aufklappst. Fang mit einem rein lesenden Bericht an, beobachte ein paar Tage, was herauskommt, und erweitere die Aufgaben dann Schritt für Schritt.
Weiterlesen.
-
AIAnleitung: Claude Code auf dem Mac installieren & nutzen
Claude Code auf dem Mac installieren, anmelden und sinnvoll nutzen: die wichtigsten Konzepte und drei Alltags-Workflows jenseits vom Programmieren.
Nathan Base -
Apple MacHintergrund-Jobs am Mac mit launchd statt cron
Skripte am Mac per Zeitplan oder beim Anstecken eines Laufwerks starten: LaunchAgent mit launchd anlegen, testen und Fehler finden.
Nathan Base -
Web & CodePush-Benachrichtigungen selbst hosten mit ntfy
ntfy mit Docker und Caddy selbst hosten, absichern und Meldungen von Skripten, Uptime Kuma und Home Assistant aufs iPhone und Android-Handy schicken.
Nathan Base -
AIClaude Code oder Codex CLI: welcher Coding-Agent?
Claude Code und Codex CLI im Vergleich: Preise, Limits, Stärken laut Community, Sicherheitsmodi und eine klare Empfehlung, wann Du welchen Agenten nimmst.
Nathan Base -
AIMCP-Server in Claude Code und Codex einrichten
MCP-Server in Claude Code und Codex CLI hinzufügen, API-Schlüssel sicher übergeben und die typischen Fehler wie Timeouts und fehlende Anmeldung beheben.
Nathan Base -
AIOllama auf dem Mac: lokale KI mit MLX nutzen
Ollama auf dem Mac: lokale Modelle nach Arbeitsspeicher wählen und mit OpenCode, Claude Code oder Codex, VS Code, Docker und GitHub programmieren.
Nathan Base