BashTool: The Tool Where the Safety Tag Matters Most

Bash is the tool with the most complex permission checking, because a single command can do almost anything. src/tools/BashTool/BashTool.tsx implements it.

Timeout and Interruption Strategy

// src/tools/BashTool/BashTool.tsx
const PROGRESS_THRESHOLD_MS = 2000      // Show progress indicator after 2 seconds
const ASSISTANT_BLOCKING_BUDGET_MS = 15_000  // Max 15 seconds of blocking in main agent

Two constants control UX:

  • If a command runs for more than 2 seconds, the UI shows a progress indicator so the user knows what it's waiting for
  • In the main agent thread, commands exceeding 15 seconds are automatically moved to background tasks (see Section A: Core Engine — AgentTool background task routing)

Command Classification (read / search / list)

// src/tools/BashTool/BashTool.tsx
const BASH_SEARCH_COMMANDS = new Set(['find', 'grep', 'rg', 'ag', ...])
const BASH_READ_COMMANDS = new Set(['cat', 'head', 'tail', 'jq', 'awk', ...])
const BASH_LIST_COMMANDS = new Set(['ls', 'tree', 'du'])
const BASH_SEMANTIC_NEUTRAL_COMMANDS = new Set(['echo', 'printf', 'true', 'false', ':'])

This classification determines whether a command is "collapsed" in the UI — search, read, and list operations carry low-value information and are collapsed by default; users click to expand. This reduces interface noise.

Pipeline commands (cat file | grep pattern) are only collapsed entirely when all subcommands belong to the same type. If any subcommand involves a write operation, the entire command is not collapsed.

Permission Checking

BashTool's permission check (src/tools/BashTool/bashPermissions.ts) isn't simple string matching — it first does syntax parsing:

// src/tools/BashTool/bashPermissions.ts
import { parseForSecurity } from '../../utils/bash/ast.js'
import { classifyBashCommand } from '../../utils/permissions/bashClassifier.js'

parseForSecurity parses the command string into an AST (Abstract Syntax Tree), then checks each node against the rules. This prevents bypass tricks like hiding real commands behind variables, heredocs, or subshells.