---
url: /guide/copilot.md
---
# GitHub Copilot CLI Data Source (Beta)

> GitHub Copilot CLI support is experimental. The adapter reads local session-state and OpenTelemetry JSONL files.

ccusage can read GitHub Copilot CLI session-state and OpenTelemetry files as supported local data sources. It uses the same reporting experience as the rest of ccusage: responsive tables, JSON output, LiteLLM-based pricing, cache token accounting, and all-source aggregation.

## Focused Views

::: code-group

```bash [bunx (Recommended)]
bunx ccusage copilot --help
```

```bash [npx]
npx ccusage@latest copilot --help
```

```bash [pnpm]
pnpm dlx ccusage copilot --help
```

:::

## Data Source

The CLI reads Copilot session-state shutdown and usage-checkpoint events from `${COPILOT_HOME:-~/.copilot}/session-state/*/events.jsonl` by default. It also reads OpenTelemetry JSONL files recursively from `${COPILOT_HOME:-~/.copilot}/otel/**/*.jsonl` and includes the single explicit file pointed to by `COPILOT_OTEL_FILE_EXPORTER_PATH`. Set `COPILOT_HOME` to the Copilot data root when the default `~/.copilot` directory has been relocated.

Session-state files do not require OpenTelemetry configuration. Shutdown usage is cumulative per canonical session/model pair, and resumed sessions emit another shutdown snapshot. ccusage reports the first snapshot as-is and each later snapshot as the difference from its predecessor, so usage follows the resume dates while totals stay unchanged. For date-bounded reports, snapshots before `--since` remain available as subtraction baselines, and snapshots after `--until` are excluded. When both sources contain the same session/model pair, the session-state usage is used and matching OpenTelemetry rows are suppressed only when their timestamps are at or before the latest raw shutdown visible through `--until`; rows emitted after that timestamp by a resumed session are retained. A Copilot process restores the per-model breakdown of the session's last shutdown, so the calls of a process that ended without a shutdown (killed, crashed, or restarted by the app) are missing from every later one. When the OpenTelemetry rows of a pair outnumber the requests its shutdowns report, counted from the first shutdown interval that has OpenTelemetry rows, ccusage reports those rows instead of the shutdown intervals from that interval on. This comparison covers every shutdown, so a date-bounded report shows the same usage per day as an unbounded one. OpenTelemetry rows for other session/model pairs remain available. Chat spans that the CLI exports twice, with the response ID and usage of the same call, are counted once.

For session-state token usage, only `session.shutdown` events are used. For each `data.modelMetrics.<model>` entry, ccusage reads its `usage` fields and uses any positive `requests.count` for `messageCount`; each retained OpenTelemetry usage row contributes one message. `requests.cost` is ignored and costs continue to use ccusage's normal token pricing. In session-state data, `inputTokens` includes both cache buckets, so ccusage derives uncached input as `max(inputTokens - cacheReadTokens - cacheWriteTokens, 0)` before populating `inputTokens`; cache reads and cache writes are then reported separately. OpenTelemetry `gen_ai.usage.input_tokens` includes both cache buckets as well and is normalized the same way. `reasoningTokens` is a subset of `outputTokens`, so it is not added again to output, total tokens, or cost. Copilot model IDs with `-1m` or `-1m-internal` suffixes, such as `claude-opus-4.6-1m`, are normalized to their priced model name for pricing and source deduplication.

For example, a `claude-opus-4.7` shutdown with `inputTokens=100`, `outputTokens=50`, `cacheReadTokens=10`, and `cacheWriteTokens=20` is reported as 70 input tokens, 50 output tokens, 20 cache-creation tokens, and 10 cache-read tokens. With the embedded Opus pricing, its calculated cost is exactly `$0.00173`.

