ProdMetrics Agent Tracker
A VS Code / Kiro extension that forwards Kiro .agents/** task and conversation
completion files to the ProdMetrics backend. Install it once per developer and it
works in every workspace you open — no per-repo .kiro/hooks, no track-task.sh,
no jq, no per-repo install.
It replaces the per-repo hook + shell-script + dedup-ledger setup with a single
extension that:
- watches
**/.agents/**/*.{json,md} in every open workspace folder,
- content-hash dedups centrally (so unchanged files are not re-sent),
- routes task files to
task-events and conversation files to conversation-events,
- attributes events via your configured email + API token.
Record layout
Files under .agents/tasks/ follow a per-day/grouped layout:
- Conversations — one file per conversation under a per-day folder:
.agents/tasks/conversations/<yyyy-mm-dd>/<conversation-id>.json
(<yyyy-mm-dd> = the conversation's UTC first-touch date). These route to
conversation-events.
- Workflows / agent tasks — one folder per workflow run under a per-day folder,
holding any number of files that together form one patched record:
.agents/tasks/workflows/<yyyy-mm-dd>/<workflow-id>/*
(<workflow-id> = the workflow run id, e.g. wf_916592ec3fc5bcd9). These route to
task-events.
For these paths the POST body carries grouping keys derived from the path — day plus
conversationId (conversations) or workflowId (workflows) — so the backend can relate
every file of one conversation/workflow to a single per-day record. fileId stays the
full repo-relative path and one file is sent per POST. Legacy convo-* paths still route
to conversation-events for backward compatibility.
How it works
| Old per-repo piece |
Replaced by |
.kiro/hooks/*.json triggers |
FileSystemWatcher on **/.agents/** |
scripts/track-task.sh + jq |
src/extension.js + native JSON.parse / fetch |
scripts/track-task.env |
VS Code settings + SecretStorage for the token |
.kiro/.task-tracker-sent/*.hash |
content-hash ledger in globalState (shared across repos) |
A file is read on create/change, hashed, and POSTed only if its hash changed since
the last successful send. On HTTP failure or offline, it is NOT marked sent, so it
retries on the next change or manual sync.
Note: this covers the file-based forwarding your task/conversation trackers did.
The spec PostTaskExec non-file event is not a file on disk; if you still need
it, keep a minimal spec hook or wire it to a Kiro lifecycle API (if available).
Run it (development)
code extension/ (open this folder) — or in Kiro, open it as a folder.
- Press
F5 ("Run Extension") to launch an Extension Development Host.
- In the dev host, open any workspace that has a
.agents/ folder.
- Configure (see below), then edit/create an
.agents/**/completion.json and watch
the ProdMetrics Agent Tracker output channel.
No build step — the extension runs directly from the .js sources.
Kiro credit usage → database
Per-prompt Kiro credit consumption is forwarded to the backend and stored in the
credit_events collection, the same way .agents files land in kiro_events /
conversation_events.
Source. The Kiro Credit Tracker hooks run credit-prompt-tracker.py
(snapshot on prompt submit, record on stop), which appends one row per prompt
to ~/.kiro/credit-ledger.csv (columns: datetime, total_used, session_cost, remaining, limit, overages, reset_date, user_id, prompt). Those hooks/script are
installed separately (by the Kiro Credit Tracker extension); this extension only
reads the CSV they produce.
Forwarding. The CSV lives in the home dir, outside any workspace, so the
extension polls it with fs.watchFile. Each new, non-baseline row is mapped to a
type:"credit" event (ISO-UTC timestamp, session_cost, used, limit,
overages, resetDate, userId, prompt, a stable id/creditId) and POSTed
to POST /api/v1/credit-events. The backend groups entries by (user, UTC day)
and sums session_cost. Rows are deduped by a stable key (persisted in
globalState) and the backend upsert is idempotent, so re-sends never duplicate.
Attribution. Each event carries the configured prodmetricsTracker.userEmail,
which the backend resolves to an employee (the ledger's raw Kiro user_id is kept
on the entry but is not an employee id). Without an email or token the event falls
back to the default user. Baseline rows (where session_cost == total_used,
i.e. the tracker's first run or a billing-cycle reset) are skipped — they are not
a prompt's cost.
Live. Forwarding is live, like task/conversation events. The home-dir CSV is
outside any workspace, so a FileSystemWatcher cannot see it; instead fs.watch
on the ledger's directory delivers an OS change event the instant the Stop hook
writes a row, which is forwarded immediately (a 400 ms debounce coalesces the
snapshot+record writes). An fs.watchFile poll (creditLedgerPollMs) stays as a
safety net for filesystems where fs.watch misses events.
Command: ProdMetrics: Sync Kiro credit ledger now (manual catch-up). Settings:
creditLedgerEnabled, creditLedgerPath, creditLedgerPollMs, creditEventsUrl.
Settings (Preferences → Settings → "ProdMetrics"):
prodmetricsTracker.taskEventsUrl — task/agent endpoint (default points at prod).
prodmetricsTracker.conversationEventsUrl — conversation endpoint (blank = derived).
prodmetricsTracker.userEmail — your login email for attribution.
prodmetricsTracker.enabled — master on/off.
prodmetricsTracker.debounceMs — coalesce rapid writes (default 800ms).
Token: run ProdMetrics: Set API token from the Command Palette (stored encrypted in
SecretStorage, never in settings).
Commands
- ProdMetrics: Sync .agents files now — forward every
.agents file in the workspace.
- ProdMetrics: Set API token — store the bearer token securely.
- ProdMetrics: Clear sent-ledger (force re-send) — forget dedup markers so the next
sync re-sends everything (useful for testing).
The status-bar item ($(pulse) ProdMetrics) shows activity and runs a manual sync on click.
Package / install
From this repository:
npm install
npm --prefix webview-ui ci
npx vsce package --no-dependencies
That writes prodmetrics-agent-tracker-0.15.0.vsix. Install it with Extensions: Install from VSIX….
Publish to the Marketplace
Publisher short name: prodmetrics. The token is a Marketplace Manage personal access token for all accessible organizations. Put it in VSCE_PAT. Do not write the token into this file.
npm install
npm --prefix webview-ui ci
export VSCE_PAT="<Marketplace token>"
npx vsce publish --no-dependencies
npm run deploy runs the same publish. The webview is built first. GitLab uses that command with the masked variable VSCE_PAT.