Skip to content

[Feature]: First-class interop/sync between T3 threads and local Claude Code CLI sessions #6590

Description

@boonguan

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I am describing a concrete problem or use case, not just a vague idea.

Area

apps/server

Problem or use case

T3 Code and the Claude Code CLI already share the same on-disk session storage (~/.claude/projects/<project>/*.jsonl), and T3 already scans those transcripts for the usage page. But the sessions themselves are invisible to each other:

I verified the mechanics by inspecting the server bundle: the Claude adapter resumes via the Agent SDK resume: <sessionId> option, and readClaudeResumeState accepts any UUID — so hand-editing resume_cursor_json in state.sqlite to point at an external CLI session actually works today. The model context comes back fully, but the thread renders empty because no projections exist for the imported turns. That gap is the real work, not the resume plumbing.

Proposed solution

First-class interop/sync with local Claude Code sessions:

  1. Discovery: list transcripts from ~/.claude/projects/<cwd-slug>/ in the resume picker for the current workspace (session id, first user prompt, last activity, turn count — all parseable from the JSONL).
  2. Import: selecting one creates a T3 thread whose resume cursor points at that session id (the adapter already supports this), and backfills projection_thread_messages from the transcript so the prior conversation is visible in the UI.
  3. Live sync (stretch): watch the project's transcript directory; when a session bound to a T3 thread grows from outside (CLI turn), append those turns to the projections so the thread stays truthful.

Why this matters

People move between terminal and editor constantly. Today the two front-ends silently share provider state but not user-visible state, which is worse than either full sharing or full isolation: you can end up with a thread whose model context and visible history disagree. Import + backfill makes the shared-storage design an actual feature.

Smallest useful scope

Discovery + import with projection backfill for Claude sessions in the current workspace only. No live sync, no Codex, no cross-machine anything. Even import without backfill (model context only, with a visible "resumed from CLI session, prior history not shown" marker) would beat the status quo of hand-editing sqlite.

Alternatives considered

  • Running claude --resume <id> in a terminal inside T3 — works, but it's a CLI session, not a T3 thread (no checkpoints, no approvals UI, no mobile handoff).
  • Hand-editing resume_cursor_json in ~/.t3/userdata/state.sqlite to point an existing thread at an external session UUID — works for model context, but the UI shows none of the imported history, and it requires closing the app and touching a WAL-backed sqlite file.

Risks or tradeoffs

  • Transcript JSONL is an internal Claude Code format and changes without notice; the projection backfill needs to be tolerant of unknown record types (the usage scanner already takes this stance).
  • Imported sessions may reference tool calls/approvals T3 never mediated; those should render read-only rather than replaying through the approval pipeline.
  • Session files can be large; backfill should stream and cap like the existing usage scan does.

Examples or references

Contribution

  • I would be open to helping implement this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions