Skip to content

Feature request: according to #1382 add zcode support #1595

Description

@axisrow

What do you want to change?

Add ZCode (Z.ai's coding CLI, GLM-5.2) as a data source: ccusage zcode daily|monthly|session, plus ZCode rows in unified reports. Related to #1382.

Why?

I use ZCode alongside Claude Code and Codex and want to track all three in one report.

How? (optional)

ZCode keeps usage in a local SQLite database (~/.zcode/cli/db/db.sqlite), not JSONL. I have a working Rust adapter that reads it, prices GLM-5.2 from embedded pricing, and passes fixture-backed tests. Details and a sanitized sample are in the comment below. I'll open the PR here once approved.

Activity

  1. github-actions commented on Aug 12, 2026

    @github-actions
    Contributor

    This issue was auto-closed. Issues from new contributors are auto-closed by default.

    Maintainers review auto-closed issues and reopen worthwhile ones. Issues that do not meet the quality bar in CONTRIBUTING.md may not be reopened or receive a reply.

    Keep the issue short, concrete, and written in your own voice.

    If a maintainer replies lgtmi, your future issues will stay open. If a maintainer replies lgtm, your future issues and PRs will stay open.

    See CONTRIBUTING.md.

  2. pullfrog commented on Aug 12, 2026

    @pullfrog
    Contributor

    Assessment

    This is a worthwhile and technically feasible feature, and it follows the existing request in #1382. The repository currently has no zcode support or zcode-specific data samples, though, so the request is not yet implementation-ready. The key missing details are the local log directory and file layout, the exact JSONL record shape, and the supported report behavior.

    Before implementation, please provide a sanitized sample containing at least one assistant usage record, including its timestamp, model, token fields, message/session identifiers, and any precomputed cost fields. Please also confirm:

    • The zcode version and platform that produced the sample.
    • The default directory and filename pattern, plus whether zcode provides an environment variable or configuration override.
    • Whether the format is byte-for-byte compatible with Claude Code or only semantically similar.
    • Whether daily, monthly, and session reports are required, and whether weekly reports should be supported as well.
    • Which model identifiers zcode writes and whether those identifiers have public pricing metadata.

    Proposed implementation plan

    1. Validate the supplied fixture and path information against the current Claude adapter. Reuse or extract shared parsing only where the record semantics are genuinely identical; keep zcode path discovery and source-specific behavior isolated in a rust/adapters/zcode crate.
    2. Implement zcode path discovery, JSONL loading, timestamp/session/project extraction, token mapping, malformed-line handling, deduplication, and cost-mode behavior with fixture-backed tests. Document the source format in the adapter README files.
    3. Register the zcode command and adapter throughout the Rust CLI: command parsing and report validation, dispatch, --last handling, workspace dependencies, native packaging, unified report loading/detection, progress labels, agent names, and display labels.
    4. Add parser snapshots and CLI JSON assertions for ccusage zcode daily|monthly|session (and weekly if confirmed), plus unified-report tests proving zcode is detected when data exists and omitted when it does not. Verify token totals, model breakdowns, session grouping, date filters, and cost modes.
    5. Update the generated config schema and all user-facing documentation surfaces: README support tables, source guide, all-reports/source-support pages, environment-variable and configuration references, and VitePress navigation.
    6. Run the standard formatting, typecheck, Rust test, schema, and documentation validation commands before opening a PR.

    No implementation changes were made during this evaluation. With the fixture and path details above, this can be turned into a concrete implementation PR; without them, any adapter would be based on assumptions and could silently misattribute usage.

    Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | View workflow run | via Pullfrog | Using GPT Luna (free via Pullfrog for OSS) | 𝕏

  3. axisrow commented on Aug 12, 2026

    @axisrow
    ContributorAuthor

    Thanks for the checklist. Answers below, plus a sanitized sample and a ready implementation.

    ZCode version / platform: ZCode.app 3.7.5 (build 3.7.5.4641) on macOS (aarch64-apple-darwin). CLI usage data is written to a single global SQLite database, not JSONL — this differs from #1382's original assumption of an Anthropic-compatible JSONL transcript format.

    Default location / override: ~/.zcode/cli/db/db.sqlite. No documented env var for a custom path today; the adapter reads this fixed location the same way the Claude adapter reads its default directory.

    Format compatibility with Claude Code: Not compatible. ZCode is its own SQLite schema (session, model_usage, tool_usage tables), not a Claude-style JSONL transcript. model_usage is the source of truth for tokens; no cost is ever stored (GLM-5.2 runs on a flat-rate coding-plan subscription), so cost must be computed from pricing like Codex/Amp.

    Sanitized model_usage row (real row from a completed turn, ids truncated):

    id: usage_model_main_turn_msg_xxx
    session_id: sess_xxx
    turn_id: turn_xxx
    provider_id: builtin:zai-coding-plan
    model_id: GLM-5.2
    status: completed
    started_at: 1786420438822        -- epoch milliseconds
    completed_at: 1786420442120
    input_tokens: 12965              -- includes cache reads/writes (OpenAI-style folding)
    output_tokens: 50
    reasoning_tokens: 0
    cache_creation_input_tokens: 0
    cache_read_input_tokens: 11200
    computed_total_tokens: 13015
    

    Key semantic notes:

    • input_tokens already includes cache_read_input_tokens + cache_creation_input_tokens. Fresh input = input_tokens - cache_read_input_tokens - cache_creation_input_tokens.
    • Only status = 'completed' rows should count toward usage; running/error/cancelled are excluded.
    • Timestamps are epoch milliseconds, not seconds.
    • session table (id, directory, title, time_created, time_updated) gives project/session grouping for the session report.

    Report modes: daily, monthly, and session should work the same as other agents. Weekly is not required — it isn't offered as a standalone report for the other single-agent adapters either, so parity is enough.

    Model identifiers / pricing: Only GLM-5.2 is observed in the local data. Z.ai's published API pricing for GLM-5.2 (https://docs.z.ai/guides/overview/pricing) is $1.40/M input, $0.26/M cached input, $4.40/M output — same rates as GLM-5.1, so it slots into the existing glm_pricing helper in pricing.rs next to the other zai/glm-* entries.

    Status: I already have a working implementation against this schema — read-only SQLite adapter under rust/crates/ccusage/src/adapter/zcode/, wired into the CLI, config schema, and unified reports, counting only completed rows, normalizing cache-inclusive input tokens, and pricing GLM-5.2 from the embedded table. Fixture-backed tests pass (cargo test -p ccusage zcode), along with the CLI/config-schema snapshot tests. Draft PR on my fork for reference: axisrow#1 — happy to open the real PR here once this gets an lgtm.

  4. lengmodkx commented on Aug 12, 2026

    @lengmodkx

    Thanks for the thorough answers — I'm a separate user on the other major platform, so I can both confirm the schema @axisrow described and add one new observation from ZCode.app 3.7.6 on Windows (win32-x64, Windows 10.0.26200).

    Confirmation (Windows 3.7.6)

    ~/.zcode/cli/db/db.sqlite exists here too, with the same tables — model_usage (2409 rows), turn_usage, tool_usage, session (223 rows). Real row from a completed turn:

    id: usage_model_main_turn_msg_xxx_0
    session_id: sess_xxx
    turn_id: turn_xxx
    provider_id: 847d13c9-0568-4f2f-818e-8bd498e5d920     -- local UUID, not builtin:zai-*
    model_id: deepseek-v4-flash
    variant: max
    agent: zcode-agent
    mode: yolo
    status: completed
    started_at: 1786509843044                            -- epoch ms, confirmed
    completed_at: 1786509848621
    input_tokens: 70443                                  -- includes cache reads, confirmed:
    cache_creation_input_tokens: 0                       --   fresh = 70443 - 70144 = 299
    cache_read_input_tokens: 70144
    computed_total_tokens: 71123
    raw_usage_json: {"inputTokens":70443,"outputTokens":680,"totalTokens":71123,"cacheReadTokens":70144,"cacheWriteTokens":0}
    

    All the semantic notes from the earlier comment hold on Windows too: epoch milliseconds, input_tokens folds in cache reads/writes, and only status='completed' rows should count (we also see running/error states in the table).

    New observation: JSONL rollout files (3.7.6)

    Since 3.7.6, zcode also writes per-session JSONL files alongside the SQLite DB:

    • ~/.zcode/cli/rollout/model-io-sess_<session-uuid>.jsonl — one file per session, one record per API call
    • ~/.zcode/cli/log/zcode-YYYY-MM-DD.jsonl — per-day structured event log (startup/config events, no usage data)

    Each rollout record is the full request/response envelope and carries the same token data as model_usage.raw_usage_json (they're two views of the same event). Sanitized record:

    {
      "completedAt": "2026-08-12T04:38:10.555Z",
      "requestId": "7dfe9748-...",
      "attempt": 1,
      "model": { "modelId": "deepseek-v4-flash", "providerId": "847d13c9-...", "role": "main", "source": "session", "variant": "max" },
      "response": {
        "providerMetadata": { "anthropic": { "usage": { "input_tokens": 248, "output_tokens": 13, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 128 } } },
        "usage": { "inputTokens": 376, "outputTokens": 13, "totalTokens": 389, "cacheReadTokens": 128, "cacheWriteTokens": 0 }
      },
      "sessionId": "sess_308bb267-...",
      "turnId": "turn_9407d696-...",
      "querySource": "main_turn",
      "startedAt": "2026-08-12T04:38:01.824Z",
      "type": "model_io"
    }

    Note: response.usage.inputTokens = input_tokens + cache_read_input_tokens (376 = 248 + 128), and within one turnId every API call is its own record — dedup by requestId, not turnId.

    My read on this: SQLite is the authoritative source (it's the only one with the full 2409-row history here), and the rollout JSONL looks like a recent real-time/debug export that only covers recent sessions (3 files vs 223 sessions). Building the adapter on model_usage as @axisrow did is the right call; the JSONL exists mainly as a cross-check fixture.

    Pricing / cost

    Worth noting: not all zcode users are on a flat-rate plan like the GLM-5.2 coding-plan. Here the recorded models are deepseek-v4-flash and MiniMax-M3 (via MiniMax's Anthropic-compatible endpoint), both metered. model_id is whatever name the user configured on their provider and provider_id is a local UUID with no public mapping, so per-model pricing must stay user-configurable rather than keyed off provider_id.

    Reports

    daily, monthly, and session are all needed here. Weekly would be nice-to-have (we track weekly OKRs) but parity with the other adapters is fine if that's the scope.

    If it helps, I can attach a small sanitized fixture directory (a couple of model-io-sess_*.jsonl files + the matching model_usage rows) for the adapter tests.

  5. axisrow commented on Aug 12, 2026

    @axisrow
    ContributorAuthor

    Quick update: the implementation is merged into my fork's main and I've now validated it against my own real ZCode data (2 days, 31 sessions, ~85M tokens including cache reads):

    $ ccusage zcode daily
    2026-08-11  GLM-5.2  in: 1,319,025  out: 259,639  cache-read: 60,046,848  total: 61,625,512  cost: $18.60
    2026-08-12  GLM-5.2  in:   611,260  out: 136,175  cache-read: 22,962,688  total: 23,710,123  cost: $ 7.43
    

    Full local build/test also passes: cargo build -p ccusage --release, cargo fmt --check, and cargo test -p ccusage (357 passed, 0 failed).

    PR ready on my fork: axisrow#1

    Happy to open the real PR here whenever a maintainer gives an lgtm.

  6. uwe-schwarz commented on Aug 16, 2026

    @uwe-schwarz

    I let zcode itself implement it with the new commits, thanks @axisrow for the previous work.

    in zcode's own words:

    I've ported @axisrow's implementation onto current main (restructured onto the per-agent rust/adapters/ layout) and extended it: current zcode builds log GLM-5.3, not just GLM-5.2, so both are priced (embedded rates from the models.dev snapshot; --offline works). Semantics follow this thread: only status='completed' rows, input_tokens treated as cache-inclusive with fresh input = input − cache_read − cache_creation, epoch-millisecond timestamps, session.directory as the session project path, ZCODE_HOME with comma-separated archive homes. Custom-provider model ids (e.g. deepseek-v4-flash via a local provider) report zero cost with a missing-pricing warning, and user pricingOverrides on either the raw id or the zai/glm-5.x alias are honored.

    The branch is up at uwe-schwarz/ccusage#1 with fixture tests plus an end-to-end daily/monthly/session snapshot, validated against a real database (582+ completed rows). Happy to open the PR here — @axisrow since you offered to open it yourself once this gets an lgtm, let me know whether you'd rather take this port as a base or keep yours; either way you'd be co-authored.

  7. aseelye commented on Aug 18, 2026

    @aseelye

    I updated this work for ccusage's current per-adapter Rust architecture in #1614. It includes compatibility with the confirmed legacy session(id, directory) schema, additive normalization of cache-read and cache-creation tokens, provider-qualified Z.ai pricing, focused/unified reports, tests, and documentation.

    The contributor gate auto-closed the PR. Could a maintainer review this issue and reopen #1614 if the approach is appropriate? The PR also credits the earlier schema investigation and implementation in axisrow#1.

  8. axisrow commented on Aug 29, 2026

    @axisrow
    ContributorAuthor

    @aseelye Just a heads up — PRs from new contributors get auto-closed by a bot here unless a maintainer has replied lgtm/lgtmi first (see the bot message on this issue and on #1614). No maintainer has commented in this thread yet, so any of our PRs will keep getting closed automatically regardless of implementation quality.

    It'd help to get a maintainer's attention directly — could you (or anyone watching) ping @ryoppippi here? We (and lengmodkx, uwe-schwarz) clearly want zcode support, and a working, tested implementation already exists in my fork: axisrow#1 — happy to open the real PR the moment this gets an lgtm.

  9. axisrow commented on Aug 29, 2026

    @axisrow
    ContributorAuthor

    cc @lengmodkx @uwe-schwarz — tagging you both directly so GitHub actually notifies you (my previous comment mentioned you without @ by mistake). Same ask: if either of you has a way to get a maintainer's attention (@ryoppippi), that's the actual blocker here, not implementation quality.

  10. ryoppippi commented on Aug 31, 2026

    @ryoppippi
    Member

    Implemented and merged in #1675. The ZCode adapter now supports the requested usage data, provider-aware pricing, reports, and safe token aggregation.

  11. ryoppippi commented on Aug 31, 2026

    @ryoppippi
    Member

    Historical audit: this discussion was auto-closed by the legacy contributor gate. That closure did not assess technical importance.

    Audit result: resolved. A later merged change or the current main implementation covers this request. This item is kept for history and does not need to be reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttriage:resolvedResolved by a later change or current implementation.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions