Skip to content

Commit 7e0e3af

Browse files
committed
Add IBM Bob provider
1 parent d9acd8c commit 7e0e3af

17 files changed

Lines changed: 353 additions & 26 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Added (CLI)
6+
- **IBM Bob provider.** CodeBurn now discovers IBM Bob IDE task history from
7+
`User/globalStorage/ibm.bob-code/tasks/<task-id>/` under both the GA
8+
`IBM Bob` application data folder and preview-era `Bob-IDE` folder. The
9+
provider reuses the Cline-family `ui_messages.json` parser for token/cost
10+
records, reads `api_conversation_history.json` for model tags when present,
11+
falls back to `ibm-bob-auto` pricing otherwise, and appears in CLI,
12+
dashboard, JSON, docs, and the macOS provider tabs. Closes #248.
13+
314
## 0.9.8 - 2026-05-10
415

516
### Added (CLI)

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<a href="https://github.com/sponsors/iamtoruk"><img src="https://img.shields.io/badge/sponsor-♥-ea4aaa?logo=github" alt="Sponsor" /></a>
1414
</p>
1515

16-
CodeBurn tracks token usage, cost, and performance across **18 AI coding tools**. It breaks down spending by task type, model, tool, project, and provider so you can see exactly where your budget goes.
16+
CodeBurn tracks token usage, cost, and performance across **19 AI coding tools**. It breaks down spending by task type, model, tool, project, and provider so you can see exactly where your budget goes.
1717

