AWS Builder Center

Sometimes You Gotta Run Before You Can Walk: My Kiro Customization Playbook

Kiro stopped being an AI assistant and became a co-pilot that knows how I work. This post walks through the three customization mechanisms I use daily — steering files, hooks, and specs — with concrete examples from 4 months of iteration. If you've been treating your IDE's AI as a text box, there's a lot more available to you.

Every few weeks, a new AI-powered IDE shows up on my radar promising to change everything. Most of them don't stick. Kiro did. Somewhere around month two, I noticed something neat: I had stopped explaining myself to it. It already knew my default customer vertical. It already refused to suggest Streamlit (great for quick notebooks, not what I reach for on production-grade demos). It was nagging me about deadlines before I had opened my calendar.
That is the moment an IDE stops being a tool and starts feeling like a teammate. This post is about how I got there, what a newcomer should build first, and a few patterns that are genuinely fun once you see them work.
What I learned in four months: the customization system is easier to extend than I thought. After reading Thariq Rahman's essay on HTML as an agent output format , I had a short conversation with Kiro about whether to adopt his approach in my workflow. By the end of it, Kiro had drafted a new steering file scoped to the two artifact types where the idea actually fit, with a review date built in so I'd evaluate it honestly a week later. I didn't author a policy. I had a conversation, made a scoped decision, and the system captured it. That's the shape of what becomes possible once the three pillars are in place. (I walk through this story in more detail later in the post.)

First, What Even Is Kiro?

If you've opened this post and are squinting at "steering files" and "hooks" wondering what you walked into: Kiro is an AI-powered IDE built around the idea that the AI should know how you work, not just what you typed in the last message. Think VS Code, but with three built-in mechanisms for teaching the assistant your preferences permanently instead of pasting the same instructions into every chat.
Those three mechanisms are the whole game.

