Skip to main content
← Alle Beiträge

Blog / KI-Engineering

KI-Engineering

Claude Code einrichten: settings.json, Permissions, Sandbox

Wie Sie die Claude Code settings.json aufbauen: Geltungsbereiche, allow/ask/deny-Regeln, Pfadsyntax und Sandbox, mit einer realen Projektkonfiguration.

Die Claude Code settings.json entscheidet, was der Agent in Ihrem Projekt ohne Rückfrage darf, wo er nachfragen muss und was grundsätzlich ausgeschlossen ist. Ich zeige Ihnen, wie die Datei aufgebaut ist, welche Stolperstellen in der Regelsyntax stecken und wie ich die Konfiguration in einem eigenen Projekt gesetzt habe, in dem Claude Code gegen eine live WordPress-Website arbeitet.

Vier Dateien und eine feste Rangfolge

Claude Code liest Einstellungen aus mehreren JSON-Dateien. Welche Datei Sie wählen, bestimmt, für wen eine Einstellung gilt:

Ebene Datei Gilt für
User ~/.claude/settings.json Sie, in allen Projekten auf diesem Rechner
Projekt (geteilt) .claude/settings.json alle, die im Projekt arbeiten, sobald die Datei eingecheckt ist
Projekt (lokal) .claude/settings.local.json nur Sie, nur in diesem Projekt
Managed managed-settings.json, MDM oder Admin-Konsole alle Geräte einer Organisation

Wenn derselbe Schlüssel mehrfach gesetzt ist, gewinnt die höhere Ebene. Die Reihenfolge von oben nach unten lautet: Managed Settings, Kommandozeile (claude --settings), lokale Projektdatei, geteilte Projektdatei, User-Datei.

Für Listen gilt eine wichtige Ausnahme: permissions.allow und vergleichbare Arrays werden über alle Ebenen zusammengeführt statt ersetzt. Jede Datei kann also Regeln ergänzen, aber keine Regel einer anderen Datei entfernen. Das ist praktisch für Teams und zugleich der Grund, warum eine zu großzügige Regel in der User-Datei in jedem Projekt mitwirkt.

Eine Datei, die Claude Code selbst beschreibt, sollten Sie kennen: Wenn Sie bei einer Rückfrage „Yes, and don’t ask again“ wählen, landet die Freigabe als allow-Regel in .claude/settings.local.json. Wer sich über unerwartet viele Freigaben wundert, findet sie meist dort.

Die Projektdatei als Ausgangspunkt

So sieht eine gekürzte und verallgemeinerte Fassung der geteilten Projektdatei .claude/settings.json aus, die ich für die Pflege dieser Website verwende. Das Projekt enthält keinen eigenen Anwendungscode; Claude Code arbeitet dort vor allem über einen MCP-Server gegen eine WordPress-Installation. Entsprechend streng ist die Shell eingestellt.

.claude/settings.jsonJSON
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "sandbox": {
    "enabled": true,
    "failIfUnavailable": true,
    "allowUnsandboxedCommands": false,
    "filesystem": {
      "denyRead": ["~/.ssh", "~/.aws", "./.env", "./**/.env"],
      "denyWrite": ["~/.ssh", "~/.aws", "./.env", "./**/.env"]
    },
    "network": {
      "allowedDomains": ["registry.npmjs.org", "github.com"]
    }
  },
  "permissions": {
    "allow": ["Bash(git status *)", "Bash(git diff *)", "Bash(git log *)"],
    "ask": ["Bash(git commit *)", "Bash(npx *)"],
    "deny": [
      "Read(./.env)",
      "Read(./**/.env)",
      "Read(~/.ssh/**)",
      "Bash(git push *)",
      "Bash(git reset *)",
      "Bash(sudo *)"
    ]
  }
}

Kommentare gehören nicht in diese Datei: Die Dokumentation beschreibt die Settings-Dateien als striktes JSON, ein //-Kommentar oder ein Komma am Ende ist ein Syntaxfehler. Die $schema-Zeile verweist auf das veröffentlichte JSON-Schema und bringt Autovervollständigung und Validierung in Editoren wie VS Code. Das Schema kann neueren CLI-Versionen hinterherhinken, eine Warnung bei einem frisch dokumentierten Schlüssel ist also nicht automatisch ein Fehler.

