|
| 1 | +# Kiro |
| 2 | + |
| 3 | +> Reverse-engineered from the shipped Kiro extension, local Kiro state, and local Kiro logs. The live API is not publicly documented and may change without notice. |
| 4 | +
|
| 5 | +## Overview |
| 6 | + |
| 7 | +- **Product:** [Kiro](https://kiro.dev/) |
| 8 | +- **Runtime service:** AWS CodeWhisperer Runtime (`https://q.<region>.amazonaws.com`) |
| 9 | +- **Primary local state:** `~/Library/Application Support/Kiro/User/globalStorage/state.vscdb` |
| 10 | +- **Primary local metadata fallback:** `~/Library/Application Support/Kiro/logs/*/window*/exthost/kiro.kiroAgent/q-client.log` |
| 11 | +- **Auth token file:** `~/.aws/sso/cache/kiro-auth-token.json` |
| 12 | +- **Profile fallback:** `~/Library/Application Support/Kiro/User/globalStorage/kiro.kiroagent/profile.json` |
| 13 | + |
| 14 | +OpenUsage uses Kiro's local normalized usage cache first, enriches it from Kiro's own runtime logs when available, and only falls back to the live refresh/API path when the local picture is missing or stale. |
| 15 | + |
| 16 | +## Plugin Metrics |
| 17 | + |
| 18 | +| Metric | Source | Scope | Format | Notes | |
| 19 | +| --- | --- | --- | --- | --- | |
| 20 | +| Credits | `usageBreakdowns[*]` | overview | count | Monthly included Kiro plan credits | |
| 21 | +| Bonus Credits | `freeTrialUsage` or active `bonuses[0]` | overview | count | Free-trial / bonus credit pool when present | |
| 22 | +| Overages | `overageConfiguration.overageStatus` | detail | badge | `Enabled` / `Disabled` | |
| 23 | + |
| 24 | +The plan label comes from `subscriptionInfo.subscriptionTitle` when a recent `GetUsageLimits` response is available from logs or the live API. |
| 25 | + |
| 26 | +## Local Sources |
| 27 | + |
| 28 | +### 1) SQLite usage cache |
| 29 | + |
| 30 | +Path: `~/Library/Application Support/Kiro/User/globalStorage/state.vscdb` |
| 31 | + |
| 32 | +Key: |
| 33 | + |
| 34 | +- `kiro.kiroAgent` |
| 35 | + |
| 36 | +That JSON currently contains a nested key: |
| 37 | + |
| 38 | +- `kiro.resourceNotifications.usageState` |
| 39 | + |
| 40 | +Observed shape: |
| 41 | + |
| 42 | +```json |
| 43 | +{ |
| 44 | + "usageBreakdowns": [ |
| 45 | + { |
| 46 | + "type": "CREDIT", |
| 47 | + "currentUsage": 0, |
| 48 | + "usageLimit": 50, |
| 49 | + "resetDate": "2026-05-01T00:00:00.000Z", |
| 50 | + "displayName": "Credit", |
| 51 | + "displayNamePlural": "Credits", |
| 52 | + "freeTrialUsage": { |
| 53 | + "currentUsage": 106.11, |
| 54 | + "usageLimit": 500, |
| 55 | + "expiryDate": "2026-05-03T15:09:55.196Z", |
| 56 | + "daysRemaining": 27 |
| 57 | + } |
| 58 | + } |
| 59 | + ], |
| 60 | + "timestamp": 1775500185544 |
| 61 | +} |
| 62 | +``` |
| 63 | + |
| 64 | +This is the cleanest local source for the numeric usage lines. |
| 65 | + |
| 66 | +### 2) q-client runtime logs |
| 67 | + |
| 68 | +Path pattern: |
| 69 | + |
| 70 | +```text |
| 71 | +~/Library/Application Support/Kiro/logs/<session>/window*/exthost/kiro.kiroAgent/q-client.log |
| 72 | +``` |
| 73 | + |
| 74 | +Kiro logs the full `GetUsageLimitsCommand` request/response. That response includes the fields missing from the SQLite cache, especially: |
| 75 | + |
| 76 | +- `subscriptionInfo.subscriptionTitle` |
| 77 | +- `subscriptionInfo.type` |
| 78 | +- `overageConfiguration.overageStatus` |
| 79 | +- full `usageBreakdownList` |
| 80 | + |
| 81 | +OpenUsage uses the latest logged response to recover plan metadata without needing network access. |
| 82 | + |
| 83 | +## Authentication |
| 84 | + |
| 85 | +### Token file |
| 86 | + |
| 87 | +Kiro's desktop extension stores auth in: |
| 88 | + |
| 89 | +```text |
| 90 | +~/.aws/sso/cache/kiro-auth-token.json |
| 91 | +``` |
| 92 | + |
| 93 | +Observed fields: |
| 94 | + |
| 95 | +```json |
| 96 | +{ |
| 97 | + "accessToken": "...", |
| 98 | + "refreshToken": "...", |
| 99 | + "expiresAt": "2026-04-06T19:29:16.090Z", |
| 100 | + "authMethod": "social", |
| 101 | + "provider": "Google", |
| 102 | + "profileArn": "arn:aws:codewhisperer:us-east-1:699475941385:profile/..." |
| 103 | +} |
| 104 | +``` |
| 105 | + |
| 106 | +### Profile fallback |
| 107 | + |
| 108 | +If `profileArn` is not embedded in the token file, Kiro also persists the selected profile: |
| 109 | + |
| 110 | +```json |
| 111 | +{ |
| 112 | + "arn": "arn:aws:codewhisperer:us-east-1:699475941385:profile/...", |
| 113 | + "name": "Google" |
| 114 | +} |
| 115 | +``` |
| 116 | + |
| 117 | +## Live Refresh + Usage API |
| 118 | + |
| 119 | +### Refresh social auth token |
| 120 | + |
| 121 | +```http |
| 122 | +POST https://prod.us-east-1.auth.desktop.kiro.dev/refreshToken |
| 123 | +Content-Type: application/json |
| 124 | +User-Agent: KiroIDE-<version>-<machineId> |
| 125 | +``` |
| 126 | + |
| 127 | +```json |
| 128 | +{ |
| 129 | + "refreshToken": "<refresh_token>" |
| 130 | +} |
| 131 | +``` |
| 132 | + |
| 133 | +Observed refresh response fields: |
| 134 | + |
| 135 | +- `accessToken` |
| 136 | +- `refreshToken` |
| 137 | +- `expiresIn` |
| 138 | +- `profileArn` |
| 139 | + |
| 140 | +### Fetch usage |
| 141 | + |
| 142 | +```http |
| 143 | +GET https://q.<region>.amazonaws.com/getUsageLimits?origin=AI_EDITOR&profileArn=<profileArn>&resourceType=AGENTIC_REQUEST |
| 144 | +Authorization: Bearer <accessToken> |
| 145 | +Accept: application/json |
| 146 | +``` |
| 147 | + |
| 148 | +Extra headers used by Kiro only for specific auth modes: |
| 149 | + |
| 150 | +- `TokenType: EXTERNAL_IDP` for external IdP accounts |
| 151 | +- `redirect-for-internal: true` for internal AWS accounts |
| 152 | + |
| 153 | +Observed response fields: |
| 154 | + |
| 155 | +- `nextDateReset` |
| 156 | +- `overageConfiguration.overageStatus` |
| 157 | +- `subscriptionInfo.subscriptionTitle` |
| 158 | +- `subscriptionInfo.type` |
| 159 | +- `usageBreakdownList[*]` |
| 160 | +- `userInfo.userId` |
| 161 | + |
| 162 | +## Provider Strategy in OpenUsage |
| 163 | + |
| 164 | +1. Require Kiro auth token presence so stale post-logout cache data is not shown as an active account. |
| 165 | +2. Read `state.vscdb` for the normalized numeric usage view. |
| 166 | +3. Read the latest `q-client.log` `GetUsageLimitsCommand` response for plan and overage metadata. |
| 167 | +4. If the local cache is missing, incomplete, or older than the app's staleness threshold, call the live refresh/API path. |
| 168 | +5. If live fetch fails but the local cache is usable, keep showing the last local snapshot. |
0 commit comments