In the previous chapter, File Operations Subsystem, we learned how to safely manage changes to your files. We acted like a Records Department, carefully checking every document edit.
But editing a file is relatively safe compared to the raw power of a terminal. A single shell command like rm -rf / can wipe an entire machine in seconds.
This brings us to Shell Command Governance.
Think of your operating system as a construction site.
The Shell Command Governance system acts as the Safety Officer on the site.
rm, mkfs).Why not just treat commands like text strings?
npm test fifty times a day. We need a system that can suggest: "Always allow npm test?"
The Scenario:
The AI wants to run rm -rf ./temp_cache.
The Governance Process:
rm as a Destructive Command.
Conversely, if the command was npm run build, the system might offer: "Allow, and don't ask again for npm run *".
This system is built on three pillars:
Before showing the dialog, we parse the command. If it contains words like rm, mv, or dd, we prepare a warning message.
This logic looks at the command and figures out a "wildcard" rule.
npm run buildnpm run *Terminal commands can be cryptic. The formatter ensures lists of files or long arguments are displayed neatly.
The main entry point for this logic is the BashPermissionRequest component. It uses the Unified Dialog Interface but adds specific logic for shells.
Here is a simplified view of how the component decides what to show:
// BashPermissionRequest.tsx (Simplified)
export function BashPermissionRequest({ toolUseConfirm }) {
// 1. Parse the input to get the command string
const { command } = BashTool.inputSchema.parse(toolUseConfirm.input);
// 2. Run the Safety Check
const destructiveWarning = getDestructiveCommandWarning(command);
// 3. Render the Dialog with warnings (if any)
return (
<PermissionDialog
title="Bash command"
// If dangerous, show a warning color
color={destructiveWarning ? "orange" : "blue"}
>
<Text>{command}</Text>
{/* Show the warning text if it exists */}
{destructiveWarning && (
<Text color="warning">{destructiveWarning}</Text>
)}
</PermissionDialog>
);
}
getDestructiveCommandWarning: This function analyzes the string. If it sees rm, it returns a string like "This command will delete files."Let's trace a "Dangerous" command request.
Let's look deeper into how we generate the "Always Allow" options. This logic lives in bashToolUseOptions.tsx.
We want to give the user smart choices. We don't just want "Yes". We want "Yes, and learn this pattern."
// bashToolUseOptions.tsx (Simplified)
export function bashToolUseOptions({ suggestions, editablePrefix }) {
const options = [];
// 1. Standard "Yes"
options.push({ label: 'Yes', value: 'yes' });
// 2. Smart "Always Allow" Logic
if (editablePrefix) {
// If we detected a pattern (like "npm run:*"), offer it
options.push({
label: 'Yes, and donβt ask again for',
value: 'yes-prefix-edited',
initialValue: editablePrefix, // e.g., "npm run:*"
type: 'input'
});
}
// 3. Standard "No"
options.push({ label: 'No', value: 'no' });
return options;
}
When a command affects multiple files or is very long, we use helpers in shellPermissionHelpers.tsx to make it readable.
// shellPermissionHelpers.tsx
function commandListDisplay(commands: string[]) {
// If there is only one command, make it bold
if (commands.length === 1) {
return <Text bold>{commands[0]}</Text>;
}
// If there are many, join them nicely
return (
<Text>
<Text bold>{commands[0]}</Text> and {commands.length - 1} more
</Text>
);
}
This helper ensures that if the AI tries to run 50 commands at once, the Permission Dialog doesn't explode with text. It keeps the Unified Dialog Interface clean.
Once the user selects an option (like "Always Allow"), we capture that decision in the Interactive Decision Prompt.
If the user selects yes-prefix-edited, the system:
npm run:*).
Next time the AI runs npm run test, the Central Request Dispatcher won't even ask the userβit will see the rule and auto-approve it.
Shell Command Governance is the security checkpoint of our system. It combines:
It ensures that the "Heavy Machinery" of the terminal is used safely and efficiently.
But waitβhow does the user know why a permission was requested? Or if something goes wrong, how do we find out why a rule didn't match?
In the next chapter, we will explore Permission Explainer & Debugging, the tools we use to inspect the decision-making process itself.
Next Chapter: Permission Explainer & Debugging
Generated by Code IQ