Skip to content

[Bug]: Session import is unreachable after onboarding, so externally started sessions can never be imported #10961

Closed

Description

@danielquintas8

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/web

Steps to reproduce

  1. Complete onboarding in the desktop app, importing recent sessions for a project (onboardingCompletedAt is now set).
  2. In a terminal, run claude from that project's workspace root and hold a short conversation.
  3. Return to the desktop app and look for that session: sidebar, search, and the Settled shelf.
  4. Try to import it.

Expected behavior

A session that satisfies every documented eligibility rule should be importable after onboarding, through some reachable action. This is not a request for automatic discovery, which was declined in #7748.

Actual behavior

The session never appears, and there is no way to import it.

The eligibility rules are all satisfied. The transcript is minutes old, well inside the 30 day RECENT_THREAD_WINDOW_MS, and its recorded cwd is exactly the project's workspace root, so directoryIdentity matches. The importer would accept it.

The problem is reachability. agentSessions.import has one caller in the web app, WelcomeWizard.tsx. WelcomeWizard renders only on the /welcome route. The only navigation to /welcome is FirstRunGate.tsx:185, which fires only when the gate decides the user is on a first run, and that decision does not recur once onboardingCompletedAt is set. There is no sidebar entry, settings action, or command palette item for it, so on desktop, where there is no address bar, the import capability becomes unreachable the moment onboarding finishes.

Search does not help, because it only covers threads the app already holds, so an unimported session is absent rather than merely hard to find.

For contrast, /usage is reached from a SidebarChrome control. /welcome has no equivalent.

The effect is that every session started outside the app after onboarding is permanently invisible to it, even one started seconds ago in the right directory. PR #10631 adds an on demand import entry point on the new thread screen and its description notes that import "is currently part of onboarding", so the gap looks known.

Impact

Major degradation or frequent failure

Version or commit

0.0.40 (Homebrew cask), verified against main at 4664c57

Environment

macOS desktop app. The web client is not affected in the same way, since /welcome can be typed there directly.

Workaround

Start sessions inside the app, or continue outside ones with claude --resume in a terminal. On the web client, navigate to /welcome to re-run the wizard.

