Skip to content

Add Zed agent provider (threads.db / zstd JSON schema documented) #480

Description

@chatzinikolakisk

Summary

Add a CodeBurn provider for Zed's built-in AI agent.

In #196 a maintainer noted Zed's agent usage is invisible to CodeBurn and that "Zed provider support is on the roadmap." That issue has since been closed (it was really about Cursor misattribution + the classifier). There doesn't appear to be a tracking issue for the actual Zed provider, so opening one here.

I use Zed daily and have inspected the real on-disk format on macOS, so I can build and validate this against real sessions per the contributing guide. Filing first to confirm the approach before opening a PR.

Where Zed stores agent data

Unlike file-per-session providers (Codex, Pi), Zed uses a single SQLite database with one row per agent thread:

~/Library/Application Support/Zed/threads/threads.db

Schema (table threads):

CREATE TABLE threads (
    id TEXT PRIMARY KEY,
    summary TEXT NOT NULL,
    updated_at TEXT NOT NULL,      -- ISO 8601
    data_type TEXT NOT NULL,       -- e.g. "zstd"
    data BLOB NOT NULL,            -- zstd-compressed JSON thread
    parent_id TEXT,
    folder_paths TEXT,
    folder_paths_order TEXT,
    created_at TEXT
);

The data BLOB is zstd-compressed JSON (magic bytes 28 B5 2F FD). Decompressed, each thread JSON contains everything needed for pricing:

  • model: { "provider": "anthropic", "model": "claude-opus-4-8" }
  • request_token_usage: map of request_id -> { input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens }
  • cumulative_token_usage: same shape, thread total (can be empty on in-progress threads, so summing request_token_usage is the reliable path)
  • messages with tool calls, plus updated_at, title, profile, etc.

Token semantics match Anthropic's (separate cache-creation vs cache-read fields), so pricing maps cleanly onto the existing LiteLLM engine.

Proposed approach

  • New src/providers/zed.ts modeled on the SQLite-backed providers (Cursor / Forge / Warp) rather than the file-per-session shape.
  • Lazy-load better-sqlite3 (already an optional dep for Cursor/OpenCode) so non-Zed users aren't affected.
  • Decompress each data blob with zstd, sum request_token_usage per thread, resolve model.model, emit one call per request entry.
  • Map Zed's provider/model strings onto existing pricing; add a small display-name + tool-name map.
  • Ship a fixture-based test under tests/providers/ using a redacted real thread.

Questions before I start

  1. Is the Cursor/Forge SQLite provider the pattern you'd want me to follow for a single-DB, many-rows source?
  2. Preference for the zstd dependency — add a small zstd lib, or shell out / reuse anything already vendored?
  3. Anything specific you want in the fixture (redaction expectations for messages/prompts)?

Happy to implement once you confirm the approach. I can include terminal proof of npm run dev -- today --provider zed against my real Zed history in the PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions