Permission Modes in Craft Agents: Safe, Ask, and Allow-All Explained
Craft Agents provide three permission modes—Safe (Explore), Ask (Ask to Edit), and Allow-All (Execute)—that enforce granular control over tool execution through the PermissionManager class in packages/shared/src/agent/core/permission-manager.ts.
The craft-ai-agents/craft-agents-oss repository implements a robust permission system that governs how AI agents interact with bash commands, file systems, and APIs. Understanding these permission modes is essential for deploying agents securely across exploratory, interactive, and automated workflows.
The Three Permission Modes: Safe, Ask, and Allow-All
Craft Agents map internal keys to user-facing canonical names in packages/shared/src/agent/mode-types.ts. Each mode determines whether the agent can write to the filesystem, execute arbitrary commands, or access external APIs without supervision.
Safe Mode (Explore)
Safe mode operates as a read-only sandbox where all write-type tools are blocked. When running in safe (internally keyed as 'safe', displayed as Explore), the agent cannot modify files, execute destructive bash commands, or push to git repositories. The system evaluates tool calls against a whitelist defined in the permissions JSON, rejecting any operation that could alter system state.
Ask Mode (Ask to Edit)
Ask mode enables full tool functionality while requiring user confirmation for high-risk operations. Internally keyed as 'ask' and displayed as Ask to Edit, this mode allows the agent to propose dangerous actions—such as rm, sudo, or git push—but surfaces these requests to the user for explicit approval before execution. The PermissionManager identifies dangerous commands using a hard-coded DANGEROUS_COMMANDS set in permission-manager.ts.
Allow-All Mode (Execute)
Allow-all mode grants unrestricted autonomous execution for fully automated workflows. Internally keyed as 'allow-all' and displayed as Execute, this mode bypasses all permission checks and dangerous-command detection. When allow-all is active, shouldAllowToolInMode returns allowed: true immediately, enabling the agent to run without prompts or whitelisting constraints.
How Permission Enforcement Works in Craft Agents
Permission enforcement follows a centralized evaluation pipeline that checks the current session mode before allowing tool execution.
Mode Evaluation and Policy Logic
The enforcement entry point is PermissionManager.evaluateToolCall(toolName, toolInput) in packages/shared/src/agent/core/permission-manager.ts. This method retrieves the active mode via getPermissionMode(sessionId) and delegates the policy decision to shouldAllowToolInMode(toolName, toolInput, mode, ...) located in packages/shared/src/agent/mode-manager.ts.
According to the source code in mode-manager.ts, the policy logic behaves as follows:
- In
allow-allmode: All tools returnallowed: trueimmediately. - In
askmode: Tools returnallowed: truebut may setrequiresPermission: truefor commands matching the dangerous-command list. - In
safemode: Tools are blocked unless they match a read-only whitelist defined inPermissionsConfigCache.
Dangerous Command Detection
The system maintains a hard-coded DANGEROUS_COMMANDS set in packages/shared/src/agent/core/permission-manager.ts that guarantees high-risk bash commands always require explicit user approval in ask mode. When PermissionManager.checkBashCommand() detects a dangerous pattern, it uses getBashRejectionReason and formatBashRejectionMessage to produce detailed error messages explaining why the command was blocked or requires confirmation.
Session-Scoped Whitelisting
Users can permanently approve specific commands or network domains for the duration of a session. The PermissionManager records these decisions in alwaysAllowedCommands and alwaysAllowedDomains, which bypass standard checks for subsequent invocations. Call permMgr.whitelistCommand('curl') to add a command to the session whitelist, or rely on the UI's "Always Allow" button to populate these sets automatically.
Programmatically Managing Permission Modes
Developers can interact with the permission system directly through the TypeScript API exposed in packages/shared/src/agent/mode-manager.ts and packages/shared/src/agent/core/permission-manager.ts.
Switching Session Modes
Change the active permission mode for a specific session using setPermissionMode:
import { setPermissionMode } from '@/shared/agent/mode-manager';
import { SESSION_ID } from './constants';
setPermissionMode(SESSION_ID, 'ask');
This updates the stored mode value, and the UI reflects the change via the displayName and shortName fields defined in PERMISSION_MODE_CONFIG in mode-types.ts.
Cycling Through Available Modes
To rotate through permission modes programmatically, use cyclePermissionMode which walks PERMISSION_MODE_ORDER = ['safe','ask','allow-all']:
import { cyclePermissionMode } from '@/shared/agent/mode-manager';
cyclePermissionMode(SESSION_ID); // Rotates: safe → ask → allow-all
Evaluating Tool Calls
Instantiate PermissionManager to evaluate specific tool calls against current permissions:
import { PermissionManager } from '@/shared/agent/core/permission-manager';
const permMgr = new PermissionManager({
sessionId: SESSION_ID,
workspaceId: WORKSPACE_ID,
workingDirectory: '/home/user/project',
plansFolderPath: '/home/user/project/.craft/plans',
});
const result = permMgr.evaluateToolCall('Bash', { command: 'git status' });
if (!result.allowed) {
console.error('Blocked:', result.reason);
} else if (result.requiresPermission) {
// Show a prompt to the user before proceeding
}
Whitelisting Commands
Add commands to the session whitelist to bypass future permission checks:
permMgr.whitelistCommand('curl'); // Always allow for subsequent curl invocations
Checking Bash Commands in Safe Mode
Validate specific bash commands before execution:
permMgr.setPermissionMode('safe');
const rejectMsg = permMgr.checkBashCommand('rm -rf /tmp');
if (rejectMsg) {
console.log('Rejected:', rejectMsg);
}
Summary
- Craft Agents implement three permission modes—
safe(Explore),ask(Ask to Edit), andallow-all(Execute)—defined inpackages/shared/src/agent/mode-types.ts. - Permission enforcement flows through
PermissionManager.evaluateToolCall()inpackages/shared/src/agent/core/permission-manager.ts, which delegates toshouldAllowToolInMode()inmode-manager.ts. - Safe mode blocks all write operations and restricts tools to a read-only whitelist.
- Ask mode allows all tools but requires user confirmation for commands listed in
DANGEROUS_COMMANDS. - Allow-all mode bypasses all checks, enabling fully autonomous agent execution.
- Session whitelisting via
alwaysAllowedCommandsandalwaysAllowedDomainspersists user approvals for the duration of the session.
Frequently Asked Questions
How do I programmatically change the permission mode in Craft Agents?
Import setPermissionMode from packages/shared/src/agent/mode-manager.ts and call it with the session ID and desired mode key ('safe', 'ask', or 'allow-all'). The function updates the session state and triggers UI updates through the PERMISSION_MODE_CONFIG mapping.
What is the difference between Safe mode and Ask mode in Craft Agents?
Safe mode operates as a read-only sandbox where write operations are blocked entirely, while Ask mode permits write operations but requires explicit user confirmation for commands identified as dangerous in the DANGEROUS_COMMANDS set. Safe mode never prompts the user; Ask mode may prompt depending on the tool being invoked.
Where is the dangerous command list defined in the Craft Agents source code?
The DANGEROUS_COMMANDS set is defined in packages/shared/src/agent/core/permission-manager.ts. This hard-coded list ensures that commands like rm, sudo, and git push always trigger permission requests in Ask mode, regardless of any custom whitelist configurations.
Can I whitelist specific commands for an entire session in Craft Agents?
Yes. The PermissionManager class provides whitelistCommand() and whitelistDomain() methods that add entries to alwaysAllowedCommands and alwaysAllowedDomains respectively. These session-scoped sets bypass standard permission checks for subsequent tool calls, effectively creating a temporary "always allow" policy for approved commands.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →