In the previous Git Integration chapter, we gave claudeCode the ability to understand the history of your project. It can look around and see what files have changed.
But seeing isn't enough. To be a true coding assistant, the AI needs to act. It needs to run tests, install packages, start servers, and move files.
Enter the BashTool.
The BashTool is the application's ability to type into your terminal.
If the FileEditTool is the "Text Editor," the BashTool is the "Command Line." It allows the AI to execute shell commands just like a human developer would.
Imagine you ask: "Run the tests and fix any errors."
npm test.
Without BashTool, the AI is just a text generator. With it, the AI becomes an operator.
When you open a terminal, you are in a "Session." If you type cd src, you stay in the src folder for the next command.
BashTool tries to maintain this continuity so the AI doesn't get lost.
Computers speak in two streams:
The BashTool captures both so the AI knows exactly what happened.
Every command finishes with a number.
The AI uses this number to quickly decide if its plan worked or failed.
Like the other tools, this is designed for the AI to use. However, understanding the input helps you understand the AI's behavior.
The AI sends a simple object containing the command string.
{
"command": "npm install lodash"
}
The AI can run multiple things at once using standard shell syntax.
{
"command": "cd src && ls -la"
}
Explanation: This moves into the src folder AND lists the files immediately. This is efficient because it saves a "turn" in the conversation.
When the AI requests a command, we don't just blindly run it. We have to spawn a "Sub-process."
npm test.Here is the flow:
The implementation involves two parts: the Execution Logic (running the code) and the Permission UI (asking the user).
Before running anything, we mount a React component to ask the user. This uses the Ink UI Framework.
// components/permissions/BashPermissionRequest.tsx (Simplified)
export function BashPermissionRequest({ command, onDone }) {
// Show the user what command is about to run
return (
<PermissionDialog title="Bash command">
<Text color="yellow">{command}</Text>
<Text>Do you want to proceed?</Text>
{/* Handled by user input keys (y/n) */}
<Select
options={['yes', 'no']}
onSelect={(val) => val === 'yes' ? onDone() : exit()}
/>
</PermissionDialog>
);
}
Explanation: This component intercepts the flow. The tool cannot proceed until onDone() is called, which only happens if the user selects 'yes'.
Once approved, we use Node.js utilities to run the command.
// tools/BashTool/runCommand.ts (Simplified)
import { spawn } from 'child_process';
function runShellCommand(commandString) {
// Spawn the command in a shell
const child = spawn(commandString, { shell: true });
let output = '';
// Listen for data chunks
child.stdout.on('data', (data) => {
output += data; // Collect the text
});
// Return a promise that resolves when the command finishes
return new Promise((resolve) => {
child.on('close', (code) => {
resolve({ output, exitCode: code });
});
});
}
Explanation: We use spawn with { shell: true }. We accumulate all the text into output. When the process emits close, we finish the job.
What if the user runs a server that never stops?
The BashTool includes a timeout mechanism. If a command runs too long without output, or if the user presses Ctrl+C, the tool sends a "kill signal" to the process to stop it cleanly.
The BashTool is powerful, but power brings danger.
rm -rf / by accident. The next chapter explains how we analyze commands before running them.Exit Code from the BashTool to decide if the AI completed its task successfully.
You have learned that the BashTool is the "hands" of claudeCode in the terminal. It spawns processes, captures output, and reports back to the AI. It transforms the AI from a passive advisor into an active participant in your development workflow.
However, giving an AI access to your terminal requires strict supervision. How do we ensure it acts safely?
Next Chapter: Shell Safety Checks
Generated by Code IQ