Describe the bug
apm install deploys hooks to the kiro target in the deprecated pre-1.0 Kiro hook schema
({ "when": {...}, "then": { "type": "runCommand" } }).
Kiro IDE 1.0 / CLI v3 replaced that schema with a versioned, standalone format:
{
"version": "v1",
"hooks": [
{ "name": "...", "trigger": "PreToolUse", "matcher": "...", "action": { "type": "command", "command": "..." } }
]
}
(See Kiro CLI v3 hooks and the
Kiro IDE 1.0 changelog.)
As a result, hooks that APM deploys to .kiro/hooks/ are treated by Kiro 1.0 as legacy
(migrate-only via the Agent Hooks panel), not as the current runtime format. On top of the
format mismatch there are three functional gaps (details below): no agent (prompt) action,
matcher/trigger naming differences, and several 1.0 triggers that don't map at all.
Context: the Kiro target was added relatively recently (#702, milestone 0.20.0), which predates
Kiro's 1.0 hook-schema change — so the integrator was written against the older shape.
To Reproduce
-
Create a minimal package:
apm.yml
name: hook-repro
version: 0.0.1
targets: [kiro, claude, copilot]
includes: auto
.apm/instructions/dummy.instructions.md
---
description: dummy
applyTo: "**/*.md"
---
- placeholder
.apm/hooks/check.json (documented Claude shape, type: command)
{
"hooks": {
"PreToolUse": [
{ "matcher": "fs_write|str_replace",
"hooks": [ { "type": "command", "command": "echo pre-write-check", "timeout": 10 } ] }
]
}
}
-
Run apm install.
-
Inspect .kiro/hooks/hook-repro-check-pretooluse-1.json.
Actual output (APM 0.24.0)
{
"name": "hook-repro preToolUse 1",
"version": "1.0.0",
"when": {
"type": "preToolUse",
"patterns": ["fs_write|str_replace"]
},
"then": {
"type": "runCommand",
"command": "echo pre-write-check"
}
}
This is the pre-1.0 schema (when/then/runCommand, camelCase when.type, patterns).
Expected behavior
(Kiro 1.0 / v3 schema)
{
"version": "v1",
"hooks": [
{
"name": "hook-repro pre-write-check",
"trigger": "PreToolUse",
"matcher": "fs_write|str_replace",
"action": { "type": "command", "command": "echo pre-write-check", "timeout": 10 }
}
]
}
Differences: top-level version: "v1" + a hooks array; trigger (PascalCase) instead of
when.type (camelCase); matcher instead of patterns; action instead of then; and
action.type: "command" instead of then.type: "runCommand".
Additional gaps found while testing
Beyond the format, three things block real usage on Kiro 1.0:
-
No agent action. APM only maps type: command -> runCommand. Kiro 1.0 supports
action.type: "agent" (append a prompt to the model context, no subprocess), which is the
right primitive for lightweight steering/guardrails. There is no way to author or emit an
agent-action hook through APM today.
-
Trigger mapping is stale / partial. Observed mappings on the kiro target:
| Authored (Claude shape) |
APM emits (when.type) |
Kiro 1.0 expects (trigger) |
PreToolUse |
preToolUse (+ patterns) |
PreToolUse (+ matcher) |
PostToolUse |
postToolUse (+ patterns) |
PostToolUse (+ matcher) |
Stop |
agentStop |
Stop |
UserPromptSubmit |
promptSubmit |
UserPromptSubmit |
SessionStart |
(passed through, casing-mismatch warning) |
SessionStart |
SubagentStop |
(passed through, warning) |
(n/a — use Stop) |
PreCompact |
(passed through, warning) |
(n/a) |
Kiro 1.0 also adds triggers with no APM path: PreTaskExec, PostTaskExec,
PostFileCreate, PostFileSave, PostFileDelete.
-
Native v1 files are rejected, so authors can't work around the above by shipping the
correct format directly. A .apm/hooks/*.json in the v1 shape fails install with:
WARNING apm_cli.integration.hook_integrator Skipping malformed hook file ...: 'hooks' must be a dict, got list
(Kiro 1.0's hooks is an array; APM's validator requires an object.)
Impact
Packages that target kiro cannot ship hooks that run on Kiro 1.0 without a manual migration
step per consumer. The only clean cross-target workaround today is to express hook intent as
instructions (which compile correctly to .kiro/steering/), but that loses the
command/exit-code enforcement and event-fired triggering that hooks provide — and it can't
represent a genuine blocking validation gate (e.g. a pre-task branch/worktree check).
Suggested fix / acceptance criteria
- Emit the Kiro 1.0
v1 schema for the kiro target: { "version": "v1", "hooks": [ { "name", "trigger", "matcher", "action": { "type", "command"|"prompt", "timeout"? } } ] }.
- Map events to Kiro 1.0 PascalCase
trigger names and use matcher (not patterns).
- Support an
agent/prompt action for Kiro (either a first-class portable action or a
documented Kiro-scoped passthrough), so prompt-based guardrails can be deployed rather than
only shell commands.
- Optionally: accept native Kiro
v1 hook files in .apm/hooks/ (array-shaped hooks) so
authors can target Kiro directly when a portable expression isn't possible.
Environment
References
Describe the bug
apm installdeploys hooks to thekirotarget in the deprecated pre-1.0 Kiro hook schema(
{ "when": {...}, "then": { "type": "runCommand" } }).Kiro IDE 1.0 / CLI v3 replaced that schema with a versioned, standalone format:
{ "version": "v1", "hooks": [ { "name": "...", "trigger": "PreToolUse", "matcher": "...", "action": { "type": "command", "command": "..." } } ] }(See Kiro CLI v3 hooks and the
Kiro IDE 1.0 changelog.)
As a result, hooks that APM deploys to
.kiro/hooks/are treated by Kiro 1.0 as legacy(migrate-only via the Agent Hooks panel), not as the current runtime format. On top of the
format mismatch there are three functional gaps (details below): no
agent(prompt) action,matcher/triggernaming differences, and several 1.0 triggers that don't map at all.Context: the Kiro target was added relatively recently (#702, milestone 0.20.0), which predates
Kiro's 1.0 hook-schema change — so the integrator was written against the older shape.
To Reproduce
Create a minimal package:
apm.yml.apm/instructions/dummy.instructions.md.apm/hooks/check.json(documented Claude shape,type: command){ "hooks": { "PreToolUse": [ { "matcher": "fs_write|str_replace", "hooks": [ { "type": "command", "command": "echo pre-write-check", "timeout": 10 } ] } ] } }Run
apm install.Inspect
.kiro/hooks/hook-repro-check-pretooluse-1.json.Actual output (APM 0.24.0)
{ "name": "hook-repro preToolUse 1", "version": "1.0.0", "when": { "type": "preToolUse", "patterns": ["fs_write|str_replace"] }, "then": { "type": "runCommand", "command": "echo pre-write-check" } }This is the pre-1.0 schema (
when/then/runCommand, camelCasewhen.type,patterns).Expected behavior
(Kiro 1.0 / v3 schema)
{ "version": "v1", "hooks": [ { "name": "hook-repro pre-write-check", "trigger": "PreToolUse", "matcher": "fs_write|str_replace", "action": { "type": "command", "command": "echo pre-write-check", "timeout": 10 } } ] }Differences: top-level
version: "v1"+ ahooksarray;trigger(PascalCase) instead ofwhen.type(camelCase);matcherinstead ofpatterns;actioninstead ofthen; andaction.type: "command"instead ofthen.type: "runCommand".Additional gaps found while testing
Beyond the format, three things block real usage on Kiro 1.0:
No
agentaction. APM only mapstype: command->runCommand. Kiro 1.0 supportsaction.type: "agent"(append a prompt to the model context, no subprocess), which is theright primitive for lightweight steering/guardrails. There is no way to author or emit an
agent-action hook through APM today.
Trigger mapping is stale / partial. Observed mappings on the
kirotarget:when.type)trigger)PreToolUsepreToolUse(+patterns)PreToolUse(+matcher)PostToolUsepostToolUse(+patterns)PostToolUse(+matcher)StopagentStopStopUserPromptSubmitpromptSubmitUserPromptSubmitSessionStartSessionStartSubagentStopStop)PreCompactKiro 1.0 also adds triggers with no APM path:
PreTaskExec,PostTaskExec,PostFileCreate,PostFileSave,PostFileDelete.Native v1 files are rejected, so authors can't work around the above by shipping the
correct format directly. A
.apm/hooks/*.jsonin the v1 shape fails install with:(Kiro 1.0's
hooksis an array; APM's validator requires an object.)Impact
Packages that target
kirocannot ship hooks that run on Kiro 1.0 without a manual migrationstep per consumer. The only clean cross-target workaround today is to express hook intent as
instructions (which compile correctly to
.kiro/steering/), but that loses thecommand/exit-code enforcement and event-fired triggering that hooks provide — and it can'trepresent a genuine blocking validation gate (e.g. a pre-task branch/worktree check).
Suggested fix / acceptance criteria
v1schema for thekirotarget:{ "version": "v1", "hooks": [ { "name", "trigger", "matcher", "action": { "type", "command"|"prompt", "timeout"? } } ] }.triggernames and usematcher(notpatterns).agent/prompt action for Kiro (either a first-class portable action or adocumented Kiro-scoped passthrough), so prompt-based guardrails can be deployed rather than
only shell commands.
v1hook files in.apm/hooks/(array-shapedhooks) soauthors can target Kiro directly when a portable expression isn't possible.
Environment
release notes, which include hook fixes [BUG] Copilot hook events are never renamed to camelCase #1977 / [BUG] Combined hook manifests (claude-codex-hooks.json) route to one target only; claude silently gets Copilot-schema fallback hooks #2020 / [BUG] Deployed hook scripts crash at runtime: required sibling modules are not copied, and the consumer's package.json module type is applied to them #2023 but no Kiro-1.0 schema update).
References
https://kiro.dev/changelog/ide/1-0/