Skip to main content
Claurst uses a layered permission system that controls which tool calls can execute automatically and which require user approval. The system is deliberately conservative by default and supports several operational modes.

Permission modes

The active mode is set via --permission-mode on the CLI or the permission_mode field in settings.
The original TypeScript codebase contains an additional mode called YOLO that, despite its name, actually denies all non-read-only operations. The name is counterintuitive. In Claurst the equivalent of “allow everything” is BypassPermissions, not a mode called YOLO.
The auto permission mode referenced in the TypeScript source uses an ML-based transcript classifier to approve tool calls automatically. In Claurst this maps to AcceptEdits for tool execution purposes — the classifier infrastructure is not part of the clean-room implementation.

Permission categories

Every permission check is associated with one of these categories, which map directly to the tool types that trigger them:

How the AutoPermissionHandler works

AutoPermissionHandler is the non-interactive handler used in headless and scripted runs. It implements the PermissionHandler trait:
In the interactive TUI, the PermissionHandler surfaces a dialog to the user and waits for a y/n response before returning a decision.

Layered settings

Permission rules are stored in JSON settings files. The files are read in priority order — the highest-priority source wins:
1

Managed / enterprise settings (read-only)

Deployed by an organisation’s device management system. Users cannot override these rules. Equivalent to a policy layer.
2

Local project: .claude/settings.local.json

Machine-local settings for the current project. This file should be added to .gitignore. Suitable for developer-specific overrides that should not be shared with the team.
3

Project: .claude/settings.json

Shared project settings checked into source control. Suitable for project-wide permission rules that every contributor should use.
4

Global: ~/.claude/settings.json

User-level settings applied to all projects. Loaded by Settings::load() in cc-core.
The Settings struct in cc-core handles loading and saving:

Example settings.json permission rule configuration

Rules use permission rule syntax: ToolName(pattern). Patterns support glob matching against the tool’s input.

Risk classification

Every tool action is internally classified as LOW, MEDIUM, or HIGH risk. This classification drives the auto-permission decision and determines what information the permission explainer surfaces to the user.

Protected files

The following files resist automatic editing. Any tool call that would write to these paths requires explicit user approval, even in AcceptEdits mode:
  • .gitconfig
  • .bashrc
  • .zshrc
  • .mcp.json
  • .claude.json
These protections are enforced at the permission layer before the tool’s execute() method is called.

Path traversal prevention

Claurst’s memory path validation (validateMemoryPath()) and team memory write validation (validateTeamMemWritePath()) guard against path traversal attacks using several techniques: URL-encoded traversal detection — Patterns like %2e%2e%2f (URL-encoded ../) are detected and rejected before path resolution. Unicode normalization attacks — Fullwidth characters such as ../ normalise to ../ under NFC. Paths are normalised before comparison. Backslash injection — Backslashes in path keys are rejected regardless of platform. Absolute path rejection — Relative paths to the memory directory must not start with /. Two-pass symlink validationvalidateTeamMemWritePath() first uses path::resolve() to eliminate .. segments, then follows symlinks using realpathDeepestExisting() to verify that the real filesystem path is still inside the permitted directory. Symlink loops (ELOOP) and dangling symlinks are handled explicitly. Null byte rejection — Null bytes in path keys are rejected before any filesystem operation.