Copilot also records the credits a session has used: a session-wide `totalNanoAiu` on every `session.shutdown` and on the `session.usage_checkpoint` events written during the session. One AIU is one GitHub AI credit, billed at $0.01. The per-model breakdown only covers the running Copilot process, so a resumed or restarted session can shut down with an empty or partial `modelMetrics` while its session total still includes everything. ccusage compares the session total with the per-model `totalNanoAiu` values reported so far, at every shutdown and at each checkpoint after a session's last shutdown, which covers sessions that are still open or ended without a shutdown. Credits that stay unexplained at every later snapshot are reported as a cost-only row for the `unknown` model with zero tokens, dated at the first snapshot from which they stay unexplained. A breakdown that a later shutdown catches up on is not counted twice. Sessions without checkpoints, which come from older Copilot versions that restart both totals on every resume, sessions with a shutdown that lacks either credit total, and sessions that also have OpenTelemetry rows keep token-only reporting. These rows carry a precomputed cost, so `--mode calculate` reports them as $0.

Enable these variables before starting or resuming a Copilot CLI session when you want OTel data. Sessions that ran without OpenTelemetry file export remain readable from their session-state files.

```bash
export COPILOT_HOME="$HOME/.copilot"
export COPILOT_OTEL_ENABLED=true
export COPILOT_OTEL_EXPORTER_TYPE=file
mkdir -p "$COPILOT_HOME/otel"
export COPILOT_OTEL_FILE_EXPORTER_PATH="$COPILOT_HOME/otel/copilot-otel-$(date +%Y%m%d-%H%M%S).jsonl"
```

```text
${COPILOT_HOME:-~/.copilot}/
├── session-state/
│   └── <session-id>/
│       └── events.jsonl
└── otel/
    └── *.jsonl
```

## Report Views

| Focused view              | Description                        | See also                                |
| ------------------------- | ---------------------------------- | --------------------------------------- |
| `ccusage copilot daily`   | Aggregate usage by date            | [Daily Usage](/guide/daily-reports)     |
| `ccusage copilot monthly` | Aggregate usage by month           | [Monthly Usage](/guide/monthly-reports) |
| `ccusage copilot session` | Group usage by Copilot session IDs | [Session Usage](/guide/session-reports) |

These views support `--json` for structured output, `--compact` for narrow terminals, and `--offline` for cached pricing data.

## What Gets Calculated

* **Token usage** - cumulative session shutdown snapshots are converted into per-resume intervals, and OTel rows replace them when the shutdowns miss calls; OTel chat spans are preferred within the OTel source, with inference logs and agent-turn logs used as fallbacks.
* **Cache tokens** - cache read and cache creation token attributes are counted when present.
* **Input tokens** - session-state `inputTokens` and OTel `gen_ai.usage.input_tokens` are normalized to uncached input after subtracting cache reads and cache writes.
* **Reasoning tokens** - session-state reasoning tokens are already included in output tokens; OpenTelemetry reasoning is included when total usage metadata shows it is separate.
* **Pricing** - costs are calculated from LiteLLM pricing data using the normalized model name; both `-1m` and `-1m-internal` suffixes are removed.
* **Unattributed credits** - session credits missing from the per-model breakdown are reported as `unknown` rows at $0.01 per AI credit.

## Environment Variables

| Variable                          | Description                                          |
| --------------------------------- | ---------------------------------------------------- |
| `COPILOT_HOME`                    | Copilot data root; defaults to `~/.copilot`          |
| `COPILOT_OTEL_FILE_EXPORTER_PATH` | Explicit Copilot OpenTelemetry JSONL file to include |
| `LOG_LEVEL`                       | Adjust verbosity (0 silent ... 5 trace)              |

## Troubleshooting

::: details No Copilot usage data found
Ensure Copilot session-state files exist under `${COPILOT_HOME:-~/.copilot}/session-state/<session-id>/events.jsonl`, or enable OpenTelemetry file export and place exported `.jsonl` files under `${COPILOT_HOME:-~/.copilot}/otel/`.

If you are using `copilot --resume`, session-state events remain available without OpenTelemetry. OTel-only activity from sessions started without file export cannot be recovered by ccusage.
:::

::: details Costs showing as $0.00
If a model is not in LiteLLM's database, the cost will be $0.00. [Open an issue](https://github.com/ccusage/ccusage/issues/new) to request alias support.
:::
