+1
[Bug]: Session import is unreachable after onboarding, so externally started sessions can never be imported#10961
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
- Complete onboarding in the desktop app, importing recent sessions for a project (
onboardingCompletedAtis now set). - In a terminal, run
claudefrom that project's workspace root and hold a short conversation. - Return to the desktop app and look for that session: sidebar, search, and the Settled shelf.
- 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 4664c572a
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.
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.
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_aton the thread rows, andrequireThreadAbsentaccepts the ids of deleted threads. SoimportRecentAgentThreadsshould be able to recreate the sameimport:<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 getsrecordImportedTranscript, andthread.history.importruns only whenimportedHistoryPresentis 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 storedimportedTranscriptsentry 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.
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
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.
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?
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.
- After onboarding there is no import entry point on either backend.
docs/user/welcome-wizard.mdsays to "open/welcometo run setup again", but the desktop app has no address bar. The only route that worked: DevTools (Ctrl+Shift+I) → Console →window.location.hash = "/welcome", then select both computers and import.- One large project needed several manual re-runs (see #17484). One limit could not be passed by re-running at all: #27163.
Hoping #22411 or #23122 lands. Either would have avoided the DevTools detour.
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:
t3 auth session issue --scope orchestration:read --scope orchestration:operate --ttl 10m --token-onlyPOST /api/auth/websocket-ticketwithAuthorization: Bearer <token>- Connect to
/ws?orchestrationProtocol=2&wsTicket=<ticket>and sendagentSessions.importwith{ 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:
| 1 | 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.
Another case on 0.1.6 (macOS desktop): a second Claude account added after onboarding.
- I finished onboarding with the default Claude instance, which imported from
~/.claude. - 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'). - Restarting the app imports nothing from
~/.claude2, and there's no action to start an import. As others found, clearingonboardingCompletedAtjust 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:
- Offer an import when a provider instance is added (or when its config folder changes), since that's when a pile of existing sessions becomes visible. Same as @ozyman42's
~/.claude-account-1/-2case above. - Import one session by id, as in #18614. I usually want a handful of specific sessions, not everything from the last 30 days. That's also the only way to reach older sessions, since a re-run never goes past the 30-day window.
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.
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
Same here, Claude made a script for me as a workaround
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 67eebaca2 (2026-11-05), Windows 11 desktop 0.1.7, Claude provider.
Steps to reproduce:
- Have a repository with a linked worktree, for example
git worktree add .claude/worktrees/feature-x. - Run
claudeinside the worktree folder and hold a short conversation. The transcript in~/.claude/projectsrecords the worktree folder as itscwd. - Add the worktree folder as a project, either with
t3 project addor 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.readGitIdentitiesclassifies a.gitpointer file underworktrees/as a linked worktree (apps/server/src/project/AgentSessionScanner.tslines 873-897). Since #16688, linked worktrees of a bare repository are offered again (lines 904-908). Every other linked worktree gets{ _tag: "Worktree" }.- In
scan, aWorktreeidentity setskey = ""and the candidate is skipped (lines 1553-1555, withif (key === "") continueon 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.
prepareRecentThreadsmatches transcripts by the directory identity of the project root (line 1657) and has no worktree check, andimportRecentAgentThreadstakes any{ projectId, expectedWorkspaceRoot }(apps/server/src/project/AgentSessionImporter.tslines 180-234). So the server would import a worktree project's sessions if something called it. - Nothing does. The only web caller of
agentSessionImportisWelcomeWizard.tsx(line 1224), and the only server entry is theagentSessions.importhandler inws.ts(line 2990). Adding a project, from the CLI or the dialog, never triggers it.
How this relates to the open work:
- #23122 (Import sessions row in Project Settings) calls
agentSessions.importper project with the project's own id and root, so it would also cover worktree projects. That looks like the smallest fix for this case. - #22411 (dialog under General Settings) lists the candidates that
agentSessions.scanreturns. Because the scan drops worktree folders, a worktree project would not be listed there. - #18198 imports sessions from a project's linked worktrees into the main checkout's project. That is a different model: it helps when the worktree is not its own project, and does nothing when the worktree itself is the project.
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.
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.
Read the port from ~/.t3/userdata/server-runtime.json.
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
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.
So what exactly is holding this back?
https://github.com/user-attachments/assets/dd3152ac-c1a1-4923-93b1-5d9300b290a6
@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?
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.tssendsopen-urlevents throughopenWebLink()andopenAppLink().openAppLink()accepts a value only whenpromptLinkAppPath()orreadPairingAppLink()returns a non-null path.packages/shared/src/promptLinks.tsmapst3code://newandt3code://threads/<env>/<thread>. It has no/welcomecase.
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.
Note
🤖 Claude Opus 5.5 responding on behalf of Theo
Fixed by #33209, merged as 4f0b74e1902. 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.
Thanks for the report! #33209, merged as 4f0b74e190, fixes this in the Welcome page.