AWS Builder Center
I Automated Half My Dev Workflow with Kiro Hooks. Here's How You Can Too.

I Automated Half My Dev Workflow with Kiro Hooks. Here's How You Can Too.

A practical guide to Kiro hooks, event-driven automations that run shell commands or AI prompts when you save a file, create a component, or finish a task. Includes 10+ ready-to-use JSON configs for auto-linting, test generation, security scanning, i18n sync, and more. Copy, paste into .kiro/hooks/, and let your IDE handle the repetitive work.

Every developer has that recurring moment: you save a file, then manually run the linter. You create a new component, then open a terminal to scaffold a test file. You finish a coding session, then realize you forgot to check for hardcoded secrets.
What if your IDE just... did all of that for you?
Kiro hooks are event-driven automations that fire when specific things happen in your coding session: a file is saved, a tool is invoked, or the agent finishes a task. You define the trigger and the action (a shell command or an AI prompt), and Kiro handles execution in the background.
I've been using hooks for a few weeks now. They fundamentally changed how I work. Here are the patterns I use daily, with complete JSON files you can drop into your project right now.

How Hooks Work

A hook is a JSON file inside .kiro/hooks/ at your project root. Each one has three parts:
  • A trigger — the event that fires the hook (file saved, file created, agent stopped, tool used, etc.)
  • A matcher — an optional regex pattern to filter which files or tools activate the hook
  • An action — either a command (shell command) or agent (AI prompt injected into context)
When the trigger event fires, Kiro checks the matcher. If it matches (or no matcher is specified), the action executes. Command actions run a shell command in your project root. Agent actions inject a prompt into the current conversation, steering the AI's behavior.
No plugin system to learn, no extension API to implement. Just a JSON file committed to your repo. Hooks activate automatically when your session starts.
Here's the minimal anatomy:
1
2
3
4
5
6
7
8
9
{
"version": "v1",
"hooks": [{
"name": "My hook",
"trigger": "PostFileSave",
"matcher": "\\.ts$",
"action": { "type": "command", "command": "echo 'file saved'" }
}]
}

Part 1: Shell Command Hooks (Fast, Predictable)

Shell command hooks run a terminal command when the event fires. They're fast, deterministic, and perfect for tooling you already have.

Hook 1: Auto-Lint on Save

The simplest hook I have, and the one that saves me the most keystrokes. Every time I save a TypeScript file, ESLint runs with auto-fix.
1
2
3
4
5
6
7
8
9
{
"version": "v1",
"hooks": [{
"name": "Lint on save",
"trigger": "PostFileSave",
"matcher": "\\.(ts|tsx)$",
"action": { "type": "command", "command": "npx eslint --fix ${FILEPATH}" }
}]
}
File: .kiro/hooks/lint-on-save.json
The hook receives the saved file path via the FILEPATH environment variable. You can also receive full session context as JSON on STDIN for more complex scripts.

Hook 2: Run Tests After Task Completion

When Kiro finishes executing a spec task (e.g., implementing a feature from your spec), this hook runs your test suite automatically:
1
2
3
4
5
6
7
8
{
"version": "v1",
"hooks": [{
"name": "Run tests after task",
"trigger": "PostTaskExec",
"action": { "type": "command", "command": "npm run test -- --reporter=verbose" }
}]
}
File: .kiro/hooks/test-after-task.json
If tests fail, the output goes back to the agent's context so it can fix the issue immediately.

Hook 3: Format Code on Every Write

Instead of configuring format-on-save in your editor settings, let a hook handle it consistently:
1
2
3
4
5
6
7
8
9
{
"version": "v1",
"hooks": [{
"name": "Prettier on save",
"trigger": "PostFileSave",
"matcher": "\\.(ts|tsx|js|jsx|css|json)$",
"action": { "type": "command", "command": "npx prettier --write ${FILEPATH}" }
}]
}
File: .kiro/hooks/format-on-save.json

Hook 4: Log All Prompts for Auditing

If you work in a regulated environment or just want a history of what you asked the agent, this hook logs every user prompt to a file:
1
2
3
4
5
6
7
8
9
10
11
{
"version": "v1",
"hooks": [{
"name": "Log user prompts",
"trigger": "UserPromptSubmit",
"action": {
"type": "command",
"command": "echo \"$(date -u +%Y-%m-%dT%H:%M:%SZ) | ${USER_PROMPT}\" >> .kiro/prompt-log.txt"
}
}]
}
File: .kiro/hooks/audit-log.json
The USER_PROMPT environment variable contains the submitted prompt text.

Hook 5: Type-Check on Save