Permissions in der Claude Code settings.json: allow, ask, deny

Jede Regel hat die Form Tool oder Tool(specifier). Bash allein trifft jeden Shell-Befehl, Bash(npm run build) genau diesen einen Befehl, WebFetch(domain:example.com) Abrufe dieser Domain.

Die Auswertungsreihenfolge

Claude Code prüft Regeln in fester Reihenfolge: erst deny, dann ask, dann allow. Der erste Treffer entscheidet, die Spezifität einer Regel spielt keine Rolle. Eine breite Sperre wie Bash(aws *) lässt sich deshalb nicht durch eine engere Freigabe wie Bash(aws s3 ls) aufweichen. In meiner Konfiguration heißt das: git commit fragt immer nach, auch wenn später jemand eine allgemeinere Git-Freigabe ergänzt.

Ein Detail für Teams: allow-Regeln aus der eingecheckten Projektdatei greifen erst, nachdem die jeweilige Person dem Ordner vertraut hat. deny– und ask-Regeln gelten sofort.

Wildcards in Bash-Regeln

Ein * steht für beliebigen Text, auch für Leerzeichen. Alles vor dem ersten * wird wörtlich verglichen. Daraus ergeben sich zwei Regeln, die ich anfangs falsch gemacht habe:

  • Das Leerzeichen vor dem * zählt. Bash(ls *) trifft ls -la, aber nicht lsof. Bash(ls*) trifft beides. Meine ursprüngliche Datei enthielt Bash(git status*) ohne Leerzeichen; funktional harmlos, aber unpräziser als nötig.
  • Den * hinter das Unterkommando setzen. Bash(git log *) erlaubt nur git log, Bash(git *) erlaubt jeden Git-Befehl, auch git push.

Verkettete Befehle mit &&, ||, ; oder | zerlegt Claude Code in Teilbefehle, und eine Freigabe muss jeden Teil einzeln abdecken. deny– und ask-Regeln greifen, sobald irgendein Teil passt.

Warum eine deny-Regel keine Sicherheitsgrenze ist

Bash-Regeln vergleichen den Befehlstext. Bash(git push *) stoppt git push origin main, aber nicht git -C . push origin main. Bash(rm *) stoppt nicht /bin/rm oder bash -c 'rm ...'. Die Dokumentation sagt das ausdrücklich und verweist für eine belastbare Grenze auf die Sandbox oder auf PreToolUse-Hooks.

Ich nutze deny-Regeln deshalb als Leitplanke für die üblichen Formulierungen und verlasse mich für echte Isolation auf die Sandbox.

Pfade in Read- und Edit-Regeln

Read– und Edit-Regeln verwenden gitignore-Syntax, mit vier Präfixen:

Muster Bedeutung
//pfad absoluter Pfad ab Dateisystem-Wurzel
~/pfad relativ zum Home-Verzeichnis
/pfad relativ zur Settings-Quelle (in Projektdateien: Arbeitsverzeichnis)
pfad oder ./pfad relativ zum aktuellen Verzeichnis

Der häufigste Fehler: Read(/Users/name/geheim) ist kein absoluter Pfad. Der einfache Schrägstrich verankert an der Settings-Quelle; absolut wird es erst mit //. In der User-Datei zeigt /secrets/** sogar auf ~/.claude/secrets/**.

Eine Read-Sperre gilt für die eingebauten Datei-Tools und für Shell-Befehle, die Claude Code als Dateizugriff erkennt, etwa cat, head oder tail. Sie greift nicht bei Befehlen, die Dateien lesen, ohne sie zu benennen, zum Beispiel grep -r muster .. Auch das spricht dafür, sensible Pfade zusätzlich in der Sandbox zu sperren.

Standardmodus festlegen

Mit permissions.defaultMode legen Sie fest, in welchem Modus eine Sitzung startet, etwa default, acceptEdits oder plan. Die Modi auto und bypassPermissions wirken nicht aus Projektdateien, sondern nur aus User- oder Managed Settings. Ein eingechecktes Repository kann Ihnen also nicht unbemerkt alle Rückfragen abschalten.

Die Sandbox: Grenzen auf Betriebssystemebene