Activity

  1. Code-Tomato commented on Sep 24, 2026

    @Code-Tomato

    +1

  2. added a commit that references this issue on Sep 24, 2026
    1f83231
  3. Code-Tomato commented on Sep 24, 2026

    @Code-Tomato

    Opened #13510 with a small fix: an Import sessions row on the project's settings page that reruns the existing import. It's reachable on desktop, and there are no server changes. Tested on a dev build; the PR has a screenshot.

  4. added a commit that references this issue on Oct 1, 2026
    42a4175
  5. MarvinFS commented on Oct 10, 2026

    @MarvinFS

    Another way to hit this, and a good example of why the missing entry point hurts: deleting a project and then adding the same folder again.

    T3 Code (Alpha) 0.0.45 on Windows 11, Claude provider. I deleted a project with 98 imported Claude threads and added the same folder back. The new project is empty, and nothing offers to import the sessions that are still on disk. The only way back I found is the DevTools route from the comments on #13510, window.location.hash = "/welcome", which walks through the Connect and Agents steps again. The add-project flow would be a natural place for the offer, because the user is already choosing that folder.

    Two details from the code that may help whoever picks this up:

    • Deleting a project only stamps deleted_at on the thread rows, and requireThreadAbsent accepts the ids of deleted threads. So importRecentAgentThreads should be able to recreate the same import:<provider>:<session id> threads in the new project. Only the entry point is missing.
    • Import never refreshes a thread that already has imported history. In importRecentAgentThreads, such a thread only gets recordImportedTranscript, and thread.history.import runs only when importedHistoryPresent is false. A session imported while it was running therefore stays truncated, and importing again does not fix it. In my case the thread had 5 messages and the transcript had 39. The stored importedTranscripts entry has the file size and mtime, so the server could detect that the transcript grew.

    A refresh has to go through events. The client keeps a saved copy of each thread it has opened and subscribes with afterSequence. When no newer events exist, orchestration.subscribeThread sends no snapshot. I rebuilt the messages by editing projection_thread_messages directly, and the app kept showing the old ones until I cleared the client's saved copy in DevTools.

  6. ozyman42 commented on Oct 21, 2026

    @ozyman42

    In my case t3 by default imported from ~/.claude when all my sessions are actually in other claude directories (e.g. ~/.claude-account-1 and ~/.claude-account-2). Now post onboarding I don't see an option to import the sessions from these account folders even when adding these folders as individual claude providers

  7. juliusmarminge commented on Oct 22, 2026

    @juliusmarminge
    Member

    Checked current main at b5a226e49c using vp run dev in an isolated Linux worktree with copied development state. Opened the real web client, then General Settings and searched Settings for import: there is no session-import action. This checks the missing entry point only; I did not run the macOS desktop reproduction or create a new external Claude session.

    Two open PRs already explicitly address this issue: #22411 adds the shared import dialog under General Settings, and #23122 adds import in Project Settings. The earlier #10631 was closed without merging. Leaving this issue open for the existing work; no additional PR created.

  8. evilive3000 commented on Oct 22, 2026

    @evilive3000

    Also observed incomplete recent history in imported Codex chats on T3 Code Desktop 0.1.1, Linux: T3 contained 82 of 88 messages in one session and 42 of 43 in another. The missing messages were at the end and present in the original Codex transcripts. Would you prefer a separate issue for refreshing already-imported history?

  9. mthsmb commented on Oct 29, 2026

    @mthsmb

    Another data point on 0.1.5: Windows 11 desktop app with a local Windows backend and a WSL2 (Ubuntu) backend. Both have Claude Code history, and the WSL backend also has Codex history.

    Hoping #22411 or #23122 lands. Either would have avoided the DevTools detour.

  10. cachanova commented on Oct 30, 2026

    @cachanova

    Some more data from an existing install (desktop, t3 v0.1.0, Linux), in case it helps whichever fix lands.

    Resetting onboardingCompletedAt doesn't bring the wizard back. I tried setting it to null in client-settings.json with the app closed. On the next launch the client decides app and saves completion again within a few seconds, because the onboarding gate goes straight to the app whenever projectCount > 1 || threadCount > 1. So for anyone with more than one project or thread, there is currently no way back to the import step.

    The server side works fine for existing projects. Calling the RPC directly imported the missing sessions:

    1. t3 auth session issue --scope orchestration:read --scope orchestration:operate --ttl 10m --token-only
    2. POST /api/auth/websocket-ticket with Authorization: Bearer <token>
    3. Connect to /ws?orchestrationProtocol=2&wsTicket=<ticket> and send agentSessions.import with { projectId, expectedWorkspaceRoot }

    That brought in 15 new threads for my existing project. (As noted in the PRs, importedCount includes sessions imported on earlier runs.) Re-running is safe, so either #22411 or #23122 would cover this.

    Separate problem the PRs don't fix: long sessions are rejected outright. Three of my Claude Code sessions (57 MB, 76 MB and 107 MB .jsonl) are skipped on every run. They count toward skippedCount, and the server trace logs:

    Could not read imported transcript … Transcript selected history exceeds the 32 MiB memory budget
    

    The parser only keeps the first user message plus the last 199 messages anyway, so the stored thread would be small. But the 32 MiB budget applies to everything selected while reading, so the whole transcript fails. These long-running sessions are the ones people most want to move over. Keeping only a rolling window of recent records while reading, instead of everything up to 32 MiB, would let them import. Separately, it would help if the UI said why a session was skipped: too large, changed during the read (still open in Claude Code), older than 30 days, and so on.

  11. Alex-DashNC commented on Oct 31, 2026

    @Alex-DashNC

    Another case on 0.1.6 (macOS desktop): a second Claude account added after onboarding.

    1. I finished onboarding with the default Claude instance, which imported from ~/.claude.
    2. Later I added a second Claude instance with CLAUDE_CONFIG_DIR path set to ~/.claude2, the folder my second account's CLI sessions live in (alias claude2='CLAUDE_CONFIG_DIR=~/.claude2 claude').
    3. Restarting the app imports nothing from ~/.claude2, and there's no action to start an import. As others found, clearing onboardingCompletedAt just gets set again on launch.

    The scanner already reads each Claude instance's homePath, so an entry point from #22411 or #23122 would cover this. Two requests for whichever lands:

  12. thomasyuxizeng commented on Nov 3, 2026

    @thomasyuxizeng

    Another data point on 0.1.6 (Windows 11 desktop, local backend), plus two things I'd like whichever fix lands (#22411 / #23122) to cover.

    Confirmed again: after onboarding there is no way back to the import step. The wizard only appears when the workspace is nearly empty, so resetting onboardingCompletedAt doesn't help once there is more than one project or thread. I worked around it by calling agentSessions.scan and agentSessions.import directly over the local RPC socket, which works fine.

    1. Import needs a way to pick sessions, not just folders.
    agentSessions.import takes { projectId, expectedWorkspaceRoot }, so it imports every session in a folder. In my case one project held ~175 sessions, and ~145 of them were runs of two scheduled tasks (one task's runs had near-identical titles). They buried the ~25 sessions I actually work in. The only fix was to import everything and then delete the extras.

    It would help to have:

    • a recent-N option, or a "since" date, in the import UI;
    • a size or message-count floor ("only sessions with real context");
    • a way to leave out automated or scheduled runs.

    The scan could also report per-session size and last-active time, so the UI can show a preview list with checkboxes. Today a candidate only has a threadCount per folder.

    2. Sessions still being written are skipped, and there is no hint to retry.
    The first import of that project returned importedCount: 95, skippedCount: 80. Re-running it gave 164/11, then 170/5, then 173/2. So a few passes converge, but a user who sees "80 skipped" has no idea that running it again helps. Looping until skippedCount stops dropping, or retrying automatically, would avoid that. This looks related to #17484.

    Happy to share the small script I used (rank sessions by size, skip scheduled runs, import, then prune) if it's useful as a reference.

  13. Marrocco-Simone commented on Nov 3, 2026

    @Marrocco-Simone

    confirmed on macos too, i had to connect the app to the web browser view and manually go to /welcome to import a new project with the old sessions

  14. haroune-mohammedi commented on Nov 3, 2026

    @haroune-mohammedi

    Same here, Claude made a script for me as a workaround

  15. kennethlee99 commented on Nov 5, 2026

    @kennethlee99

    Another case for the missing import entry point, and a detail about which of the open fixes covers it: a project that is a linked git worktree.

    Checked against main at 67eebac (2026-11-05), Windows 11 desktop 0.1.7, Claude provider.

    Steps to reproduce:

    1. Have a repository with a linked worktree, for example git worktree add .claude/worktrees/feature-x.
    2. Run claude inside the worktree folder and hold a short conversation. The transcript in ~/.claude/projects records the worktree folder as its cwd.
    3. Add the worktree folder as a project, either with t3 project add or the Add project dialog.

    Expected: the past Claude threads for that folder show up, or there is a way to import them.

    Actual: the project has zero threads. In my setup five worktree projects show nothing, while the four main checkouts that went through the welcome wizard imported 56 threads.

    What the source shows:

    • AgentSessionScanner.readGitIdentities classifies a .git pointer file under worktrees/ as a linked worktree (apps/server/src/project/AgentSessionScanner.ts lines 873-897). Since fix(server): onboarding offers worktrees of a bare repository #16688, linked worktrees of a bare repository are offered again (lines 904-908). Every other linked worktree gets { _tag: "Worktree" }.
    • In scan, a Worktree identity sets key = "" and the candidate is skipped (lines 1553-1555, with if (key === "") continue on line 1562). So a worktree folder never appears in the import list. The unit test "skips linked git worktrees and reports the origin of real checkouts" locks this in.
    • The import itself does not have that restriction. prepareRecentThreads matches transcripts by the directory identity of the project root (line 1657) and has no worktree check, and importRecentAgentThreads takes any { projectId, expectedWorkspaceRoot } (apps/server/src/project/AgentSessionImporter.ts lines 180-234). So the server would import a worktree project's sessions if something called it.
    • Nothing does. The only web caller of agentSessionImport is WelcomeWizard.tsx (line 1224), and the only server entry is the agentSessions.import handler in ws.ts (line 2990). Adding a project, from the CLI or the dialog, never triggers it.

    How this relates to the open work:

    Suggestion: land #23122 (or an equivalent per-project import action), and consider offering the same import when a project is created, as MarvinFS suggested above. Either way, the scanner can keep skipping worktrees as onboarding candidates.

  16. Abirouk commented on Nov 6, 2026

    @Abirouk

    Same on macOS, desktop 0.1.6: sessions started in the Claude desktop app after onboarding never appear.

    A route that needs neither DevTools nor direct RPC calls: the desktop app's local server also serves the web client, so the wizard can be reached from a browser.

    1. Read the port from ~/.t3/userdata/server-runtime.json.

    2. Create a one-time pairing token with the t3 CLI (~/.t3/bin/t3, or Settings → About → Install). These scopes were enough for my run: t3 auth pairing create --ttl 10m --label import-welcome --scope orchestration:read --scope orchestration:operate --scope settings:write --scope providers:manage --scope filesystem:read

    3. Open http://127.0.0.1:/welcome in a browser. It redirects to the pairing page, which says the environment expects a trusted credential; a pasted one-time token is accepted anyway. You land on the app afterwards, so open /welcome again, then step through Connect and Agents, tick the projects, Import.

    The missing sessions came into the existing projects. Pairing leaves a 30-day browser session with those scopes behind; t3 auth session list shows it under the label and t3 auth session revoke removes it.

  17. guessthepw commented on Nov 6, 2026

    @guessthepw

    So what exactly is holding this back?

  18. vibhu1508 commented on Nov 8, 2026

    @vibhu1508
    resync-sessions-demo.mp4

    @t3dotgg @juliusmarminge I took a shot at this and wanted to check whether you’d take it as a PR before I open one.

    What it does: a Resync sessions button in the sidebar footer, next to Usage, plus a matching ⌘K command palette entry. One click rescans every connected environment and imports new Claude Code, Codex and Pi sessions into the projects you already have.

    Only new sessions are counted, so a second click reports nothing new instead of re-counting. The importer gains an optional newCount, and older servers still work.
    Folders that aren’t projects yet aren’t created automatically. The result toast counts them and offers Open setup, which also makes the import wizard reachable on desktop after onboarding.
    Offline environments are skipped, so a resync never hangs.
    The button is hidden when the connection doesn’t have permission to import.

    It’s one commit on current main (+306 / −11, about a third of that tests), and it leaves the setup wizard untouched. vp run check:changed passes, and I tested it end to end in an isolated dev build. Branch: https://github.com/vibhu1508/t3code/tree/feat/resync-agent-sessions

    #22411 and #23122 also target this issue; this one is a single action from the sidebar rather than a settings entry. I’m happy to fold it into either of those instead, or to keep only the command palette entry if you’d prefer less UI.

    Would you take this as a PR?

  19. wsszh commented on Nov 9, 2026

    @wsszh

    Reproducing on the macOS desktop app 0.1.7 with the Pi provider. Two additions to the reachability gap.

    Pi is affected in the same way. AgentSessionSource in packages/contracts/src/agentSessions.ts is ["claudeAgent", "codex", "pi"], so Pi is a supported import source. A Pi provider instance that the user enables after onboarding is never scanned again, because the only scan runs on /welcome. When I call agentSessions.scan over the local RPC, the Pi candidates come back with the correct threadCount, cwd, and alreadyImported values. Calling agentSessions.import the same way imports the sessions. The scanner and the importer both work. Only the entry point is missing. This matches the reports above for Claude and Codex.

    The t3code://app/welcome deep link is also rejected. On 0.1.7 this link does nothing:

    • apps/desktop/src/app/DesktopClerk.ts sends open-url events through openWebLink() and openAppLink().
    • openAppLink() accepts a value only when promptLinkAppPath() or readPairingAppLink() returns a non-null path.
    • packages/shared/src/promptLinks.ts maps t3code://new and t3code://threads/<env>/<thread>. It has no /welcome case.

    docs/user/welcome-wizard.md tells the reader to open /welcome to run setup again. That works in the web client. On desktop it cannot work while the URL scheme has no /welcome mapping, and the desktop window has no address bar.

    A /welcome case in promptLinkAppPath() would make the documented remedy work on desktop without a new UI surface. It does not replace #22411 or #23122, which fix the normal path.

    Environment: macOS desktop app 0.1.7, local backend.

  20. t3dotgg commented on Nov 9, 2026

    @t3dotgg
    Member

    Note

    🤖 Claude Opus 5.5 responding on behalf of Theo

    Fixed by #33209, merged as 4f0b74e. After onboarding, Settings → About → Welcome page → Open reopens the page. Under Projects, Review all also lists projects already in T3 Code, and picking one imports its conversations that are not imported yet, including sessions started outside T3 Code.

    Verified: CI passed on the merged head. The Welcome page browser tests include importing a project that is already in T3 Code.

  21. juliusmarminge commented on Nov 9, 2026

    @juliusmarminge
    Member

    Thanks for the report! #33209, merged as 4f0b74e190, fixes this in the Welcome page.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions