Kiro Product
IDE
Feature Description
IDE hooks (.kiro/hooks/*.kiro.hook) with preToolUse event and runCommand action receive no information about the tool being invoked — no stdin data, no environment variables with tool arguments. The hook cannot see what the agent is about to do, making it impossible to build lightweight, LLM-free command gates.
Kiro CLI hooks already solve this by passing a JSON payload via stdin containing tool_name and tool_input (documented at https://kiro.dev/docs/cli/hooks/). IDE hooks should receive the same payload.
Use Case
Without tool context, preToolUse + runCommand can only check static workspace state (does a file exist? is a setting configured?). It cannot make decisions based on what the agent is about to execute. This eliminates the most valuable use cases for pre-execution hooks:
Security & compliance gates (shell commands)
- Block destructive commands:
rm -rf /, DROP TABLE, kubectl delete namespace production
- Prevent credential leaks: block commands containing tokens, passwords, or API keys in arguments
- Enforce toolchain policies: block
pip install in uv-managed projects, block npm install -g in CI-controlled environments
File write protection (write tools)
- Prevent writes to protected paths: lock files, CI configs, production configs
- Block modifications to generated files that should only be changed by their generator
- Enforce code ownership: only allow writes to files matching team ownership patterns
MCP tool auditing
- Log all database queries before execution (inspect SQL in
tool_input)
- Block destructive MCP operations:
DELETE, UPDATE without WHERE clause
- Rate-limit expensive API calls by inspecting the endpoint in tool arguments
Read access control
- Prevent reading sensitive files:
.env, private keys, credential stores
- Audit which files the agent accesses during a session
All of these require the hook to see the tool arguments. Currently, the only way to inspect tool arguments in IDE hooks is via askAgent (agent prompt action), which triggers a full LLM call — expensive, slow, and consumes credits. A runCommand hook with stdin access would be instant, free, and deterministic.
Additional Context
A preToolUse hook with runCommand on shell tools:
- Receives empty stdin (verified with
select.select + 2s timeout)
USER_PROMPT env var is {} (empty JSON object)
- No
TOOL_*, HOOK_*, or KIRO_* environment variables are set
Test hook used:
#!/usr/bin/env python3
import sys, os, select, json
result = {}
readable, _, _ = select.select([sys.stdin], [], [], 2)
if readable:
result["stdin"] = sys.stdin.read()
else:
result["stdin"] = "NO DATA"
result["USER_PROMPT"] = os.environ.get("USER_PROMPT", "NOT SET")
with open(".hook_test.txt", "w") as f:
json.dump(result, f, indent=2)
Result: {"stdin": "NO DATA", "USER_PROMPT": "{}"}
Expected Behavior (matches CLI)
Per the CLI docs, preToolUse hooks receive JSON via stdin:
{
"hook_event_name": "preToolUse",
"cwd": "/current/working/directory",
"tool_name": "execute_bash",
"tool_input": {
"command": "pip install requests"
}
}
This works correctly in kiro-cli chat — verified with the same workspace. The IDE should pass the same payload.
Similarly, postToolUse hooks in the CLI receive tool_response in addition to tool_name and tool_input. This would enable post-execution auditing and validation in the IDE.
Reproduction Steps
- Create
.kiro/hooks/stdin-test.kiro.hook:
{
"enabled": true,
"name": "Stdin test",
"version": "1",
"when": { "type": "preToolUse", "toolTypes": ["shell"] },
"then": {
"type": "runCommand",
"command": "python3 -c \"import sys,select; r,_,_=select.select([sys.stdin],[],[],2); data=sys.stdin.read() if r else 'NO STDIN'; open('.hook_test.txt','w').write(data)\"",
"timeout": 10
}
}
- Have the agent run any shell command
- Read
.hook_test.txt — it contains NO STDIN
- Compare: define the same hook in
.kiro/agents/test.json and run via kiro-cli chat --agent test — stdin contains the full JSON payload
Environment
- Kiro IDE version: 0.11
- OS: macOS (Apple Silicon)
- Kiro CLI: hooks work correctly with stdin JSON in the same workspace
Kiro Product
IDE
Feature Description
IDE hooks (
.kiro/hooks/*.kiro.hook) withpreToolUseevent andrunCommandaction receive no information about the tool being invoked — no stdin data, no environment variables with tool arguments. The hook cannot see what the agent is about to do, making it impossible to build lightweight, LLM-free command gates.Kiro CLI hooks already solve this by passing a JSON payload via stdin containing
tool_nameandtool_input(documented at https://kiro.dev/docs/cli/hooks/). IDE hooks should receive the same payload.Use Case
Without tool context,
preToolUse+runCommandcan only check static workspace state (does a file exist? is a setting configured?). It cannot make decisions based on what the agent is about to execute. This eliminates the most valuable use cases for pre-execution hooks:Security & compliance gates (shell commands)
rm -rf /,DROP TABLE,kubectl delete namespace productionpip installin uv-managed projects, blocknpm install -gin CI-controlled environmentsFile write protection (write tools)
MCP tool auditing
tool_input)DELETE,UPDATEwithoutWHEREclauseRead access control
.env, private keys, credential storesAll of these require the hook to see the tool arguments. Currently, the only way to inspect tool arguments in IDE hooks is via
askAgent(agent prompt action), which triggers a full LLM call — expensive, slow, and consumes credits. ArunCommandhook with stdin access would be instant, free, and deterministic.Additional Context
A
preToolUsehook withrunCommandonshelltools:select.select+ 2s timeout)USER_PROMPTenv var is{}(empty JSON object)TOOL_*,HOOK_*, orKIRO_*environment variables are setTest hook used:
Result:
{"stdin": "NO DATA", "USER_PROMPT": "{}"}Expected Behavior (matches CLI)
Per the CLI docs,
preToolUsehooks receive JSON via stdin:{ "hook_event_name": "preToolUse", "cwd": "/current/working/directory", "tool_name": "execute_bash", "tool_input": { "command": "pip install requests" } }This works correctly in
kiro-cli chat— verified with the same workspace. The IDE should pass the same payload.Similarly,
postToolUsehooks in the CLI receivetool_responsein addition totool_nameandtool_input. This would enable post-execution auditing and validation in the IDE.Reproduction Steps
.kiro/hooks/stdin-test.kiro.hook:{ "enabled": true, "name": "Stdin test", "version": "1", "when": { "type": "preToolUse", "toolTypes": ["shell"] }, "then": { "type": "runCommand", "command": "python3 -c \"import sys,select; r,_,_=select.select([sys.stdin],[],[],2); data=sys.stdin.read() if r else 'NO STDIN'; open('.hook_test.txt','w').write(data)\"", "timeout": 10 } }.hook_test.txt— it containsNO STDIN.kiro/agents/test.jsonand run viakiro-cli chat --agent test— stdin contains the full JSON payloadEnvironment