For TypeScript projects with strict mode, catch type errors the moment you save:
1
2
3
4
5
6
7
8
9
{
"version": "v1",
"hooks": [{
"name": "Type check on save",
"trigger": "PostFileSave",
"matcher": "\\.(ts|tsx)$",
"action": { "type": "command", "command": "npx tsc --noEmit --pretty" }
}]
}
File: .kiro/hooks/typecheck-on-save.json

Part 2: Agent Prompt Hooks (AI-Powered Automation)

Agent hooks inject a prompt into the conversation context. This is where things get powerful: you can have the AI generate code, review changes, create documentation, or enforce standards automatically.

Hook 6: Auto-Generate Tests When You Create a File

When I create a new source file, Kiro's agent writes the corresponding test file:
1
2
3
4
5
6
7
8
9
10
11
12
{
"version": "v1",
"hooks": [{
"name": "Generate test for new file",
"trigger": "PostFileCreate",
"matcher": "src/.*\\.(ts|tsx)$",
"action": {
"type": "agent",
"prompt": "A new source file was just created. Generate a corresponding unit test file in the tests/ directory that mirrors the source file's path structure. Include tests for all exported functions and classes. Use vitest syntax. Follow the existing test patterns in this project. Run the tests to make sure they pass."
}
}]
}
File: .kiro/hooks/auto-test.json
The more specific your prompt, the better the output. Mention your test framework, directory structure, and any conventions.

Hook 7: Security Scanner on Session Stop

This fires after the agent finishes responding. It reviews all changed files for leaked secrets:
1
2
3
4
5
6
7
8
9
10
11
{
"version": "v1",
"hooks": [{
"name": "Security scan on stop",
"trigger": "Stop",
"action": {
"type": "agent",
"prompt": "Review all files changed in this session for security issues:\n1. Hardcoded API keys, tokens, or credentials\n2. Private keys or certificates\n3. Database connection strings with passwords\n4. Internal URLs or IP addresses\n5. Secrets in configuration files\n\nFor each issue found, report: file path, line number, the risk, and a recommended fix using environment variables or a secrets manager."
}
}]
}
File: .kiro/hooks/security-scan.json

Hook 8: Keep i18n Files in Sync

When I update the English locale file, this hook flags every other language file that needs updating:
1
2
3
4
5
6
7
8
9
10
11
12
{
"version": "v1",
"hooks": [{
"name": "Sync i18n on English update",
"trigger": "PostFileSave",
"matcher": "locales/en.*\\.json$",
"action": {
"type": "agent",
"prompt": "The English locale file was just updated. Do the following:\n1. Identify which string keys were added or modified\n2. Check all other language files under locales/ for these keys\n3. For missing keys, add them with a \"TODO_TRANSLATE\" marker value\n4. For modified source strings, mark existing translations as \"NEEDS_REVIEW\"\n5. Print a summary of changes made across all language files"
}
}]
}
File: .kiro/hooks/i18n-sync.json

Hook 9: Auto-Update Documentation

When API route files change, keep the README in sync:
1
2
3
4
5
6
7
8
9
10
11
12
{
"version": "v1",
"hooks": [{
"name": "Update API docs on route change",
"trigger": "PostFileSave",
"matcher": "src/routes/.*\\.(ts|js)$",
"action": {
"type": "agent",
"prompt": "A route file was just modified. Update the API section in docs/API.md to reflect the current state of all route files in src/routes/. Include: HTTP method, path, request body schema, response schema, and a curl example for each endpoint. Keep the format consistent with existing entries."
}
}]
}
File: .kiro/hooks/api-docs-sync.json

Hook 10: Enforce Coding Standards Before Tool Execution

PreToolUse hooks fire before the agent executes a tool. They can provide additional context, or even block the action entirely.
1
2
3
4
5
6
7
8
9
10
11
12
{
"version": "v1",
"hooks": [{
"name": "Enforce standards on writes",
"trigger": "PreToolUse",
"matcher": "write",
"action": {
"type": "agent",
"prompt": "Before writing this file, verify:\n1. No functions exceed 30 lines\n2. All exported functions have JSDoc comments\n3. No magic numbers (extract to named constants)\n4. Error handling is present for async operations\n5. No console.log statements (use the project logger)\n\nIf any rule is violated, fix it before writing."
}
}]
}
File: .kiro/hooks/enforce-standards.json

Part 3: Advanced Patterns

Block Dangerous Operations

PreToolUse hooks can actually block actions. For shell commands, exit code 2 means "block this tool call." The agent sees the block and tries a different approach:
1
2
3
4
5
6
7
8
9
10
11
12
{
"version": "v1",
"hooks": [{
"name": "Block deletion of critical files",
"trigger": "PreToolUse",
"matcher": "write",
"action": {
"type": "command",
"command": "echo '{\"tool_input\": \"'$TOOL_INPUT'\"}' | python3 -c \"import sys,json; data=json.load(sys.stdin); sys.exit(2 if any(p in data.get('tool_input','') for p in ['migrations/', '.github/workflows/', 'package.json']) else 0)\""
}
}]
}
File: .kiro/hooks/block-critical-deletes.json
Exit code 0 = proceed. Exit code 2 = block.

