| name | kiro-capture |
| description | Capture and analyze kiro-cli HTTPS traffic using mitmdump. Sets up mitmdump proxy, provides the kiro-cli launch command, then parses the capture log to generate individual API call files and a detailed analysis report. Use via /kiro-capture. |
| disable-model-invocation | true |
kiro-capture
Capture kiro-cli HTTPS traffic with mitmdump and generate analysis reports.
Phase Detection
On invocation, find the latest session under /tmp/kiro-capture/:
LATEST=$(ls -dt /tmp/kiro-capture/*/ 2>/dev/null | head -1)
if [ -n "$LATEST" ] && [ -f "${LATEST}state.json" ]; then
cat "${LATEST}state.json"
fi
Decision logic:
state.json exists with "status": "capturing":
- Check PID with
kill -0 <pid>
- PID alive → ask user: "Capture in progress. Stop and analyze?" If yes → Phase 2
- PID dead → tell user "mitmdump already stopped. Analyzing log." → Phase 2
state.json exists with "status": "completed" or "status": "analyzing" → ask user: "Previous capture is done. Start a new capture?"
- No
state.json or empty directory → Phase 1
Phase 1: Setup
Step 1 — Check prerequisites
which mitmdump
If not found:
brew install mitmproxy
Check CA certificate:
ls ~/.mitmproxy/mitmproxy-ca-cert.pem
If missing, run mitmdump once to generate it:
mitmdump --set flow_detail=0 &
MITM_PID=$!
sleep 2
kill $MITM_PID 2>/dev/null
wait $MITM_PID 2>/dev/null
Step 2 — Check port availability
lsof -i :8080 -t 2>/dev/null
If port 8080 is in use, try 8081, 8082, ... until a free port is found.
Step 3 — Create session directory
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
SESSION_DIR="/tmp/kiro-capture/${TIMESTAMP}"
mkdir -p "$SESSION_DIR"
Step 4 — Start mitmdump
mitmdump -p $PORT --set flow_detail=3 >"${SESSION_DIR}/raw.log" 2>&1 &
MITM_PID=$!
sleep 1
kill -0 $MITM_PID 2>/dev/null && echo "OK" || echo "FAILED"
Step 5 — Save state.json
Write to ${SESSION_DIR}/state.json:
{
"status": "capturing",
"pid": <MITM_PID>,
"port": <PORT>,
"session_dir": "<SESSION_DIR>",
"started_at": "<ISO8601>"
}
Step 6 — Output kiro-cli launch command
Tell the user:
"mitmdump is running on port {PORT}. Run the following command in a separate terminal to start kiro-cli through the proxy:
HTTPS_PROXY=http://127.0.0.1:{PORT} \
HTTP_PROXY=http://127.0.0.1:{PORT} \
SSL_CERT_FILE=~/.mitmproxy/mitmproxy-ca-cert.pem \
kiro-cli chat
When you're done using kiro-cli, come back here and run /kiro-capture again to stop the capture and generate the analysis report.
Session directory: {SESSION_DIR}"
Phase 1 ends here. Wait for the user to re-invoke.
Phase 2: Analysis
Step 7 — Stop mitmdump
Read PID from state.json and stop that specific process:
kill <PID_FROM_STATE_JSON>
while kill -0 <PID_FROM_STATE_JSON> 2>/dev/null; do sleep 0.2; done
Skip if PID is already dead.
Step 8 — Update state.json
Set status to "analyzing".
Step 9 — Parse capture log
Read ${SESSION_DIR}/raw.log and extract request/response pairs.
mitmdump flow_detail=3 output format:
<IP>: <METHOD> <URL>
<header>: <value>
...
<request body>
<< <STATUS> <SIZE>
<header>: <value>
...
<response body>
For each request/response pair, extract:
- Sequence number — assign 01, 02, ... in order of appearance
- API name — from
x-amz-target header. Known APIs:
AmazonCodeWhispererStreamingService.GenerateAssistantResponse (EventStream response)
AmazonCodeWhispererService.ListAvailableModels (JSON)
ToolkitTelemetry.ClientTelemetryMetrics (JSON)
AmazonCodeWhispererService.GetProfile (JSON)
AmazonCodeWhispererService.GetUsageLimits (JSON, 403 is expected/normal; may be absent in a session)
AmazonCodeWhispererService.SendTelemetryEvent (JSON)
AWSCognitoIdentityService.GetCredentialsForIdentity (JSON; cognito-identity host — returns temporary AWS creds used to SigV4-sign the telemetry calls)
- If no
x-amz-target, infer from URL path/host:
oidc.*.amazonaws.com/token → SSOOIDC.CreateToken (JSON; grantType: refresh_token rotates the Bearer token mid-session)
client-telemetry.*.amazonaws.com/metrics → ToolkitTelemetry.ClientTelemetryMetrics
- Request URL
- Request headers — all headers, but redact:
authorization header value → [REDACTED] (covers both Bearer <token> and AWS4-HMAC-SHA256 ... Signature=...)
x-amz-security-token header value → [REDACTED]
- Request body — extract JSON as-is, but redact secret values in these bodies:
CreateToken request: refreshToken, clientSecret → [REDACTED]
- Response status — from
<< STATUS SIZE line
- Response headers
- Response body:
- JSON → extract as-is, but redact secret values:
GetCredentialsForIdentity response: AccessKeyId, , →
Redaction rule: secret values may only ever appear in raw.log (the mitmdump input). Every generated .md must contain [REDACTED] in their place. After generating files, verify no secret fragment (AWS ASIA... access key IDs, Bearer aoa.../aor... tokens, AWS4-HMAC ... Signature=<hex>, Cognito IQoJ... session tokens) leaks into any .md — including report.md prose.
EventStream response parsing
GenerateAssistantResponse responses use EventStream binary format. In mitmdump logs, binary and text are interleaved.
Parsing steps:
- Identify event boundaries by
:event-type markers
- Extract JSON objects (
{...}) from each event segment
- Classify events:
initial-response — stream preamble ({"conversationId":""})
reasoningContentEvent — native reasoning/thinking stream: text deltas followed by a final signature field. Concatenate the text deltas; note the signature exists but show it as [present] (do not dump the full value)
assistantResponseEvent — assistant response text (delta content field)
toolUseEvent — tool call (name, toolUseId, input fields)
metadataEvent — turn end (stopReason, e.g. END_TURN)
contextUsageEvent — context usage (contextUsagePercentage field)
meteringEvent — credit consumption ({"unit":"credit","usage":...})
- Merge events sharing the same
toolUseId to reconstruct complete tool calls
- Concatenate
assistantResponseEvent content fields to reconstruct full response text; concatenate reasoningContentEvent text fields to reconstruct the reasoning trace
Note: reasoningContentEvent and meteringEvent are emitted by kiro-cli 2.10.0. Reasoning is now native (a reasoningContentEvent stream), not a thinking tool in the tools array.
Step 10 — Generate individual API call files
For each request/response pair, create ${SESSION_DIR}/NN_APIName.md.
Format (follows existing _docs/capture/01_ClientTelemetryMetrics.md):
# NN. ServiceName.APIName
## Request
\`\`\`
METHOD URL
\`\`\`
### Request Headers
\`\`\`
header: value
authorization: [REDACTED]
x-amz-security-token: [REDACTED]
...
\`\`\`
### Request Body
\`\`\`json
{JSON body}
\`\`\`
## Response
\`\`\`
STATUS SIZE
\`\`\`
### Response Headers
\`\`\`
header: value
...
\`\`\`
### Response Body
\`\`\`json
{JSON body}
\`\`\`
For EventStream responses, use this Response Body format instead:
### Response Body
Content-Type: `application/vnd.amazon.eventstream`
**Events:**
| # | Event Type | Summary |
| --- | ---------------------- | -------------------------------- |
| 1 | initial-response | conversationId "" |
| 2 | reasoningContentEvent | {text delta / signature present} |
| 3 | assistantResponseEvent | {first 80 chars} |
| 4 | toolUseEvent | {tool name}: {first 80 chars} |
| 5 | metadataEvent | stopReason {value} |
| 6 | contextUsageEvent | {percentage}% |
| 7 | meteringEvent | {usage} credits |
**Full reasoning text:** (if any reasoningContentEvent)
\`\`\`
{concatenated reasoning text}
\`\`\`
**Full assistant response:**
\`\`\`
{concatenated full text}
\`\`\`
**Tool calls:** (if any toolUseEvent)
\`\`\`json
[{reconstructed tool call objects}]
\`\`\`
**Metering:** {unit}, usage {value}
Step 11 — Generate analysis report
Create ${SESSION_DIR}/report.md.
Template:
# Capture Analysis Report — {TIMESTAMP}
## Capture Environment
| Item | Value |
| ---------------- | ----------------------------------------------------- |
| Date | {started_at from state.json} |
| kiro-cli version | {from user-agent: md/appVersion-X.Y.Z} |
| AWS SDK | {from user-agent: aws-sdk-rust/X.Y.Z} |
| OS | {from user-agent} |
| Model | {modelId from GenerateAssistantResponse request body} |
| Region | {from request URL hostname} |
| Capture tool | mitmdump (mitmproxy) |
| Raw log | [raw.log](raw.log) |
## API Call Summary
| # | API | Status | Size | File |
| --- | ----------------------- | -------- | ------ | ------------------------------ |
| 01 | {ServiceName}.{APIName} | {status} | {size} | [01_APIName.md](01_APIName.md) |
| ... |
## API Category Breakdown
| Category | Count | APIs |
| ----------------------------- | ----- | ------------------------------------------------------------------- |
| CodeWhispererStreamingService | {n} | GenerateAssistantResponse |
| CodeWhispererService | {n} | GetProfile, ListAvailableModels, GetUsageLimits, SendTelemetryEvent |
| ToolkitTelemetry | {n} | ClientTelemetryMetrics |
| AWSCognitoIdentityService | {n} | GetCredentialsForIdentity |
| SSOOIDC | {n} | CreateToken |
(Omit categories with count 0.)
## Authentication
1. **Bearer Token** (`authorization: Bearer <token>`): CodeWhisperer / kiro.dev API
2. **AWS Signature V4** (`authorization: AWS4-HMAC-SHA256 ...`): Telemetry API
3. **Cognito + OIDC**: `GetCredentialsForIdentity` yields the temporary AWS creds that SigV4-sign the telemetry calls; `CreateToken` (`grantType: refresh_token`) refreshes the Bearer token mid-session (note if/when the token rotates)
## Conversation Flow
Group requests by conversationId and agentContinuationId. Render as ASCII tree:
\`\`\`
kiro-cli startup
├── ClientTelemetryMetrics (...)
├── GetProfile
├── ...
User message sent
├── GenerateAssistantResponse #1 (...)
├── SendTelemetryEvent
└── ClientTelemetryMetrics (...)
Tool result sent
├── GenerateAssistantResponse #2 (...)
...
\\`
| # | GenerateAssistantResponse | History length | contextUsagePercentage |
| --- | ------------------------- | ----------------- | ---------------------- |
| 1 | #NN | {history entries} | {percentage}% |
| ... |
Model ID: {modelId}
Reasoning/thinking: {active/inactive — active if the response has a stream. kiro-cli 2.10.0 uses native reasoning, so there is no tool in the tools array}
Tool count: {length of tools array}
| Tool name | Invocation count |
| ----------------------------- | ---------------- |
| {tool name from toolUseEvent} | {count} |
(If no toolUseEvent occurred, report and note the turns were plain text.)
Bullet list of anything noteworthy vs. prior captures, e.g.:
New event types or APIs observed (e.g. , )
Bearer token refresh / rotation via OIDC
Model-catalog specifics from (rateMultiplier, maxOutputTokens, context window, thinking.type enum)
APIs that were expected but absent (e.g. )
Metering / credit usage per turn
Step 12 — Update state.json
Set status to "completed". Add completed_at timestamp.
Step 13 — Report to user
Tell the user:
"Capture analysis complete.
- Session directory:
{SESSION_DIR}
- Raw log:
{SESSION_DIR}/raw.log
- Analysis report:
{SESSION_DIR}/report.md
- Individual API calls:
{SESSION_DIR}/NN_*.md ({count} files)
Total API calls: {total_count}
- GenerateAssistantResponse: {count}
- Others: {count}
Context usage (final): {last_percentage}%"