Cognition Devin CLI local usage tracking.
- Source:
src/providers/devin.ts - Loading: eager (
src/providers/index.ts) - Test:
tests/providers/devin.test.ts
Devin CLI data lives under:
~/.local/share/devin/cli/
The MVP usage source is transcript JSON:
~/.local/share/devin/cli/transcripts/*.json
The provider also reads:
~/.local/share/devin/cli/sessions.db
sessions.db is enrichment only. It supplies project path/name, model fallback,
timestamp fallback, and hidden-session filtering. It is not the source of usage
or billing.
Devin reports spend in ACUs. CodeBurn reports provider cost through costUSD,
so Devin stays disabled until a positive finite ACU-to-USD rate is configured:
{
"devin": {
"acuUsdRate": 2.25
}
}The config file is:
~/.config/codeburn/config.json
The macOS Settings window writes this value from the Devin tab. There is no environment-variable override and no default rate. Do not hardcode a universal ACU price; Devin ACU pricing is account/contract dependent.
When the rate is missing or invalid, discoverSessions() returns [] and the
parser yields no calls. Devin remains registered as a provider, but it does not
appear in CLI/UI results until configured.
Transcript root is a JSON object following the ATIF-v1.7 trajectory schema,
with Devin-specific additions such as per-step metadata and extra. The
parser does not validate schema_version; it only requires a parseable object
with steps[].
Core fields include session_id, agent.model_name, agent.extra (Devin
backend/permission info), final_metrics, and steps[].
Steps now support two metric sources. The parser checks step.metrics first
(the standard ATIF location) and falls back to step.metadata.metrics (the
legacy Devin location). Similarly, ACU cost is read from
step.metadata.committed_acu_cost first, falling back to
step.extra.committed_acu_cost.
Messages can be a plain string or an array of ContentPart objects (text or
image), following the ATIF v1.6+ multimodal content model. The parser
normalises both forms when extracting user messages.
Each counted step can provide:
step_idmetadata.committed_acu_cost(orextra.committed_acu_cost)metrics.prompt_tokens(ormetadata.metrics.input_tokens)metrics.completion_tokens(ormetadata.metrics.output_tokens)metrics.extra.cache_creation_input_tokens(ormetadata.metrics.cache_creation_tokens)metrics.cached_tokens(ormetadata.metrics.cache_read_tokens)metadata.created_atmetadata.generation_model(orextra.generation_model)metadata.request_idtool_calls[].function_nameobservation.results[](tool output; not parsed for usage)
User-input steps (metadata.is_user_input === true) are skipped. Non-user
steps are included only if they have positive ACU usage or positive token usage.
ACU cost is per step, not cumulative. The provider reads
metadata.committed_acu_cost first, falling back to
extra.committed_acu_cost, then converts with:
costUSD = committed_acu_cost * devin.acuUsdRate
Token-only steps are still included when they have positive token metrics, but
their costUSD is 0 if committed_acu_cost is absent from both locations.
src/parser.ts preserves Devin's provider-supplied costUSD instead of
re-pricing it through LiteLLM.
The provider currently reads these columns from sessions:
| Column | Use |
|---|---|
id |
join key with transcript session_id during parsing; discovery uses the transcript filename before .json |
working_directory |
projectPath and derived project name |
model |
model fallback |
title |
project name fallback |
created_at |
timestamp fallback |
last_activity_at |
preferred session timestamp fallback |
hidden |
skip hidden sessions |
message_nodes, prompt_history, and tool_call_state are not parsed yet.
Step timestamps come from metadata.created_at, falling back to
sessions.last_activity_at, then sessions.created_at.
Transcript step timestamps are passed through as ATIF string timestamps.
Numeric normalization is only applied to sessions.db timestamps:
- less than
10_000_000_000: seconds - otherwise: milliseconds
Model names resolve in this order:
step.metadata.generation_modelstep.model_nametranscript.agent.model_namesessions.modeldevin
No provider-level cache.
The normal session cache stores parsed provider calls, but Devin is always
reparsed by src/parser.ts because sessions.db can change without the
transcript JSON fingerprint changing.
devin:<sessionId>:<step.step_id>
The provider name is part of the key via the devin: prefix.
- The transcript directory has usage;
sessions.dbis enrichment only. committed_acu_costis per-generation/per-step ACU usage. Never treat it as cumulative. It can appear inmetadata(legacy) orextra(ATIF v1.7); the provider checks both.- Token metrics can live in
step.metrics(standard ATIF) orstep.metadata.metrics(legacy Devin). The provider checksstep.metricsfirst, falling back tometadata. - Step messages can be a plain string or an array of
ContentPartobjects (text/image). The parser normalises both when extracting user messages. - There is no default ACU-to-USD rate. Missing config intentionally hides Devin.
- Hidden sessions from
sessions.dbare skipped in discovery and parsing. - Tool names come directly from
tool_calls[].function_name; the provider assumes valid ATIF tool-call records. - If SQLite is unavailable or
sessions.dbcannot be opened, the provider still parses transcripts without enrichment.
-
First check whether
~/.config/codeburn/config.jsoncontains a validdevin.acuUsdRate. Without it, no Devin sessions should appear. -
For usage total bugs, compare against (ACU cost can live in
metadataorextra):jq '[.steps[] | select(.metadata.is_user_input != true) | (.metadata.committed_acu_cost // .extra.committed_acu_cost // 0)] | add' ~/.local/share/devin/cli/transcripts/<session>.json
-
If project/model/timestamp metadata is wrong, inspect
sessions.db, not the transcript. -
If a hidden session appears, check the
hiddencolumn. Discovery can only hide sessions whose transcript filename matchessessions.id; parsing uses the transcriptsession_idwhen present. -
Run
tests/providers/devin.test.tsafter parser changes. It covers ACU conversion, disabled-until-configured behavior, timestamp parsing, deduplication, hidden sessions,sessions.dbenrichment, ATIF v1.7 multimodal messages,step.metricsvsmetadata.metricspriority, andextra.committed_acu_costfallback.