Skip to content

Commit 71ae900

Browse files
authored
Merge pull request #348 from sayuru-akash/main
feat: Add Kiro plugin for usage tracking
2 parents e2fc87c + 96eede6 commit 71ae900

7 files changed

Lines changed: 887 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ OpenUsage lives in your menu bar and shows you how much of your AI coding subscr
3333
- [**Factory / Droid**](docs/providers/factory.md) / standard, premium tokens
3434
- [**Gemini**](docs/providers/gemini.md) / pro, flash, workspace/free/paid tier
3535
- [**JetBrains AI Assistant**](docs/providers/jetbrains-ai-assistant.md) / quota, remaining
36+
- [**Kiro**](docs/providers/kiro.md) / credits, bonus credits, overages
3637
- [**Kimi Code**](docs/providers/kimi.md) / session, weekly
3738
- [**MiniMax**](docs/providers/minimax.md) / coding plan session
3839
- [**OpenCode Go**](docs/providers/opencode-go.md) / 5h, weekly, monthly spend limits

docs/providers/kiro.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
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.

plugins/kiro/icon.svg

Lines changed: 1 addition & 0 deletions
Loading

0 commit comments

Comments
 (0)