codeburn/docs/providers/cline-cli.md
Rick Culpepper (claude) 448d470049 feat(providers): add cline-cli provider for Cline CLI sessions
The Cline CLI (npm `cline`, 3.x) stores sessions as
<sessions>/<id>/<id>.json + <id>.messages.json. The existing `cline`
provider only discovers tasks/<id>/ui_messages.json, so every CLI session
was silently reported as $0.00 — no warning, not even under --verbose.

Adds `cline-cli` as its own provider rather than a third root on `cline`,
leaving the shared Cline-family parser (Roo Code, KiloCode, IBM Bob)
untouched. It mirrors the CLI's own root resolution
(CLINE_SESSION_DATA_DIR -> CLINE_DATA_DIR -> CLINE_DIR -> ~/.cline),
implements probeRoots() so `doctor` can tell "not installed" from "wrong
override", emits one call per assistant message's `metrics` block, and
falls back to the session rollup when a session carries none. The
fallback reads `usage`, not `aggregateUsage`, which folds in spawned
subagents that are themselves separate session directories.

Two supporting changes, both required for CLI costs to report correctly:

- parser.ts re-priced cline-cli calls from tokens because the provider
  was not on the reported-cost allowlist, inflating a real 12-session
  local sample from $1.11 to $3.92.
- session-cache.ts gains the matching PROVIDER_ENV_VARS entry (so a
  changed override invalidates) and a `reported-cost-v1` parse version
  (so sessions cached before the allowlist fix re-parse once instead of
  being re-priced forever).

Cost is treated as metered only when actually present and non-negative,
so a metered $0 stays reported while a missing or negative cost falls
back to token pricing — applied identically on the per-message and
rollup paths. Timestamps promote a seconds-resolution value rather than
silently landing in 1970, matching the guard kiro.ts uses.

CLINE_DIR / CLINE_DATA_DIR / CLINE_SESSION_DATA_DIR are added to the test
env-isolation list so a developer's real sessions cannot bleed into
fixtures.

The VS Code variant discovery bug reported alongside this in #874 is
deliberately NOT fixed here — it shipped in #882.

Verified against 18 real local sessions: 142 calls, 4,934,762 input /
224,561 output tokens, and a cost matching the CLI's own metered total to
the cent. `codeburn doctor` reports "Cline CLI  OK".

Refs: #874
2026-08-04 02:45:16 +03:00

3.4 KiB

Cline CLI

The Cline command-line agent (npm cline, 3.x). Separate from the Cline provider, which reads the VS Code extension's task tree.

  • Source: src/providers/cline-cli.ts
  • Loading: eager (src/providers/index.ts)
  • Test: tests/providers/cline-cli.test.ts

Where it reads from

One root, resolved exactly as the CLI resolves it — each level independently overridable:

Level Env var Default
sessions CLINE_SESSION_DATA_DIR <data>/sessions
data CLINE_DATA_DIR <root>/data
root CLINE_DIR ~/.cline

A directory is a session only when it contains <sessionId>/<sessionId>.json. probeRoots() reports the resolved sessions dir, so codeburn doctor distinguishes "CLI not installed" from "override pointing somewhere else".

Storage format

sessions/<sessionId>/
  <sessionId>.json           metadata + rolled-up usage
  <sessionId>.messages.json  per-message metrics

<sessionId>.json carries session_id, provider, model, cwd, workspace_root, started_at / ended_at, messages_path, and a metadata.usage rollup (inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens, totalCost).

<sessionId>.messages.json holds { version, updated_at, agent, sessionId, messages[], system_prompt }. Assistant messages carry Anthropic-style content blocks (thinking / text / tool_use) plus:

"modelInfo": { "id": "z-ai/glm-5.2", "provider": "cline-pass" },
"metrics": { "inputTokens": 6937, "outputTokens": 213,
             "cacheReadTokens": 0, "cacheWriteTokens": 0, "cost": 0.002108502 }

One metrics block becomes one parsed call. Dedup key: cline-cli:<sessionId>:<messageId>.

Caching

None at the provider level; the metadata file is the cached source path and the normal parser/cache layers apply.

Quirks

  • provider in the session file is the upstream LLM route (e.g. cline-pass), not the tool. The codeburn provider name is always cline-cli.
  • Model strings are not normalized by the CLI. The same model appears as z-ai/glm-5.2, cline-pass/glm-5.2, and GLM-5.2 across sessions, so pricing lookups may need a model-alias.
  • Cost is reported per message, so costIsEstimated is false on the normal path; it falls back to calculateCost only when a message omits cost.
  • Rollup fallback. A session whose messages carry no metrics (interrupted, or an older layout) emits a single call from metadata.usage. This reads usage, deliberately not aggregateUsage / aggregatedAgentsCost, which fold in spawned subagents that are themselves separate session directories and would double count.
  • messages_path is absolute and goes stale when a session directory is copied between machines, so the co-located <sessionId>.messages.json is preferred and messages_path is only the fallback.
  • Tool names differ from the extension's. run_commands, read_files, search_codebase, editor, apply_patch, fetch_web_content, skills, spawn_agent, and the team_* family. run_commands carries a JSON-encoded array of command lines in a single string field.

When fixing a bug here

  1. Reproduce with a minimal session directory: <id>.json plus <id>.messages.json.
  2. Run tests/providers/cline-cli.test.ts.
  3. This provider shares no code with vscode-cline-parser.ts — changes here cannot affect Cline, Roo Code, KiloCode, or IBM Bob.