1818
Everything runs locally. No wrapper, no proxy, no API keys. CodeBurn reads session data directly from disk and prices every call using [LiteLLM](https://github.com/BerriAI/litellm).
1919

@@ -104,6 +104,7 @@ Arrow keys switch between Today, 7 Days, 30 Days, Month, and 6 Months (use `--fr
104104
| <img src="assets/providers/cursor-agent.jpg" width="28" /> | cursor-agent | Yes | [cursor-agent.md](docs/providers/cursor-agent.md) |
105105
| <img src="assets/providers/gemini.png" width="28" /> | Gemini CLI | Yes | [gemini.md](docs/providers/gemini.md) |
106106
| <img src="assets/providers/copilot.jpg" width="28" /> | GitHub Copilot | Yes | [copilot.md](docs/providers/copilot.md) |
107+
| <img src="assets/providers/ibm-bob.svg" width="28" /> | IBM Bob | Yes | [ibm-bob.md](docs/providers/ibm-bob.md) |
107108
| <img src="assets/providers/kiro.png" width="28" /> | Kiro | Yes | [kiro.md](docs/providers/kiro.md) |
108109
| <img src="assets/providers/opencode.png" width="28" /> | OpenCode | Yes | [opencode.md](docs/providers/opencode.md) |
109110
| <img src="assets/providers/openclaw.jpg" width="28" /> | OpenClaw | Yes | [openclaw.md](docs/providers/openclaw.md) |
@@ -119,7 +120,7 @@ Arrow keys switch between Today, 7 Days, 30 Days, Month, and 6 Months (use `--fr
119120

120121
Each provider doc lists the exact data location, storage format, and known quirks. Linux and Windows paths are detected automatically. If a path has changed or is wrong, please [open an issue](https://github.com/getagentseal/codeburn/issues).
121122

122-
Provider logos are trademarks of their respective owners. The icon set was sourced from [tokscale](https://github.com/junhoyeo/tokscale) (MIT) plus official vendor assets, used under nominative fair use for the purpose of identifying supported tools.
123+
Provider logos are trademarks of their respective owners. The icon set was sourced from [tokscale](https://github.com/junhoyeo/tokscale) (MIT), official vendor assets, and simple provider identifiers, used under nominative fair use for the purpose of identifying supported tools.
123124

124125
CodeBurn auto-detects which AI coding tools you use. If multiple providers have session data on disk, press `p` in the dashboard to toggle between them.
125126

@@ -378,6 +379,8 @@ These are starting points, not verdicts. A 60% cache hit on a single experimenta
378379

379380
**OpenClaw** stores agent sessions as JSONL at `~/.openclaw/agents/*.jsonl`. Also checks legacy paths `.clawdbot`, `.moltbot`, `.moldbot`. Token usage comes from assistant message `usage` blocks; model from `modelId` or `message.model` fields.
380381

382+
**IBM Bob** stores IDE task history in `User/globalStorage/ibm.bob-code/tasks/<task-id>/` under the IBM Bob application data directory. CodeBurn reads `ui_messages.json` for API request token/cost records and `api_conversation_history.json` for the selected model, with support for both GA (`IBM Bob`) and preview (`Bob-IDE`) app data folders.
383+
381384
**Roo Code / KiloCode** are Cline-family VS Code extensions. CodeBurn reads `ui_messages.json` from each task directory in VS Code's `globalStorage`, filtering `type: "say"` entries with `say: "api_req_started"` to extract token counts.
382385

383386
CodeBurn deduplicates messages (by API message ID for Claude, by cumulative token cross-check for Codex, by conversation/timestamp for Cursor, by session ID for Gemini, by session+message ID for OpenCode, by responseId for Pi/OMP), filters by date range per entry, and classifies each turn.

assets/providers/ibm-bob.svg

Lines changed: 6 additions & 0 deletions
Loading

docs/architecture.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,14 @@ type Provider = {
128128
}
129129
```
130130
131-
`src/providers/index.ts` registers eighteen providers across two tiers:
131+
`src/providers/index.ts` registers nineteen providers across two tiers:
132132
133-
- **Eager**: `claude`, `codex`, `copilot`, `droid`, `gemini`, `kilo-code`, `kiro`, `openclaw`, `pi`, `omp`, `qwen`, `roo-code`. Imported at module load.
133+
- **Eager**: `claude`, `codex`, `copilot`, `droid`, `gemini`, `ibm-bob`, `kilo-code`, `kiro`, `openclaw`, `pi`, `omp`, `qwen`, `roo-code`. Imported at module load.
134134
- **Lazy**: `antigravity`, `goose`, `cursor`, `opencode`, `cursor-agent`, `crush`. Imported via dynamic `import()` so the heavy dependencies (SQLite, protobuf) do not touch users who do not have those tools installed.
135135
136136
Both lists hit the same `getAllProviders()` aggregator. A failed lazy import is silent and excludes that provider from the run.
137137
138-
`src/providers/vscode-cline-parser.ts` is a shared helper consumed by `kilo-code` and `roo-code`. It is not registered as a provider on its own.
138+
`src/providers/vscode-cline-parser.ts` is a shared helper consumed by `ibm-bob`, `kilo-code`, and `roo-code`. It is not registered as a provider on its own.
139139
140140
For the per-provider data location, storage format, parser quirks, and test coverage, see `docs/providers/`.
141141

docs/providers/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ For the architectural picture, see `../architecture.md`.
1515
| [Copilot](copilot.md) | JSONL | `src/providers/copilot.ts` | `tests/providers/copilot.test.ts` |
1616
| [Droid](droid.md) | JSONL | `src/providers/droid.ts` | `tests/providers/droid.test.ts` |
1717
| [Gemini](gemini.md) | JSON / JSONL | `src/providers/gemini.ts` | none |
18+
| [IBM Bob](ibm-bob.md) | JSON | `src/providers/ibm-bob.ts` | `tests/providers/ibm-bob.test.ts` |
1819
| [KiloCode](kilo-code.md) | JSON | `src/providers/kilo-code.ts` | `tests/providers/kilo-code.test.ts` |
1920
| [Kiro](kiro.md) | JSON | `src/providers/kiro.ts` | `tests/providers/kiro.test.ts` |
2021
| [OpenClaw](openclaw.md) | JSONL | `src/providers/openclaw.ts` | `tests/providers/openclaw.test.ts` |
@@ -38,7 +39,7 @@ For the architectural picture, see `../architecture.md`.
3839

3940
| Helper | Used by | Source |
4041
|---|---|---|
41-
| [vscode-cline-parser](vscode-cline-parser.md) | `kilo-code`, `roo-code` | `src/providers/vscode-cline-parser.ts` |
42+
| [vscode-cline-parser](vscode-cline-parser.md) | `ibm-bob`, `kilo-code`, `roo-code` | `src/providers/vscode-cline-parser.ts` |
4243

4344
## File Format
4445

docs/providers/ibm-bob.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# IBM Bob
2+
3+
IBM Bob IDE task history.
4+
5+
- **Source:** `src/providers/ibm-bob.ts`
6+
- **Loading:** eager (`src/providers/index.ts`)
7+
- **Test:** `tests/providers/ibm-bob.test.ts`
8+
9+
## Where It Reads From
10+
11+
IBM Bob stores IDE task history below `User/globalStorage/ibm.bob-code/tasks/` in the application data directory.
12+
13+
Default paths checked:
14+
15+
| Platform | Paths |
16+
|---|---|
17+
| macOS | `~/Library/Application Support/IBM Bob/User/globalStorage/ibm.bob-code/`, `~/Library/Application Support/Bob-IDE/User/globalStorage/ibm.bob-code/` |
18+
| Windows | `%APPDATA%/IBM Bob/User/globalStorage/ibm.bob-code/`, `%APPDATA%/Bob-IDE/User/globalStorage/ibm.bob-code/` |
19+
| Linux | `$XDG_CONFIG_HOME/IBM Bob/User/globalStorage/ibm.bob-code/`, `$XDG_CONFIG_HOME/Bob-IDE/User/globalStorage/ibm.bob-code/` with `~/.config` fallback |
20+
21+
The `Bob-IDE` paths cover the preview-era app name that some installs used before the GA `IBM Bob` directory.
22+
23+
## Storage Format
24+
25+
Each task is a directory under `tasks/<task-id>/` and must contain `ui_messages.json`.
26+
27+
CodeBurn parses the same Cline-family UI event format used by Roo Code and KiloCode:
28+
29+
- `ui_messages.json` entries with `type: "say"` and `say: "api_req_started"` contain serialized token/cost metrics.
30+
- `ui_messages.json` user text entries seed the turn's first user message.
31+
- `api_conversation_history.json` is optional and is used to extract the selected model from `<model>...</model>` environment details when present.
32+
- `task_metadata.json` may exist upstream, but CodeBurn does not need it for usage math today.
33+
34+
If no model tag is present, the parser uses `ibm-bob-auto`, which is priced through the same conservative Sonnet fallback used for Cline-family auto modes.
35+
36+
## Caching
37+
38+
None at the provider level.
39+
40+
## Deduplication
41+
42+
Per `<providerName>:<taskId>:<apiRequestIndex>` via `vscode-cline-parser.ts`.
43+
44+
## Quirks
45+
46+
- IBM Bob has shipped under both `IBM Bob` and `Bob-IDE` application data folder names.
47+
- This provider intentionally covers the IDE task-history format. Bob Shell's `~/.bob` checkpoint data is a separate storage surface and is not parsed until we have a stable usage schema fixture.
48+
- The shared Cline parser does not currently extract individual tool names from UI messages, so tool breakdowns are empty for IBM Bob just like Roo Code and KiloCode.
49+
50+
## When Fixing A Bug Here
51+
52+
1. Check whether the install uses `IBM Bob` or `Bob-IDE` as the application data directory.
53+
2. Confirm the task folder still contains `ui_messages.json` and `api_conversation_history.json`.
54+
3. If the UI message schema changed, add a focused fixture to `tests/providers/ibm-bob.test.ts`.
55+
4. If the change also affects Roo Code or KiloCode, update `src/providers/vscode-cline-parser.ts` and run all three provider test files.
Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
# vscode-cline-parser (Shared Helper)
22

3-
Shared discovery and parsing for VS Code extensions descended from Cline.
3+
Shared discovery and parsing for Cline-family task folders.
44

55
- **Source:** `src/providers/vscode-cline-parser.ts`
6-
- **Loading:** not a provider; imported by `kilo-code.ts` and `roo-code.ts`.
7-
- **Test:** none directly. Coverage comes from `tests/providers/kilo-code.test.ts` and `tests/providers/roo-code.test.ts`.
6+
- **Loading:** not a provider; imported by `ibm-bob.ts`, `kilo-code.ts`, and `roo-code.ts`.
7+
- **Test:** none directly. Coverage comes from `tests/providers/ibm-bob.test.ts`, `tests/providers/kilo-code.test.ts`, and `tests/providers/roo-code.test.ts`.
88

99
## What it does
1010

1111
Two responsibilities:
1212

13-
1. `discoverClineTasks(extensionId)` walks VS Code's `globalStorage/<extensionId>/tasks/` directories and returns one source per task that has a `ui_messages.json` file (`vscode-cline-parser.ts:25-50`).
14-
2. `createClineParser` reads each task's `ui_messages.json` and `api_conversation_history.json`, extracts model, tools, and token counts, and yields `ParsedProviderCall` objects.
13+
1. `discoverClineTasks(extensionId)` walks VS Code's `globalStorage/<extensionId>/tasks/` directories and returns one source per task that has a `ui_messages.json` file.
14+
2. `discoverClineTasksInBaseDirs(baseDirs)` does the same for non-VS Code apps with compatible task storage, such as IBM Bob.
15+
3. `createClineParser` reads each task's `ui_messages.json` and `api_conversation_history.json`, extracts model and token counts, and yields `ParsedProviderCall` objects.
1516

1617
## Storage layout
1718

@@ -25,25 +26,25 @@ Per task directory:
2526

2627
## Model resolution
2728

28-
The model is extracted from `api_conversation_history.json` by searching user message content blocks for a `<model>...</model>` tag (`vscode-cline-parser.ts:54-72`). Falls back to `cline-auto` if no tag is found.
29+
The model is extracted from `api_conversation_history.json` by searching user message content blocks for a `<model>...</model>` tag. Falls back to the provider-supplied auto model (`cline-auto` by default) if no tag is found.
2930

3031
## Token extraction
3132

32-
From `api_req_started` entries inside `ui_messages.json`. Each such entry's `text` field is JSON-parsed; the parsed object holds `tokensIn`, `tokensOut`, `cacheReads`, `cacheWrites`, and (optionally) `cost` (`vscode-cline-parser.ts:119-134`).
33+
From `api_req_started` entries inside `ui_messages.json`. Each such entry's `text` field is JSON-parsed; the parsed object holds `tokensIn`, `tokensOut`, `cacheReads`, `cacheWrites`, and (optionally) `cost`.
3334

34-
If `cost` is present, it is used directly. If not, `calculateCost` from `src/models.ts` computes it from tokens (`vscode-cline-parser.ts:139`).
35+
If `cost` is present, it is used directly. If not, `calculateCost` from `src/models.ts` computes it from tokens.
3536

3637
## Deduplication
3738

38-
Per `<providerName>:<taskId>:<index>` where `index` is the position of the `api_req_started` entry within `ui_messages.json` (`vscode-cline-parser.ts:109`).
39+
Per `<providerName>:<taskId>:<index>` where `index` is the position of the `api_req_started` entry within `ui_messages.json`.
3940

4041
## Quirks
4142

42-
- Only the **first** user message is emitted as `userMessage` in the `ParsedProviderCall` (`vscode-cline-parser.ts:157`). Subsequent user turns are accounted but not surfaced.
43+
- Only the **first** user message is emitted as `userMessage` in the `ParsedProviderCall`. Subsequent user turns are accounted but not surfaced.
4344
- The model regex looks inside content blocks, not at top-level fields. Some Cline-derivative extensions emit the model elsewhere; if you add support for one, branch on extension ID rather than rewriting the regex.
4445

4546
## When fixing a bug here
4647

47-
1. A change here ripples to **both** KiloCode and Roo Code. Run both test files (`tests/providers/kilo-code.test.ts` and `tests/providers/roo-code.test.ts`) before opening a PR.
48+
1. A change here ripples to IBM Bob, KiloCode, and Roo Code. Run all three provider test files before opening a PR.
4849
2. If you find that one of the two extensions emits a different shape, branch on the extension ID parameter that the discovery function already takes; do not duplicate the parser.
49-
3. If you add support for a third Cline-derivative extension, register it as a thin wrapper file in the same shape as `kilo-code.ts` and `roo-code.ts`.
50+
3. If you add support for another Cline-family task store, register it as a thin wrapper file in the same shape as `ibm-bob.ts`, `kilo-code.ts`, and `roo-code.ts`.

mac/Sources/CodeBurnMenubar/AppStore.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,7 @@ enum ProviderFilter: String, CaseIterable, Identifiable {
725725
case copilot = "Copilot"
726726
case droid = "Droid"
727727
case gemini = "Gemini"
728+
case ibmBob = "IBM Bob"
728729
case kiro = "Kiro"
729730
case kiloCode = "KiloCode"
730731
case openclaw = "OpenClaw"
@@ -742,6 +743,7 @@ enum ProviderFilter: String, CaseIterable, Identifiable {
742743
case .cursor: ["cursor", "cursor agent"]
743744
case .rooCode: ["roo-code", "roo code"]
744745
case .kiloCode: ["kilo-code", "kilocode"]
746+
case .ibmBob: ["ibm-bob", "ibm bob"]
745747
case .openclaw: ["openclaw"]
746748
default: [rawValue.lowercased()]
747749
}
@@ -756,6 +758,7 @@ enum ProviderFilter: String, CaseIterable, Identifiable {
756758
case .copilot: "copilot"
757759
case .droid: "droid"
758760
case .gemini: "gemini"
761+
case .ibmBob: "ibm-bob"
759762
case .kiloCode: "kilo-code"
760763
case .kiro: "kiro"
761764
case .openclaw: "openclaw"

mac/Sources/CodeBurnMenubar/Views/AgentTabStrip.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ extension ProviderFilter {
345345
case .copilot: return Color(red: 0x6D/255.0, green: 0x8F/255.0, blue: 0xA6/255.0)
346346
case .droid: return Color(red: 0x7C/255.0, green: 0x3A/255.0, blue: 0xED/255.0)
347347
case .gemini: return Color(red: 0x44/255.0, green: 0x85/255.0, blue: 0xF4/255.0)
348+
case .ibmBob: return Color(red: 0x0F/255.0, green: 0x62/255.0, blue: 0xFE/255.0)
348349
case .kiloCode: return Color(red: 0x00/255.0, green: 0x96/255.0, blue: 0x88/255.0)
349350
case .kiro: return Color(red: 0x4A/255.0, green: 0x9E/255.0, blue: 0xC4/255.0)
350351
case .openclaw: return Color(red: 0xDA/255.0, green: 0x70/255.0, blue: 0x56/255.0)

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"claude-code",
2222
"cursor",
2323
"codex",
24+
"ibm-bob",
2425
"opencode",
2526
"pi",
2627
"ai-coding",

0 commit comments

Comments
 (0)