Confirmation Prompts on Stop

You can add interactive confirmation before a Stop hook runs. This is useful for hooks that push changes or submit data:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"version": "v1",
"hooks": [{
"name": "Deploy to staging",
"trigger": "Stop",
"action": { "type": "command", "command": "./scripts/deploy-staging.sh" },
"confirm": {
"question": "Deploy this session's changes to staging?",
"options": [
{ "id": "deploy", "label": "Yes, deploy", "run": true },
{ "id": "skip", "label": "Not yet", "run": false }
]
}
}]
}
File: .kiro/hooks/deploy-confirm.json
The user sees a dialog before the command runs.

Chain Multiple Hooks on the Same Trigger

You can define multiple hooks in a single file, or spread them across files. They all activate independently:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"version": "v1",
"hooks": [
{
"name": "Lint TypeScript",
"trigger": "PostFileSave",
"matcher": "\\.(ts|tsx)$",
"action": { "type": "command", "command": "npx eslint --fix ${FILEPATH}" }
},
{
"name": "Update test coverage",
"trigger": "PostFileSave",
"matcher": "src/.*\\.(ts|tsx)$",
"action": {
"type": "agent",
"prompt": "Check if the modified functions have corresponding test coverage. If not, update the test file."
}
}
]
}
File: .kiro/hooks/save-pipeline.json

Part 4: Hooks + MCP (External Integrations)

Hooks become even more powerful when combined with MCP (Model Context Protocol) servers. Your agent hooks can reference MCP tools to interact with external systems:
  • Figma MCP — validate that HTML/CSS changes respect your design system
  • Database MCP — sync seed data from sample files in the project
  • Jira/Linear MCP — update ticket status after a spec task completes
  • Slack MCP — send notifications when the agent finishes a task
Example: validate CSS against a Figma design system on every save:
1
2
3
4
5
6
7
8
9
10
11
12
{
"version": "v1",
"hooks": [{
"name": "Validate against Figma design",
"trigger": "PostFileSave",
"matcher": "\\.(css|html|tsx)$",
"action": {
"type": "agent",
"prompt": "A UI file was just saved. Use the Figma MCP to fetch the design tokens for this project. Compare the colors, spacing, font sizes, and border radii used in the saved file against the Figma design system. Report any deviations and suggest fixes."
}
}]
}
File: .kiro/hooks/figma-validation.json

What I Learned After Weeks of Using Hooks

Start with shell commands. They're predictable, fast, and easy to debug. Reserve agent prompts for tasks that genuinely need AI reasoning: test generation, code review, documentation writing, refactoring suggestions.
Be specific in your agent prompts. "Review code" gives mediocre results. "Review changed files for hardcoded credentials, list file path and line number, suggest using environment variables" gives great results. Include numbered steps.
Commit your hooks to version control. They live in .kiro/hooks/, which means your whole team gets them on git pull. It's like sharing a linter config, but for AI-powered automation.
Use matchers aggressively. A hook that fires on every single file save will slow you down. A hook that fires only on src/**/*.ts is surgical and fast.
The PreToolUse trigger is a safety net, not a wall. Use it to add guardrails (enforce standards, log actions, validate inputs) rather than to prevent the agent from working.
Combine command + agent hooks for the same trigger. Use a command hook to run the linter (fast, deterministic), and an agent hook to review logic (slower, but intelligent). They fire independently.
Use timeout for long-running commands. If a command might hang, set "timeout": 30 to cap execution time. Default is 60 seconds.
Disable hooks without deleting them. Set "enabled": false to temporarily turn off a hook while keeping the config.

Quick Reference: All Available Triggers

  • PostFileSave — after a file is saved
  • PostFileCreate — after a new file is created
  • PostFileDelete — after a file is deleted
  • PreToolUse — before the agent uses a tool (can block with exit code 2)
  • PostToolUse — after a tool executes
  • UserPromptSubmit — when a message is sent to the agent (can block)
  • SessionStart — when a new session begins
  • Stop — when the agent finishes responding
  • PreTaskExec — before a spec task starts (can block)
  • PostTaskExec — after a spec task completes

Get Started in 60 Seconds

  1. Create a .kiro/hooks/ directory in your project root
  2. Copy any of the JSON files above into it
  3. Start a Kiro session
That's it. No registration, no setup wizard, no config file to wire up. Hooks activate automatically.
Or use Kiro's built-in hook creator: open the Hooks panel, click "+", describe what you want in natural language, and Kiro generates the JSON for you.
If you want to go further: official docs  and the examples gallery .
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article