Kiro (kiro)
Set up this tool
agnostic-ai writes AWS Kiro steering files, native skills, agents, commands, and hooks under .kiro/, plus MCP servers and .kiroignore.
First rule
Install the client using the official setup guide, then open your project in it.
Select kiro in agnostic-ai.yaml, then follow First rule to add the shared commit-prefix rule and sync it. With the default paths, it reaches .kiro/steering/conventional-commits.md, or shared AGENTS.md when another selected target already puts the rule there.
File-matching steering rules need the IDE or CLI V3. Earlier CLI versions load only always-on rules.
For existing files, check what import kiro reads before syncing.
Verify
Run agnostic-ai sync --check and find the commit-prefix rule in .kiro/steering/conventional-commits.md or the shared AGENTS.md. Open the project in Kiro and trust the workspace if it asks (CLI 2.33 shows a trust screen before it loads workspace configuration). Confirm the steering rule or shared instructions are loaded, then ask for a commit subject for a small fix; it should use fix:.
Next, add a skill.
Output
AGENTS.md # entry-point pointer body, plus the rules block when another tool adds it
.kiro/steering/<name>.md # one per rule (inclusion: always, or fileMatch + fileMatchPattern from globs)
.kiro/skills/<name>/SKILL.md # one per skill (+ bundled scripts/, references/, assets/)
.kiro/agents/<name>.md # one per agent
.kiro/prompts/<name>.md # one per command (slash commands in CLI V3)
.kiro/hooks/<name>.json # one per hook
.kiro/settings/mcp.json # when MCP entries exist
.kiro/settings/cli.json # chat.defaultModel, when a settings spec sets model
.kiroignore # when ignore entries exist
Native mappings
Field mappings, discovery, and compatibility
- Rules: steering files must start with their YAML frontmatter. Rules without globs use
inclusion: always. Rules with globs usefileMatchwithfileMatchPattern, a string for one pattern and a list for several. Rules with globs need the Kiro IDE or Kiro CLI V3. CLI V1 and V2 load onlyalwaysfiles. Sync never writes Kiro'sautoandmanualmodes. AGENTS.md: Kiro includes it in default resources. When Codex or another tool that copies rules intoAGENTS.mdadds the## Rulesblock, always-on rules normally get no steering file.fileMatchrules keep theirs. Custom agents inherit default resources alongside their own list unlesschat.disableInheritingDefaultResourcesis on. Settingx-kiro.resourceson an agent does not change this. If you turn that setting on, addfile://AGENTS.mdto each agent'sx-kiro.resources.agnostic-ai lintwarns (LINT029) when an agent with resources leaves it out. See target behavior.- Memory: with
builtins: [memory],.kiro/steering/kiro-memory-index.mdincludes.agnostic-ai/memory/MEMORY.mdand.agnostic-ai/local/memory/MEMORY.mdwith#[[file:...]], so Kiro loads both shared memory lists every session. No other tool gets the file, andsync --globalleaves it out. Kiro resolves each path from the workspace root and shows a marker for a list that does not exist yet. It applies its file read permissions and ignore rules to a reference, so a list they block does not load. Withmemory.personal: repo, the file includes only the project list. The shared policy tells Kiro to find personal memory withagnostic-ai memory path. - Skills: native at
.kiro/skills/<name>/SKILL.md, read by the skill picker. The file (nameanddescriptionfrontmatter) is identical to the shared.agents/skills/one. Bundledscripts/,references/, andassets/are copied with it. - Agents: native custom agents in YAML-frontmatter Markdown, read by the agent picker.
description(default: the agent name) andmodelare copied as written. The spec name stays the file name.x-kiro.namesets Kiro's optional display name and survives import. - Settings: the settings
modelgoes tochat.defaultModelin.kiro/settings/cli.json, as written, and every other key in the file stays. Kiro CLI uses a workspace value over the global one in~/.kiro/settings/cli.jsonin its terminal UI sessions. Kiro ids use dots (claude-sonnet-4.6), so setmodel: {default: ..., kiro: claude-sonnet-4.6}when the shared value is a Claude Code id. A Claude alias such assonnetraises a note and writes nothing.permissionsraise a note, because the file has no allow, deny, or ask list. Sync replaces achat.defaultModelyou set by hand while a settings spec setsmodel, and removing the model later deletes the key without restoring your earlier value; setmodel: {claude: ...}to keep Kiro out.x-kiroin a settings spec raises a note and is not written, becausecli.jsontakes flat dotted keys. Sync rewrites the file in its own two-space format, and comments in it are not kept. - Agent MCP servers: each server an agent names in
mcpServersis written in full under the agent'smcpServers, the only form Kiro takes. An agent-only server stays out of.kiro/settings/mcp.json.x-kiro.mcpServersreplaces the list.
Commands
Kiro CLI 2.27.0 and newer shows workspace prompts as /name commands in V3. Sync writes the command body to .kiro/prompts/<name>.md, with a generated-file header and no frontmatter.
Kiro expands $ARGUMENTS, ${1} through ${10}, and ${@}. Sync keeps these tokens as they are. Use a ::target kiro fence for Kiro-specific templates. Bare $1 and $ARGUMENTS[0] still get the unsupported-syntax checks.
outputs.kiro.commands-dir changes the prompt folder. Otherwise, outputs.kiro.dir puts prompts under <dir>/prompts. Import reads the same folder into sources.commands.
Kiro also has a global prompt folder. sync --global does not write commands.
Unmanaged AGENTS.md
Listing AGENTS.md under sync.unmanaged keeps every steering file. Check the effect on other targets sharing that file.
Old flattened steering files
Older versions flattened skills into .kiro/steering/skill-<name>.md and agents into .kiro/steering/agent-<name>.md, which never reached the pickers. sync removes them.
Kiro's agent schema also carries tools, mcpServers, permissions, hooks, keyboardShortcut (CLI 2.x only), welcomeMessage, excludedTools, includeMcpJson, and includePowers. tools is translated from the portable can or tools field. Kiro's mcpServers holds inline definitions, not names, so set x-kiro.mcpServers. Set the rest, and any other key, under x-kiro.
Kiro groups agent tools into read, write, shell, web, and subagent. The configuration reference and tools page list the same categories. It also accepts @server_name, @server_name/tool_name, @mcp, @builtin, and *.
Built-in tools such as knowledge use their exact tool IDs. Sync translates four of the categories, plus named MCP servers and tools:
Spec can values | Spec tools values | Kiro category |
|---|---|---|
read | Read, Grep, Glob | read |
write, edit, delete | Write, Edit | write |
shell | Bash | shell |
web | WebFetch, WebSearch | web |
mcp:<server> | mcp__<server> | @<server> |
mcp:<server>/<tool> | mcp__<server>__<tool> | @<server>/<tool> |
Duplicates are merged. A Kiro category covers more than one tool, so access widens: write also covers delete_file, and web covers fetch and search. Sync prints a note naming the extra access, such as kiro: .agnostic-ai/agents/writer.md: edit becomes Kiro's write category, which also allows delete_file. on-unsupported: error fails when access widens, including for a Claude Code alias such as Edit. Scoped values, such as shell(git diff *) and read(src/**), are dropped with a sync note. The rest are still written. x-kiro.tools takes Kiro's own names and always wins.
Hooks are native: one JSON file per spec, {"version": "v1", "hooks": [{name, trigger, matcher, action, timeout, enabled, description}]}.
- Portable
on: before-toolmaps toPreToolUse, with anchored lists of documented built-in IDs forshell,read,web, andedit, and@<server>/*formcp:<server>. Built-in kinds exclude MCP tools and need an updated mapping for new IDs. The tool wildcard keeps server names such asmcpdistinct from source selectors. Other portable events anddecision: stdouthave no Kiro mapping. See portable hooks. eventbecomestrigger, as written.validateflagsAgentSpawnandagentSpawn, Kiro V3's compatibility aliases, and suggestsSessionStart.- Each
command(string or list) becomes anaction: {"type": "command", "command": ...}entry in the same file. Thenamegets a-2,-3, ... suffix to stay unique. disabled: truewrites"enabled": false.descriptionis written to the file as documentation only.timeout: 0disables the timeout; omitting it keeps Kiro's 60-second default.x-kirokeys are copied to each entry. That is the only way to setconfirm(ask before a Stop command hook runs, withquestion,optionsofid/label/run, and optionalconfirmCommand).x-kiro.actiontakes{type: agent, prompt: ...}or{type: command, command: ...}. A valid one needs no portablecommandand replaces the whole list with one action. An invalid one fails sync..agnostic-ai/scripts/<name>references are copied to.kiro/scripts/<name>, outside.kiro/hooks/where Kiro reads hook files, and the command is rewritten. See shared hook scripts.agnostic-ai hook runruns aUserPromptSubmitorStophook, or a tool hook with--payload, on an assumedsh -c, before a session does.
Use your home hook specs in every workspace with Kiro CLI V3:
agnostic-ai sync --global --only kiro --dry-run
agnostic-ai sync --global --only kiro
agnostic-ai sync --global --only kiro --check
Sync writes ~/.kiro/hooks/<name>.json and copies shared scripts to ~/.kiro/scripts/. Set KIRO_HOME to a valid absolute profile directory to change where agnostic-ai writes these folders and Kiro's other global files. Like Kiro CLI, sync uses ~/.kiro when the value is relative, a filesystem root, your home directory, or one of its ancestors. Global hooks and workspace hooks both run.
Sync removes only recorded files after their specs are removed. A conflicting or edited file stops sync.
agnostic-ai import --global kiro imports hook files that one spec can reproduce at the same filename. Files with mixed triggers, names that differ from their filename, or other content the spec cannot preserve are skipped with a warning. Existing specs stay. After importing, run the sync and check commands above.
MCP servers go to .kiro/settings/mcp.json under mcpServers, Kiro's workspace-level config. Local servers have command plus optional args and env. Remote ones have url plus optional headers and env. Kiro expands a ${NAME} reference only after you approve the variable under Mcp Approved Env Vars in its settings. See environment references. disabled is copied as written (default false). Kiro also accepts autoApprove (tools approved without prompting, "*" for all) and disabledTools (tools hidden from the agent). A remote server can add oauth ({clientId, clientSecret, redirectUri, clientMetadataUrl, oauthScopes}) and a top-level oauthScopes fallback; oauth.oauthScopes wins. An empty oauthScopes: [] is written as is, which is Kiro's documented fix for scope errors. Kiro's oauth differs from Claude Code's, so each tool maps only its own sub-keys. See disabled support by target.
Ignore specs are joined into the project .kiroignore in gitignore syntax (Kiro ignore); override with outputs.kiro.ignore-file. The IDE honors the file only when it is listed in kiroAgent.agentIgnoreFiles (Kiro suggests [".gitignore", ".kiroignore"]). CLI V3 honors workspace .kiroignore, ~/.kiro/settings/kiroignore, and Git's global ignore file (core.excludesfile, only in Git repositories). Matching files are blocked from direct reads and hidden from content and filename search.
Config keys
| Key | Default |
|---|---|
outputs.kiro.rules-dir | .kiro/steering |
outputs.kiro.agents-dir | .kiro/agents |
outputs.kiro.skills-dir | .kiro/skills |
outputs.kiro.commands-dir | .kiro/prompts |
outputs.kiro.hooks-dir | .kiro/hooks |
outputs.kiro.mcp-file | .kiro/settings/mcp.json |
outputs.kiro.ignore-file | .kiroignore |
Import
agnostic-ai import kiro reads the native agent and skill folders first. Then it reads rules and old flattened agents and skills from .kiro/steering/ (the filename prefix picks the kind):
| Source | Becomes |
|---|---|
.kiro/prompts/<name>.md (or the configured command directory) | <commands>/<name>.md |
.kiro/agents/<name>.md (native agent profile) | <agents>/<name>.md |
.kiro/skills/<name>/SKILL.md (native skill folder) | <skills>/<name>/SKILL.md, bundled files next to the skill included |
.kiro/steering/<name>.md (inclusion: always) | <rules>/<name>.md (project-wide rule) |
.kiro/steering/<name>.md (inclusion: fileMatch + fileMatchPattern) | <rules>/<name>.md with globs: <fileMatchPattern> |
.kiro/steering/<name>.md (inclusion: manual or auto) | skipped with a note. The file stays hand-written, since a rule has no on-demand mode |
.kiro/steering/agent-<name>.md (legacy, pre-native sync) | <agents>/<name>.md, body only |
.kiro/steering/skill-<name>.md (legacy, pre-native sync) | <skills>/<name>/SKILL.md, body only |
.kiro/hooks/<id>.json (hooks[]) | one hook spec per group of entries that differ only in action.command |
.kiro/settings/mcp.json (mcpServers.<name>) | <mcps>/<name>.yaml |
AGENTS.md | .agnostic-ai/AGNOSTIC_AI.md |
Native files win over old steering files with the same name.
Hook import reads every Kiro field:
triggerbecomesevent;matcher,description, andtimeout(includingtimeout: 0) carry over;enabled: falsebecomesdisabled: true.action.type: "agent"goes underx-kiro.action, not the portable prompt handler, which spec-format.md limits to Claude Code, Cursor, and Copilot.confirmand unknown keys go underx-kiro, so new Kiro fields are kept.- Several
triggervalues split into one spec each. - Entries that differ only in
action.commandbecome onecommand:list, without the-2/-3suffixes. - A readable name ("Lint on save") becomes the file name in slug form and stays unchanged in
name:. - An action with no content (
type: "command"with nocommand,type: "agent"with noprompt) is skipped with a warning.
The imported spec loses some data, but the Kiro files sync writes stay the same:
- A rule's folder scope becomes an equivalent
globs:. - An old flattened agent or skill keeps only its body. That form never had a description, model, or bundled files.
- An explicit
enabled: trueleaves no key, since it is the default. - Two hook files with the same
namekeep both hooks. The second gets a generated name, because spec names are unique file names. {{filePath}}stays as written. Kiro documents it as new in 3.0, and it means nothing elsewhere.
Global voice language
agnostic-ai sync --global --only kiro writes home voice.language to the literal "voice.language" key in ~/.kiro/settings/cli.json, or settings/cli.json under KIRO_HOME. Use auto to detect the transcription language. Kiro CLI has no on/off or capture mode key, so sync prints a note for voice.enabled and voice.mode. Other voice settings, including voice.autoSubmit, stay as written. Removing the portable language restores its previous value; a value you changed by hand stays yours. See voice dictation.
Protected paths
Not enforced. Sync prints a note for a protected block; Kiro has no edit guard it writes. Global voice language uses the separate home settings mapping above. See protected-path alternatives.