Die Sandbox arbeitet anders als Permissions. Sie prüft keinen Befehlstext, sondern das Betriebssystem setzt Datei- und Netzwerkgrenzen für jeden Bash-, PowerShell- und Monitor-Befehl samt Kindprozessen durch. Auf macOS nutzt Claude Code dafür Seatbelt, auf Linux und WSL2 bubblewrap.

Was standardmäßig erlaubt ist

  • Schreiben: Arbeitsverzeichnis, zusätzlich freigegebene Verzeichnisse und ein temporäres Verzeichnis pro Nutzer.
  • Lesen: der gesamte Rechner, abgesehen von einigen gesperrten Bereichen. Das schließt Dateien wie ~/.aws/credentials und ~/.ssh/ ausdrücklich ein.
  • Netzwerk: keine Domain ist vorab freigegeben. Beim ersten Zugriff fragt Claude Code nach; mit sandbox.network.allowedDomains sparen Sie sich die Rückfrage. Domains aus WebFetch(domain:...)-Freigaben fließen ebenfalls in die Liste ein.

Der Lese-Standard ist der Grund, warum ich ~/.ssh und ~/.aws in sandbox.filesystem.denyRead eintrage. Alternativ bietet sandbox.credentials einen eigenen Block für Zugangsdaten-Dateien und Umgebungsvariablen.

Auto-Allow und die Hintertür schließen

Im Auto-Allow-Modus laufen Befehle, die in die Sandbox passen, ohne Rückfrage; explizite deny-Regeln und inhaltliche ask-Regeln wie Bash(git push *) gelten trotzdem. Den Modus wählen Sie über /sandbox.

Scheitert ein Befehl an der Sandbox, darf Claude ihn standardmäßig außerhalb erneut versuchen, dann mit normaler Rückfrage. "allowUnsandboxedCommands": false schaltet diese Möglichkeit ab. Und falls die Sandbox gar nicht starten kann, etwa wegen fehlender Pakete unter Linux, läuft Claude Code standardmäßig mit einer Warnung ungeschützt weiter. "failIfUnavailable": true macht daraus einen harten Fehler. In meinem Projekt sind beide Schalter gesetzt, weil dort Schreibzugriffe eine Produktivseite treffen.

Was die Sandbox nicht leistet

Die Sandbox betrifft nur Shell-Befehle. Die Datei-Tools Read, Edit und Write laufen über das Permission-System. Außerdem prüft der eingebaute Proxy Domains anhand des Hostnamens, ohne TLS-Verkehr zu inspizieren. Breite Freigaben wie github.com können deshalb Wege für Datenabfluss öffnen. github.com steht auch in meiner Liste; ich halte die Liste deshalb kurz und prüfe sie, wenn sich der Projektzweck ändert.

Einige Dateien sind innerhalb beschreibbarer Verzeichnisse trotzdem geschützt, darunter die .claude-Settings-Dateien und die Ordner .claude/skills, .claude/agents und .claude/hooks. Ein allowWrite-Eintrag hebt diesen Schutz nicht auf. Ein Befehl kann sich also nicht selbst neue Rechte eintragen.

Prüfen, was tatsächlich gilt

Nach jeder Änderung kontrolliere ich drei Stellen:

Claude-Code-SitzungTEXT
# Slash-Befehle innerhalb einer Claude-Code-Sitzung
/status        # Zeile "Setting sources": welche Dateien geladen wurden
/permissions   # alle Regeln mit der Datei, aus der sie stammen
/sandbox       # Reiter "Config": aufgelöste Sandbox-Einstellungen

/status zeigt, welche Dateien geladen wurden, aber nicht, welche Datei welchen Schlüssel geliefert hat. Abgelehnte Einträge listet claude doctor. Änderungen an permissions übernimmt Claude Code meist ohne Neustart.

BK

Bastian Kurz

Software Engineering · BK-Coding

Ich entwickle Backends, Schnittstellen und Webplattformen und setze KI-Agenten in meiner eigenen Entwicklung ein, auch für diese Website.

Entstanden mit KI-Unterstützung, fachlich geprüft und verantwortet von Bastian Kurz.

Mehr über mich →

Fragen oder Anmerkungen zu diesem Beitrag?

Weiterlesen

Weitere Beiträge

Alle Beiträge →