The Three Pillars of Kiro Customization

  1. Steering files (.kiro/steering/*.md) are persistent rules and context that get injected into every interaction. Think of them as your personal style guide, coding standards, and "here's what I always forget" notes rolled into one.
  2. Hooks (.kiro/hooks/*.kiro.hook) are event-driven automations that fire on IDE events. Save a file, finish a task, open the app in the morning, whatever you want. Each hook either runs a shell command or sends a prompt back to the agent.
  3. Specs (.kiro/specs/*) are structured feature development flows: requirements, then design, then tasks, all in markdown files the agent references while implementing.
I use all three aggressively. My workspace currently has 22 steering files, 12 hooks, and 24 specs. That sounds like a lot. It wasn't on day one. It grew the way any good filing system grows, one "oh right, I should remember this" at a time.

Steering Files: Teaching Kiro Who You Are

Steering files are the heart of this whole setup. They're just markdown documents in .kiro/steering/. You write rules, conventions, and context. Kiro reads them before answering anything. If you've ever wished your IDE would "just remember" that you prefer one framework over another, this is the fix.
There are three flavors:

Always-On Rules (The Non-Negotiables)

These load every single time. My behavior.md is the shortest and most impactful file in my workspace:
1
2
3
4
Respond to all prompts like Jarvis, Tony Stark's personal assistant.
Address me as Ma'am.
Default vertical: High-Tech and Semiconductors.
UI framework: Flask, never Streamlit.
That is it. Four lines. But those four lines mean I never have to type "please don't use Streamlit" or "assume my default vertical" again. Every response already knows.
My tech.md is the file I'm proudest of. It's a living knowledge base of SDK gotchas, model IDs, deployment patterns, and every hard-won lesson I've picked up. Real example: early on, a test suite started failing in CI but passing locally. The culprit was comparing naïve datetime.utcnow() values against timezone-aware datetimes from the database layer. I added a three-line entry to tech.md: "always use datetime.now(timezone.utc) for new timestamps, never datetime.utcnow()." Next time Kiro wrote date-handling code, it got it right the first try.
That's the payoff: you only suffer once.

Conditional Steering (Smart Context Loading)

Some rules should only apply in specific situations. Kiro supports this via YAML frontmatter. My testing.md file:
1
2
3
4
---
inclusion: fileMatch
fileMatchPattern: 'test_*,*_test.py,conftest.py,tests/*'
---
That header tells Kiro: "only load this file's contents when the user is editing something that matches these patterns." So my pytest conventions, Hypothesis patterns, and fixture rules get injected when I'm writing tests, and they stay out of the way when I'm writing a blog post. Context windows aren't free. This pattern respects that.

Manual Steering (On-Demand Expertise)

The last flavor waits in the closet until you call it. You tag it with inclusion: manual and pull it in with # in chat:
1
2
3
---
inclusion: manual
---
Files like paper-quality.md and spec-template.md live here. My spec-template.md alone is 300+ lines of skeleton structure for requirements, design, and tasks files. Every new spec starts by pulling it in with #spec-template, which means the Research Foundation section, property-based test design, and acceptance criteria format are consistent across 20+ projects. Without it, I'd reinvent the same structure every time and forget at least one section.

Hooks: Event-Driven Automation

If steering files are the "what," hooks are the "when." They fire on IDE events and either run a shell command or send a new prompt to the agent. They are also the most genuinely fun part of the setup, because they're where Kiro goes from reactive to proactive.
Here are seven of my favorites (out of twelve total):

1. Prompt Context Injector (promptSubmit)

Every single message I send gets a tiny context reminder injected before the agent sees it:
1
2
3
4
5
6
7
{
"when": { "type": "promptSubmit" },
"then": {
"type": "askAgent",
"prompt": "Quick context check: Use global inference profiles, default to semiconductors, no root files, Flask for UI, SSM for config."
}
}
Think of it as .editorconfig for AI. It's the belt-and-suspenders companion to always-on steering: even if the agent somehow forgets a rule, this hook reminds it before every message. It costs almost nothing in tokens and catches the most common drift.

2. Blindspot Audit on Major Writes (postToolUse → fsWrite)

After any substantive markdown file is created (research papers, blog posts, specs), Kiro automatically runs a 4-quadrant blindspot analysis:
  • Unexplained Feature: anything that doesn't fit the story?
  • Convenient Absence: what check or section is missing?
  • Unasked Question: what's more interesting but unexplored?
  • Unexploited Strength: what's stronger than claimed but undersold?
This idea is borrowed from Scott Cunningham's MixtapeTools methodology. It catches gaps I'd miss in the flow of writing. Imagine having a peer reviewer who never gets tired of your drafts. That's this hook. This very blog post got audited twice while I was writing it.

3. New File Validator (fileCreated)

Every new file gets sanity-checked against my workspace conventions:
  • Is it in the workspace root? (Flag it. Nothing lives in root except README and dotfiles.)
  • Is the naming correct? (snake_case for Python, camelCase for TypeScript, kebab-case for folders.)
  • Is it in a proper project folder?
  • Does it have a module docstring?
90% of the time this hook does absolutely nothing. That's correct. It's a doorman, not a concierge.

4. Post-Task Test Runner (postTaskExecution)

When a spec task completes, Kiro automatically runs pytest -v --tb=short -x if tests exist in the project. No more "oops, I broke something three tasks ago and didn't notice until the demo." The test suite gets the last word before the task is marked done.

5. Agent Stop Cleanup (agentStop)

When Kiro finishes a task, it cleans up after itself:
  • Stops any background processes it started (no more phantom Flask servers on port 5000)
  • Identifies and removes scratch files that match patterns like test_*, scratch_*, debug_*
  • Leaves organized test suites alone
Over a long session, scratch files accumulate like coffee cups on a desk. This hook does the dishes.

6. Referee 2 Reminder (postTaskExecution)

This one is adapted from Scott Cunningham's MixtapeTools playbook. The idea: the agent that built something cannot objectively audit it. So after any spec task completes, Kiro nudges me to open a fresh context window and run an independent review. Two sentences, Jarvis tone, every time. I ignore it maybe 30% of the time. The 70% it catches something has paid for itself.

7. Daily AI Intel Report (userTriggered)

This is my favorite hook, and the one I'd recommend as a template for anyone building closed-loop automation. One button in the IDE fires the whole thing. The script pulls from:
  • RSS feeds from curated AI blogs
  • arXiv new submissions in cs.AI, cs.LG, cs.AR
  • HuggingFace daily papers
  • AWS launch announcements
Then Kiro fires up to 10 parallel web searches across hand-picked sources (Karpathy's blog, Andrew Ng's The Batch, Anthropic Research, DeepMind, AWS ML Blog, NVIDIA AI, Latent Space podcast), rotated based on what moved since the last run. It writes everything into a single dated markdown report with sections for visionary highlights, podcast queue, hands-on tutorials, and a reading schedule for the week.
The trick is a tiny .last_run file that tracks when the hook last executed. The hook skips any source that had no new content since that timestamp, so parallel searches stay lean. Target wall-clock: under three minutes from click to report. It replaces about an hour of browser-tab hoarding every morning, and it's the clearest example of closed-loop behavior in my workspace. Yesterday's output informs today's run.

Credit Where It's Due

Several of these hooks are adapted from patterns I picked up in the broader Claude Code ecosystem. If you want to see production-grade examples before building your own, awesome-claude-code  and disler/claude-code-hooks-mastery  are two excellent starting points. The Referee 2 pattern comes from Scott Cunningham's MixtapeTools  methodology, which I'd recommend reading in full if you take research or spec quality seriously.
Here's the meta-trick: you don't need to translate these by hand. Point Kiro at a Claude Code skill or hook JSON and ask it to port the pattern. It will read the original, understand the intent, and produce an equivalent Kiro hook or steering file in your own workspace conventions. That is how I ported the blindspot audit in about four minutes. The three pillars of Kiro customization include Kiro itself as an active participant, which means any pattern that works in another AI-IDE is one conversation away from working in yours.

MCP Servers: Specialized Knowledge on Tap

MCP (Model Context Protocol) servers are small programs that expose tools and documentation to Kiro. Mine live in .kiro/settings/mcp.json:
ServerPurposeAuto-Approved Tools
AWS DocumentationSearch and read AWS docssearch_documentation
Bedrock AgentCoreAgentCore-specific docssearch_agentcore_docs, fetch_agentcore_doc
Strands AgentsStrands SDK documentationsearch_docs, fetch_doc
The autoApprove list is the quiet superpower. Read-only documentation lookups happen without a confirmation prompt. Zero friction for the most common task of my day (looking up an AWS service parameter I half-remember).
My context-management.md steering file also defines a dynamic install and uninstall pattern: MCP servers that aren't needed permanently get installed for a task and removed after. This keeps context lean and prevents the slow bloat that kills long sessions.

Specs: Structured Feature Development

A spec is three markdown files in a folder, and it's the closest thing to "AI pair programming done right" that I've found.
1
2
3
4
.kiro/specs/PROJECT_NAME/
requirements.md # What and why (functional + non-functional)
design.md # How (HLD + LLD + property test design)
tasks.md # Implementation steps with acceptance criteria
The rules of the house:
  • Requirements always start with a Research Foundation section citing papers, standards, and AWS docs. This forces me to ground the work in evidence before I start building castles in the air.
  • Design always includes a Property-Based Test Design section. You think about failure modes during design, not at 11pm the night before a demo.
  • Tasks always end with deliverable tasks (research paper, blog post, architecture diagram, demo script). The work isn't done when the code compiles. It's done when a teammate could read the story.
  • Every task has concrete acceptance criteria. "Pytest passes all 18 role×tool combinations" is a criterion. "RBAC works" is a wish.
The spec workflow is enforced by behavior.md: always Requirements, then Design, then Tasks. No shortcuts, no "let's just prototype." I have 24 specs right now covering everything from chip-design-intelligence-agent to yield-management-model-migration. Every one of them exists because Requirements → Design → Tasks caught an architectural mistake before it became an expensive refactor.

What Shipped in May 2026: Specs Got Faster and Smarter

The Kiro team just shipped three improvements to spec-driven development (full blog here ) that changed how I work with specs:
1. Parallel task execution. When I click "Run all Tasks," Kiro now builds a dependency graph and runs independent tasks concurrently. Tasks touching the same files serialize; setup runs first; tests run after the code they validate. Everything else runs in waves. My last large spec finished noticeably faster than the sequential version would have, and I did not configure anything to make that happen.
2. Quick Plan mode. For well-understood features, I can skip the three-phase approval flow. Kiro scans my workspace first to detect language and frameworks, asks targeted clarifying questions (scope, constraints, ambiguity, implementation forks), then generates requirements, design, and tasks in one pass. I land on the task list ready to build. Artifacts are still created and editable, so I can review them after the fact. If I change tasks, only tasks regenerate. If I change scope, the full pipeline reruns. It is not a shortcut that skips structure. It is the same structure, generated faster.
3. Analyze Requirements. This one is my favorite. After requirements.md is generated, a single click runs a Neurosymbolic AI analysis (LLM plus automated reasoning) that catches three classes of issue a human review will miss: genuine ambiguity ("remove the record", hard delete or soft delete?), logical contradictions between requirements, and silent gaps where expected behavior is undefined. It surfaces each finding as a two-option question with a proposed fix. On my first try, it caught a contradiction I had missed on a read-through.
I updated my spec-template.md steering file to make "Analyze Requirements" a required checkpoint after every requirements.md generation. It takes seconds. It saves hours.

Why Specs Matter: A Karpathy Endorsement

For anyone still on the fence about specs, Andrej Karpathy made the case better than I could at YC AI Startup School in 2025. In the Q&A of his "Software Is Changing (Again) " talk (around the 20:32 mark ), he said:
"People have to be in charge of this spec, this plan... there's something more general here where you have to work with your agent to design a spec that is very detailed... you're in charge of the oversight and the top-level categories, but the agents are doing a lot of the under-the-hood."
That is the entire thesis of spec-driven development. A capable agent still needs a flight plan: a shared agreement on the destination, the constraints, and the waypoints along the way. Kiro treats specs as a first-class feature, with the tooling to match, and that is a big part of why I stuck with it. Karpathy's call for humans to stay in charge of "this spec, this plan" is something Kiro bakes into its workflow by default.

The Maintenance Question

At this point someone usually asks: "Twenty-two steering files? Are you running a small compliance department?"
Here's the secret: I don't maintain them in dedicated sessions. My learning.md steering file defines a continuous learning policy. Before marking any implementation task complete, Kiro asks: "Did I learn anything that isn't already in the steering files?" If yes, add it now, not later. There's a routing table that maps the type of learning to the right file.
That means steering files grow during the work, not between the work. Take security-policies.md: it started as a set of zero-trust patterns for a single enterprise-agentic-identity demo, then earned its way into the default for every customer-facing project I build. Identity propagation end-to-end, independent validation at every agent hop, RBAC enforcement at the data layer rather than the API layer. Each rule landed in the file after a specific demo where its absence would have produced a bad outcome. Every entry has a "Reason" line explaining the failure mode it prevents. Six months from now I will not remember why the spec says "every downstream agent must independently validate the IdentityContext, never trust the upstream caller." The reason line is insurance against my future self deleting a rule that's protecting me.

What About the Cost?

Fair question, and the one most newcomers ask: "If every message fires a promptSubmit hook and every save triggers a blindspot audit, doesn't this get expensive fast?"
Honestly, less than you'd think. The promptSubmit injector is maybe 40 tokens per message, a rounding error against the context of the actual task. Always-on steering files like behavior.md stay short by design (mine is four lines). Conditional steering only loads when the fileMatch pattern hits, so testing.md doesn't cost me anything when I'm editing a blog post. The heavier hooks (blindspot audits, Referee 2 reminders) only fire on substantive writes or task completion, not on every keystroke.
The real cost driver in any AI-IDE workflow is long, unfocused sessions with bloated context. Kiro's conditional inclusion patterns actively fight that: you only pay for the context that's relevant to what you're doing right now. My rough sense after four months is that the customization overhead adds maybe 5-10% to baseline token usage, and it saves me far more than that in rework avoided, because the agent gets the answer right the first time instead of iterating through three wrong versions.
If you want to be careful, start with the promptSubmit injector and one conditional steering file, measure for a week, and expand from there. The compounding benefit shows up quickly.

Best Practices (What I'd Tell Past Me)

1. Start with behavior, not automation

Your first steering file should define tone, defaults, and non-negotiables. Everything else builds on that foundation. Mine started with three lines (Jarvis tone, my default customer vertical, no Streamlit) and four months later those three lines still carry more weight than anything I've added since.

2. Hooks should be invisible when things are right

The best hooks fire silently when everything's fine and only speak up on violations. My new-file-validator does nothing 90% of the time. That's correct. You want guardrails that stay quiet.

3. Use conditional inclusion aggressively

Don't load testing conventions when you're writing a blog post. Don't load PDF generation rules when you're debugging a Lambda. fileMatch patterns keep context focused and keep you from paying for tokens you'll never use.

4. The "prompt context injector" pattern is underrated

A lightweight promptSubmit hook that reminds the agent of your top five rules on every message costs almost nothing and prevents the most common drift. If you build nothing else from this post, build this. It's an afternoon of setup and a year of fewer facepalm moments.

5. Closed-loop hooks beat one-shot hooks

My Daily AI Intel hook (Python script, then parallel web searches, then appended sections in the same dated report) is worth more than any single automation. Look for workflows where the output of one session improves the next. The .last_run file is a three-line change that makes tomorrow's run 10x faster than today's.

6. Document the "why" in steering files

Every rule in my steering files has a "Reason" line. I cannot stress this enough. "Use the global inference profile ID for Bedrock calls" is a rule. "Use the global inference profile ID because it routes across all commercial regions and avoids cross-region availability gaps that bare model IDs can hit" is a rule that survives contact with your future self.

7. Specs are not optional for complex work

If a project touches more than three files or takes more than a day, it gets a spec. The Requirements → Design → Tasks flow catches architectural mistakes while they're still cheap to fix. The one time I skipped it, I rewrote 600 lines the following week. I have not skipped it since.

8. Let hooks enforce what steering files teach

Steering files say "no files in root." The new-file-validator hook enforces it. Steering files say "run tests after tasks." The post-task-test-runner hook enforces it. Rules without enforcement are aspirational. Rules with enforcement are how your codebase stays clean at 6pm on a Friday.

Teaching Kiro to Evolve: A Real-Time Example

Here's a pattern I ran last week that captures why this setup pays off over time.
I was reading Thariq Rahman's essay "Using Claude Code: The Unreasonable Effectiveness of HTML ." The argument: as agents produce longer plans and specs, markdown stops being the right output format. HTML can carry richer information: SVG diagrams, sortable tables, collapsible sections, copy-as-prompt buttons, even throwaway editors for reordering backlogs.
Rather than adopt it workspace-wide, I asked Kiro to help me think it through. We built a tradeoff matrix across my actual artifact types: academic papers, demo scripts, Kiro specs, call prep briefs, competitive analyses, and research notes. The outcome wasn't "switch everything to HTML." It was a one-week trial scoped to the two artifact types where HTML genuinely wins: call prep briefs and competitive analyses. Everything else stays on its existing pipeline.
Then Kiro wrote itself a new conditional steering file, .kiro/steering/html-artifacts.md, that activates only when I'm editing call prep or comparison documents. It defines the output format (self-contained HTML, embedded CSS, no CDN dependencies), the required sections, the sharing pattern (S3 pre-signed URLs), and a review date a week out so I can evaluate honestly.
What's notable here is that the rule system extended itself. I didn't hand-author a new policy. I had a conversation, made a scoped decision, and Kiro encoded the decision as a file-pattern-matched steering rule with a built-in expiration checkpoint. The living knowledge policy in learning.md tells Kiro to keep doing this: every new pattern I discover becomes a file, scoped to the situation where it applies.
In the same session, Kiro noticed an inconsistency in its own rendering behavior. It had been using HTML tables in chat responses (which read as raw tags in the chat pane) because the steering rule didn't distinguish between "documents" and "chat." I pointed it out, and the table formatting steering file now has an explicit carve-out: markdown pipe tables in chat, HTML tables in documents.
That's the shape of a healthy customization system: decisions get captured, scope stays narrow, and the rules correct themselves when they're wrong.

The Numbers

After 4 months of iterating on this setup:
  • 22 steering files ranging from always-on conventions to manual deep-expertise playbooks
  • 12 hooks total (7 favorites above) covering file creation, task completion, agent stop, daily reminders, and call prep
  • 24 specs for structured development on every non-trivial project
  • 3 MCP servers with specialized documentation always available
  • 0 times I've accidentally used Streamlit, hardcoded an account ID, or put a file in the workspace root (verified by grepping git history and all Python files for the specific violations; both checks come back empty across the whole workspace).
The initial investment was maybe two hours spread across a week. The ongoing maintenance is zero. It happens naturally during work via the learning policy.

Getting Started

If you're new to Kiro customization, here's my suggested order. Do not try to build all of this in one afternoon. Build one thing, let it pay for itself, then build the next.
  1. Create .kiro/steering/behavior.md. Define your tone, defaults, and deal-breakers. Keep it to five lines or less. You can always add more later. The whole file should be something you could recite from memory.
  2. Create one promptSubmit hook. Your top five rules, injected every message. This is the single highest-leverage thing you can build. It takes ten minutes.
  3. Create .kiro/steering/tech.md. Start empty. Every time you hit an SDK gotcha, add a three-line entry: what, why, example. After a month it will be the most useful file in your workspace.
  4. Create a fileCreated hook. Enforce your naming and structure conventions. Future you will thank past you every single day.
  5. Create your first spec for your next non-trivial project. Requirements first. Resist the urge to skip to tasks.
That's it. Five things. You'll be surprised how quickly the system compounds. Each rule you add prevents a class of mistakes forever. Each hook you create is a workflow you never have to remember again.

The Lazy Shortcut

If step-by-step is not your style, here's the actual shortcut: point Kiro at this blog post and ask it to build everything. Something like "Read this post and scaffold all the steering files, hooks, and specs described in it for my workspace, tailored to my stack." Kiro will read the post, propose a tailored setup for your domain and tools, and draft the files in a single session. You'll still want to review what it produces (the "Reason" lines matter, and your rules should reflect your work, not mine), but you can have a fully customized workspace in an afternoon instead of a month. The three pillars include Kiro as an active collaborator, which means even the onboarding bootstraps itself.
That is the real value, and the real reason I kept going. Kiro stops being a tool you use and becomes a system that knows how you work. The first time it nags you about a deadline you'd forgotten, or catches a rule violation you didn't know you'd written into existence, you'll understand why I've got twenty-two steering files and counting.
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