In the previous chapter, Polymorphic Hook Definitions, we learned how to differentiate between different types of actions (Commands, HTTP requests, Prompts).
Now, we will focus on the most common and powerful action: The Command.
This chapter explores Shell & System Integration. We will look at how to define the "Rules of Engagement" for interacting with the operating system, ensuring commands run safely and in the correct environment.
Imagine you want your AI assistant to start a local web server. You tell it to run npm start.
If you simply execute this command blindly, several things could go wrong:
ls vs dir).We need a way to wrap the raw command in a safety layer. We need to tell the system how to run the command, not just what to run.
Think of the BashCommandHook as a set of orders given to a soldier before a mission:
BashCommandHook
The BashCommandHook schema handles these details. Let's look at a concrete use case to understand the configuration options.
Goal: We want to start a server (npm start). We want it to run in the background so we can keep working, and we want to ensure it works on Windows.
Here is how we configure that using the schema:
{
"type": "command",
"command": "npm start",
"shell": "powershell",
"async": true,
"timeout": 10
}
Let's break down the key concepts used here.
shell)Operating systems speak different languages. Linux/macOS usually speak Bash (or Zsh). Windows usually speaks PowerShell.
If you write a script that uses grep (Linux search), it will fail on Windows standard command prompt.
"bash" (default) or "powershell".timeout)This is your safety switch. It defines the maximum time (in seconds) a command is allowed to run.
timeout kills it automatically so your application doesn't hang forever.async)By default, the system blocks. It waits for the command to finish before moving to the next task.
async: true: The system fires the command and immediately moves on. It returns the "Process ID" (PID) instead of the command output.asyncRewake)This is a special, advanced feature.
asyncRewake: true: Like async, it runs in the background. However, if the command crashes (specifically with exit code 2), it "wakes up" the AI model.How does the system enforce these rules? Let's visualize the flow when a command is executed.
shell to decide which executable to spawn (/bin/bash or pwsh.exe).
Let's look at the Zod definition in hooks.ts. We will break it into two parts for clarity.
This defines the mandatory fields for a command hook.
// hooks.ts (Snippet 1)
const BashCommandHookSchema = z.object({
// The discriminator (must be "command")
type: z.literal('command'),
// The actual script to run
command: z.string(),
// Which interpreter to use?
shell: z.enum(['bash', 'powershell', 'zsh', 'sh']).optional(),
});
Explanation:
type: Must be strictly 'command'.shell: Uses z.enum. This limits the user to only valid choices. You can't set shell to "minecraft".This adds the control layers we discussed.
// hooks.ts (Snippet 2)
// Safety limit in seconds
timeout: z.number().positive().optional(),
// Fire and forget?
async: z.boolean().optional(),
// Run in background, but report errors?
asyncRewake: z.boolean().optional(),
});
Explanation:
timeout: Must be a .positive() number. You can't have a timeout of -5 seconds.asyncRewake: This implies async. It's a boolean flag that alters the internal event listener logic to handle crash reports.In this chapter, we learned:
shell lets us choose between Bash and PowerShell to ensure compatibility.timeout prevents infinite loops and hanging processes.async allows us to run long tasks (like servers) without blocking the AI.We now have a safe way to run commands. But sometimes, running a command isn't enough. Sometimes, we need the AI to verify that the command actually did what it was supposed to do.
How do we add a "Brain" to our hooks?
Next Chapter: AI Verification & Interaction
Generated by Code IQ