Draft: two-way teleport with native CLI sessions - #7136

Closed
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23
Closed

Draft: two-way teleport with native CLI sessions#7136
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23

Conversation

@baanish

@baanishbaanish commented Aug 15, 2026

Copy link
Copy Markdown

Draft. Do not merge. Exploration of two-way teleport. Opened as one PR because GitHub cannot stack cross-fork bases on this repo.

What Changed

T3 Code can list, import, and export native CLI sessions for Codex, and Claude.
Native files stay native. Import copies a CLI session onto a T3 thread. Export writes the thread back. Presence (t3 vs native) swaps Import/Export so both sides are not writers at once.
Codex export writes session_meta the CLI can resume. OpenCode imports text turns only, does not treat live opencode.db as a foreign lock, and does not match parent cwds into sibling codex / claude / grok folders. Stop settles Working when the turn is aborted, when there is no live session, or when interrupt fails.

UI

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

New UI

Draft hero Import a native CLI session link

Command palette Import sessions action

Native Claude and Codex sessions in the import picker

Hover

Teleport Out tooltip

Teleport In tooltip

Composer disabled after Teleport Out

Composer disabled when the thread is in the native CLI

Recordings

Codex
codex_teleport_roundtrip_nologo.mp4

Claude
claude_teleport_roundtrip_nologo.mp4

Why

Two-way teleport needs a shared engine, UI, and one adapter per CLI. This PR is that whole stack in one diff because stacked bases have to exist on pingdotgg/t3code.

UI Changes

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Relates to #207, #5146, #5741, and #6590.

Note

Add two-way teleport between app threads and native CLI sessions

  • Introduces a full teleport system allowing threads to be exported to native CLI sessions (Claude, Codex, Grok, OpenCode) and imported back, with message history synchronization via new thread.history.replace and thread.teleport.set orchestration commands.
  • Adds TeleportService with list/import/export session RPCs (teleport.listSessions, teleport.importSessions, teleport.exportSession) wired into the WS layer with scope-based authorization.
  • Adds per-provider JSONL/directory format adapters with schema-version gating, file-lock detection, and atomic writes; a registry pattern enables runtime format registration.
  • Extends the command palette and chat UI with session browsing, import flows, a TeleportOutButton in the chat header, and composer/send disabling when a thread is teleported-out.
  • Adds DB migration 041 adding teleport_json to projection_threads with backfill from existing runtime telemetry.
  • Risk: thread.turn.start now fails with OrchestrationCommandInvariantError if the thread's teleport presence is native, blocking turn creation on teleported-out threads.
📊 Macroscope summarized 18ed3c0. 52 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

cursoragentand others added 20 commits August 15, 2026 08:54
Contracts, orchestration, and the teleport service land first. Native CLI
formats register later, so list/import/export stay empty until a provider
adapter is added.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
The UI can list, import, and export native sessions. Until a format
adapter is registered, the picker stays empty and export fails closed.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Codex jsonl adapter so T3 can list, import, and export
rollouts the CLI can resume.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the OpenCode adapter so T3 can list, import, and export text
turns from opencode.db or JSON storage without treating the live db as a
foreign lock.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Claude jsonl adapter so T3 can list, import, and export
sessions from the Claude projects folder.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Grok session-directory adapter so T3 can list, import, and
export native Grok Build chats.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Stop marked the turn interrupted but left the session running, so the thread stayed Working after abort hung or only emitted turn.aborted.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
A projected running OpenCode thread stayed Working after Stop if the
in-memory provider session was already gone. Interrupt no longer
recovers a session just to abort it, and Stop settles the projection
when there is nothing live to interrupt.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep live-session titles and personal directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@coderabbitai

coderabbitaiBot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a86460d-dc34-4a24-9c87-02e715f5dd10

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 15, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small consistency findings in the new teleport UI. Everything else in the changed web files (command palette views, composer disabled/placeholder handling, ChatView toast) follows the existing primitives and layout conventions.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/DraftHeroHeadline.tsx Outdated
Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the new TeleportService (plus its contract errors). Four convention violations found; details inline.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/Services/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/orchestration/Layers/ProjectionPipeline.ts
Comment threadapps/server/src/teleport/formats/codex.ts
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/cwd.ts Outdated
Comment threadapps/server/src/teleport/formats/grok.ts Outdated
Comment threadapps/server/src/teleport/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadapps/server/src/orchestration/decider.ts Outdated
baanishand others added 3 commits August 15, 2026 15:30
The import CTA lacked cursor-pointer, and the header export control used
the text xs size instead of the square icon-xs used by neighboring actions.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Reject unsafe session ids on native reads/writes, fail closed when lock
checks cannot run, keep Codex whitespace, preserve in-place provider
instances, and clear stale history/approvals when replacing a thread.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new header control's disabled state suppresses the tooltip that explains why it is unavailable.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated
Effect 4 does not provide zipRight on Effect. Complete the sendTurn abort latch from a generator finalizer instead.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts Outdated
cursoragentand others added 4 commits August 17, 2026 20:35
Claim the in-flight abort through an atomic gate so a second interrupt waits instead of emitting another turn.aborted or calling session.abort again.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export writes the native session cwd from the thread worktree, which lives
outside the project root. Listing and import treated only the workspace root
as in-project, so Teleport Out was a one-way door.
Discover extra cwds from the project's thread worktrees, match subdirectory
sessions, and stop accepting ancestor cwds such as / or $HOME.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export set presence to native with a teleport-pending path before writing
the CLI file, then only reverted on write tapError. Interruptions, defects,
and later directory or teleport.set failures left the thread stuck: the UI
only offered Import, which rejected the fake path.
Wrap the pending presence in acquireUseRelease so any unsuccessful exit
reverts to T3, or persists the real native path if the file was written.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Release-path persist of a written native session can still raise a
filesystem error. Catch that so a failed bind cannot mask the export
failure or skip reverting pending presence.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two error-modeling convention issues in the new teleport code: message stored as data when it is a fixed template over existing attributes, and a helper whose only behavior is constructing that error.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Lock, schema, identity, and file-locked errors now derive `message` from
their fields, so the lockProbeError helper can go. A failed new-thread
import deletes the orphan thread instead of leaving it unbound.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/nativeWrite.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new teleport service against the Effect service conventions. Service shape (Context.Service with inline interface, exported make/layer), dependency acquisition via yield*, and Effect.catchTags usage all look right now. Three remaining error-modelling issues below.

Posted via Macroscope — Effect Service Conventions

Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/formats/codex.ts Outdated
cursoragentand others added 3 commits August 17, 2026 22:33
Store a write stage instead of a free-form message on TeleportNativeWriteError,
derive TeleportUnsupportedProviderError from the provider, and remap schema
verification with catchTags. On Windows, replace native files by moving the
destination aside so a failed rename can restore the previous session.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Persist teleport ownership first so a failed history replace cannot leave an
unbound thread with overwritten messages.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep the teleported-out composer disable path and use main's
disconnected placeholder constant.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/ChatView.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new chat-header teleport button loses the themed toolbar control styling because the tooltip wrapper overwrites data-slot="button". See the inline comment for the one-attribute fix.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx
cursoragentand others added 5 commits August 19, 2026 03:27
TooltipTrigger replaces data-slot=button, so custom themes skipped this
icon. Opt in with data-toolbar-control the same way ProjectScriptsControl does.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Send-disabled only grayed the editor. Type-to-focus, mention drops, and
file drops could still queue hidden draft content. Reject those paths too.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
In-place native session import persisted directory binding, teleport
presence, unarchive, history, and title as separate durable mutations.
A later failure left T3 ownership and history out of sync, and a
concurrent turn could run against that intermediate state.
Commit ownership, history, and unarchive in one orchestration command.
Fence thread.turn.start with importing presence, recover leftover
importing state on startup, and keep title plus directory finalize
best-effort. Import stays atomic per session, not all-or-nothing for
the batch.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/importTransaction.ts Outdated
cursoragentand others added 3 commits August 19, 2026 05:55
tapError only saw typed failures, so a cancelled or defective pre-commit
import step could leave presence "importing" until process restart.
onError reverts for fail, die, and interrupt, and keeps revert running.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatView's teleport send-disabled import. Main moved the collapsed
sidebar titlebar inset into WorkspacePageHeader, so that import is gone.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatComposer's teleport lock on the prompt editor after main
moved send/stop into the footer. Native and importing presence still
disable the editor and show the send-disabled reason.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/chat/ChatComposer.tsx
Paste/drop could start before teleport lock, then attach compressed
images after compression finished. Stash restore and stash-current
could also write into a native/importing draft. Recheck send-disabled
after awaits and reject those stash mutations while teleport-locked.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@t3-code

t3-codeBot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

closing because this is explicitly marked Draft. Do not merge. and documents cross-fork teleport exploration rather than merge-ready work.

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

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@baanish@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Draft: two-way teleport with native CLI sessions - #7136

Closed
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23
Closed

Draft: two-way teleport with native CLI sessions#7136
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23

Conversation

@baanish

@baanishbaanish commented Aug 15, 2026

Copy link
Copy Markdown

Draft. Do not merge. Exploration of two-way teleport. Opened as one PR because GitHub cannot stack cross-fork bases on this repo.

What Changed

T3 Code can list, import, and export native CLI sessions for Codex, and Claude.
Native files stay native. Import copies a CLI session onto a T3 thread. Export writes the thread back. Presence (t3 vs native) swaps Import/Export so both sides are not writers at once.
Codex export writes session_meta the CLI can resume. OpenCode imports text turns only, does not treat live opencode.db as a foreign lock, and does not match parent cwds into sibling codex / claude / grok folders. Stop settles Working when the turn is aborted, when there is no live session, or when interrupt fails.

UI

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

New UI

Draft hero Import a native CLI session link

Command palette Import sessions action

Native Claude and Codex sessions in the import picker

Hover

Teleport Out tooltip

Teleport In tooltip

Composer disabled after Teleport Out

Composer disabled when the thread is in the native CLI

Recordings

Codex
codex_teleport_roundtrip_nologo.mp4

Claude
claude_teleport_roundtrip_nologo.mp4

Why

Two-way teleport needs a shared engine, UI, and one adapter per CLI. This PR is that whole stack in one diff because stacked bases have to exist on pingdotgg/t3code.

UI Changes

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Relates to #207, #5146, #5741, and #6590.

Note

Add two-way teleport between app threads and native CLI sessions

  • Introduces a full teleport system allowing threads to be exported to native CLI sessions (Claude, Codex, Grok, OpenCode) and imported back, with message history synchronization via new thread.history.replace and thread.teleport.set orchestration commands.
  • Adds TeleportService with list/import/export session RPCs (teleport.listSessions, teleport.importSessions, teleport.exportSession) wired into the WS layer with scope-based authorization.
  • Adds per-provider JSONL/directory format adapters with schema-version gating, file-lock detection, and atomic writes; a registry pattern enables runtime format registration.
  • Extends the command palette and chat UI with session browsing, import flows, a TeleportOutButton in the chat header, and composer/send disabling when a thread is teleported-out.
  • Adds DB migration 041 adding teleport_json to projection_threads with backfill from existing runtime telemetry.
  • Risk: thread.turn.start now fails with OrchestrationCommandInvariantError if the thread's teleport presence is native, blocking turn creation on teleported-out threads.
📊 Macroscope summarized 18ed3c0. 52 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

cursoragentand others added 20 commits August 15, 2026 08:54
Contracts, orchestration, and the teleport service land first. Native CLI
formats register later, so list/import/export stay empty until a provider
adapter is added.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
The UI can list, import, and export native sessions. Until a format
adapter is registered, the picker stays empty and export fails closed.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Codex jsonl adapter so T3 can list, import, and export
rollouts the CLI can resume.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the OpenCode adapter so T3 can list, import, and export text
turns from opencode.db or JSON storage without treating the live db as a
foreign lock.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Claude jsonl adapter so T3 can list, import, and export
sessions from the Claude projects folder.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Grok session-directory adapter so T3 can list, import, and
export native Grok Build chats.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Stop marked the turn interrupted but left the session running, so the thread stayed Working after abort hung or only emitted turn.aborted.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
A projected running OpenCode thread stayed Working after Stop if the
in-memory provider session was already gone. Interrupt no longer
recovers a session just to abort it, and Stop settles the projection
when there is nothing live to interrupt.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep live-session titles and personal directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@coderabbitai

coderabbitaiBot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a86460d-dc34-4a24-9c87-02e715f5dd10

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 15, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small consistency findings in the new teleport UI. Everything else in the changed web files (command palette views, composer disabled/placeholder handling, ChatView toast) follows the existing primitives and layout conventions.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/DraftHeroHeadline.tsx Outdated
Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the new TeleportService (plus its contract errors). Four convention violations found; details inline.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/Services/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/orchestration/Layers/ProjectionPipeline.ts
Comment threadapps/server/src/teleport/formats/codex.ts
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/cwd.ts Outdated
Comment threadapps/server/src/teleport/formats/grok.ts Outdated
Comment threadapps/server/src/teleport/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadapps/server/src/orchestration/decider.ts Outdated
baanishand others added 3 commits August 15, 2026 15:30
The import CTA lacked cursor-pointer, and the header export control used
the text xs size instead of the square icon-xs used by neighboring actions.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Reject unsafe session ids on native reads/writes, fail closed when lock
checks cannot run, keep Codex whitespace, preserve in-place provider
instances, and clear stale history/approvals when replacing a thread.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new header control's disabled state suppresses the tooltip that explains why it is unavailable.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated
Effect 4 does not provide zipRight on Effect. Complete the sendTurn abort latch from a generator finalizer instead.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts Outdated
cursoragentand others added 4 commits August 17, 2026 20:35
Claim the in-flight abort through an atomic gate so a second interrupt waits instead of emitting another turn.aborted or calling session.abort again.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export writes the native session cwd from the thread worktree, which lives
outside the project root. Listing and import treated only the workspace root
as in-project, so Teleport Out was a one-way door.
Discover extra cwds from the project's thread worktrees, match subdirectory
sessions, and stop accepting ancestor cwds such as / or $HOME.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export set presence to native with a teleport-pending path before writing
the CLI file, then only reverted on write tapError. Interruptions, defects,
and later directory or teleport.set failures left the thread stuck: the UI
only offered Import, which rejected the fake path.
Wrap the pending presence in acquireUseRelease so any unsuccessful exit
reverts to T3, or persists the real native path if the file was written.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Release-path persist of a written native session can still raise a
filesystem error. Catch that so a failed bind cannot mask the export
failure or skip reverting pending presence.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two error-modeling convention issues in the new teleport code: message stored as data when it is a fixed template over existing attributes, and a helper whose only behavior is constructing that error.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Lock, schema, identity, and file-locked errors now derive `message` from
their fields, so the lockProbeError helper can go. A failed new-thread
import deletes the orphan thread instead of leaving it unbound.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/nativeWrite.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new teleport service against the Effect service conventions. Service shape (Context.Service with inline interface, exported make/layer), dependency acquisition via yield*, and Effect.catchTags usage all look right now. Three remaining error-modelling issues below.

Posted via Macroscope — Effect Service Conventions

Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/formats/codex.ts Outdated
cursoragentand others added 3 commits August 17, 2026 22:33
Store a write stage instead of a free-form message on TeleportNativeWriteError,
derive TeleportUnsupportedProviderError from the provider, and remap schema
verification with catchTags. On Windows, replace native files by moving the
destination aside so a failed rename can restore the previous session.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Persist teleport ownership first so a failed history replace cannot leave an
unbound thread with overwritten messages.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep the teleported-out composer disable path and use main's
disconnected placeholder constant.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/ChatView.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new chat-header teleport button loses the themed toolbar control styling because the tooltip wrapper overwrites data-slot="button". See the inline comment for the one-attribute fix.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx
cursoragentand others added 5 commits August 19, 2026 03:27
TooltipTrigger replaces data-slot=button, so custom themes skipped this
icon. Opt in with data-toolbar-control the same way ProjectScriptsControl does.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Send-disabled only grayed the editor. Type-to-focus, mention drops, and
file drops could still queue hidden draft content. Reject those paths too.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
In-place native session import persisted directory binding, teleport
presence, unarchive, history, and title as separate durable mutations.
A later failure left T3 ownership and history out of sync, and a
concurrent turn could run against that intermediate state.
Commit ownership, history, and unarchive in one orchestration command.
Fence thread.turn.start with importing presence, recover leftover
importing state on startup, and keep title plus directory finalize
best-effort. Import stays atomic per session, not all-or-nothing for
the batch.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/importTransaction.ts Outdated
cursoragentand others added 3 commits August 19, 2026 05:55
tapError only saw typed failures, so a cancelled or defective pre-commit
import step could leave presence "importing" until process restart.
onError reverts for fail, die, and interrupt, and keeps revert running.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatView's teleport send-disabled import. Main moved the collapsed
sidebar titlebar inset into WorkspacePageHeader, so that import is gone.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatComposer's teleport lock on the prompt editor after main
moved send/stop into the footer. Native and importing presence still
disable the editor and show the send-disabled reason.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/chat/ChatComposer.tsx
Paste/drop could start before teleport lock, then attach compressed
images after compression finished. Stash restore and stash-current
could also write into a native/importing draft. Recheck send-disabled
after awaits and reject those stash mutations while teleport-locked.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@t3-code

t3-codeBot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

closing because this is explicitly marked Draft. Do not merge. and documents cross-fork teleport exploration rather than merge-ready work.

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

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@baanish@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Draft: two-way teleport with native CLI sessions - #7136

Closed
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23
Closed

Draft: two-way teleport with native CLI sessions#7136
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23

Conversation

@baanish

@baanishbaanish commented Aug 15, 2026

Copy link
Copy Markdown

Draft. Do not merge. Exploration of two-way teleport. Opened as one PR because GitHub cannot stack cross-fork bases on this repo.

What Changed

T3 Code can list, import, and export native CLI sessions for Codex, and Claude.
Native files stay native. Import copies a CLI session onto a T3 thread. Export writes the thread back. Presence (t3 vs native) swaps Import/Export so both sides are not writers at once.
Codex export writes session_meta the CLI can resume. OpenCode imports text turns only, does not treat live opencode.db as a foreign lock, and does not match parent cwds into sibling codex / claude / grok folders. Stop settles Working when the turn is aborted, when there is no live session, or when interrupt fails.

UI

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

New UI

Draft hero Import a native CLI session link

Command palette Import sessions action

Native Claude and Codex sessions in the import picker

Hover

Teleport Out tooltip

Teleport In tooltip

Composer disabled after Teleport Out

Composer disabled when the thread is in the native CLI

Recordings

Codex
codex_teleport_roundtrip_nologo.mp4

Claude
claude_teleport_roundtrip_nologo.mp4

Why

Two-way teleport needs a shared engine, UI, and one adapter per CLI. This PR is that whole stack in one diff because stacked bases have to exist on pingdotgg/t3code.

UI Changes

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Relates to #207, #5146, #5741, and #6590.

Note

Add two-way teleport between app threads and native CLI sessions

  • Introduces a full teleport system allowing threads to be exported to native CLI sessions (Claude, Codex, Grok, OpenCode) and imported back, with message history synchronization via new thread.history.replace and thread.teleport.set orchestration commands.
  • Adds TeleportService with list/import/export session RPCs (teleport.listSessions, teleport.importSessions, teleport.exportSession) wired into the WS layer with scope-based authorization.
  • Adds per-provider JSONL/directory format adapters with schema-version gating, file-lock detection, and atomic writes; a registry pattern enables runtime format registration.
  • Extends the command palette and chat UI with session browsing, import flows, a TeleportOutButton in the chat header, and composer/send disabling when a thread is teleported-out.
  • Adds DB migration 041 adding teleport_json to projection_threads with backfill from existing runtime telemetry.
  • Risk: thread.turn.start now fails with OrchestrationCommandInvariantError if the thread's teleport presence is native, blocking turn creation on teleported-out threads.
📊 Macroscope summarized 18ed3c0. 52 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

cursoragentand others added 20 commits August 15, 2026 08:54
Contracts, orchestration, and the teleport service land first. Native CLI
formats register later, so list/import/export stay empty until a provider
adapter is added.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
The UI can list, import, and export native sessions. Until a format
adapter is registered, the picker stays empty and export fails closed.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Codex jsonl adapter so T3 can list, import, and export
rollouts the CLI can resume.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the OpenCode adapter so T3 can list, import, and export text
turns from opencode.db or JSON storage without treating the live db as a
foreign lock.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Claude jsonl adapter so T3 can list, import, and export
sessions from the Claude projects folder.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Grok session-directory adapter so T3 can list, import, and
export native Grok Build chats.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Stop marked the turn interrupted but left the session running, so the thread stayed Working after abort hung or only emitted turn.aborted.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
A projected running OpenCode thread stayed Working after Stop if the
in-memory provider session was already gone. Interrupt no longer
recovers a session just to abort it, and Stop settles the projection
when there is nothing live to interrupt.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep live-session titles and personal directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@coderabbitai

coderabbitaiBot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a86460d-dc34-4a24-9c87-02e715f5dd10

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 15, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small consistency findings in the new teleport UI. Everything else in the changed web files (command palette views, composer disabled/placeholder handling, ChatView toast) follows the existing primitives and layout conventions.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/DraftHeroHeadline.tsx Outdated
Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the new TeleportService (plus its contract errors). Four convention violations found; details inline.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/Services/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/orchestration/Layers/ProjectionPipeline.ts
Comment threadapps/server/src/teleport/formats/codex.ts
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/cwd.ts Outdated
Comment threadapps/server/src/teleport/formats/grok.ts Outdated
Comment threadapps/server/src/teleport/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadapps/server/src/orchestration/decider.ts Outdated
baanishand others added 3 commits August 15, 2026 15:30
The import CTA lacked cursor-pointer, and the header export control used
the text xs size instead of the square icon-xs used by neighboring actions.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Reject unsafe session ids on native reads/writes, fail closed when lock
checks cannot run, keep Codex whitespace, preserve in-place provider
instances, and clear stale history/approvals when replacing a thread.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new header control's disabled state suppresses the tooltip that explains why it is unavailable.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated
Effect 4 does not provide zipRight on Effect. Complete the sendTurn abort latch from a generator finalizer instead.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts Outdated
cursoragentand others added 4 commits August 17, 2026 20:35
Claim the in-flight abort through an atomic gate so a second interrupt waits instead of emitting another turn.aborted or calling session.abort again.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export writes the native session cwd from the thread worktree, which lives
outside the project root. Listing and import treated only the workspace root
as in-project, so Teleport Out was a one-way door.
Discover extra cwds from the project's thread worktrees, match subdirectory
sessions, and stop accepting ancestor cwds such as / or $HOME.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export set presence to native with a teleport-pending path before writing
the CLI file, then only reverted on write tapError. Interruptions, defects,
and later directory or teleport.set failures left the thread stuck: the UI
only offered Import, which rejected the fake path.
Wrap the pending presence in acquireUseRelease so any unsuccessful exit
reverts to T3, or persists the real native path if the file was written.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Release-path persist of a written native session can still raise a
filesystem error. Catch that so a failed bind cannot mask the export
failure or skip reverting pending presence.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two error-modeling convention issues in the new teleport code: message stored as data when it is a fixed template over existing attributes, and a helper whose only behavior is constructing that error.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Lock, schema, identity, and file-locked errors now derive `message` from
their fields, so the lockProbeError helper can go. A failed new-thread
import deletes the orphan thread instead of leaving it unbound.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/nativeWrite.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new teleport service against the Effect service conventions. Service shape (Context.Service with inline interface, exported make/layer), dependency acquisition via yield*, and Effect.catchTags usage all look right now. Three remaining error-modelling issues below.

Posted via Macroscope — Effect Service Conventions

Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/formats/codex.ts Outdated
cursoragentand others added 3 commits August 17, 2026 22:33
Store a write stage instead of a free-form message on TeleportNativeWriteError,
derive TeleportUnsupportedProviderError from the provider, and remap schema
verification with catchTags. On Windows, replace native files by moving the
destination aside so a failed rename can restore the previous session.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Persist teleport ownership first so a failed history replace cannot leave an
unbound thread with overwritten messages.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep the teleported-out composer disable path and use main's
disconnected placeholder constant.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/ChatView.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new chat-header teleport button loses the themed toolbar control styling because the tooltip wrapper overwrites data-slot="button". See the inline comment for the one-attribute fix.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx
cursoragentand others added 5 commits August 19, 2026 03:27
TooltipTrigger replaces data-slot=button, so custom themes skipped this
icon. Opt in with data-toolbar-control the same way ProjectScriptsControl does.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Send-disabled only grayed the editor. Type-to-focus, mention drops, and
file drops could still queue hidden draft content. Reject those paths too.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
In-place native session import persisted directory binding, teleport
presence, unarchive, history, and title as separate durable mutations.
A later failure left T3 ownership and history out of sync, and a
concurrent turn could run against that intermediate state.
Commit ownership, history, and unarchive in one orchestration command.
Fence thread.turn.start with importing presence, recover leftover
importing state on startup, and keep title plus directory finalize
best-effort. Import stays atomic per session, not all-or-nothing for
the batch.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/importTransaction.ts Outdated
cursoragentand others added 3 commits August 19, 2026 05:55
tapError only saw typed failures, so a cancelled or defective pre-commit
import step could leave presence "importing" until process restart.
onError reverts for fail, die, and interrupt, and keeps revert running.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatView's teleport send-disabled import. Main moved the collapsed
sidebar titlebar inset into WorkspacePageHeader, so that import is gone.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatComposer's teleport lock on the prompt editor after main
moved send/stop into the footer. Native and importing presence still
disable the editor and show the send-disabled reason.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/chat/ChatComposer.tsx
Paste/drop could start before teleport lock, then attach compressed
images after compression finished. Stash restore and stash-current
could also write into a native/importing draft. Recheck send-disabled
after awaits and reject those stash mutations while teleport-locked.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@t3-code

t3-codeBot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

closing because this is explicitly marked Draft. Do not merge. and documents cross-fork teleport exploration rather than merge-ready work.

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

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@baanish@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Draft: two-way teleport with native CLI sessions - #7136

Closed
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23
Closed

Draft: two-way teleport with native CLI sessions#7136
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23

Conversation

@baanish

@baanishbaanish commented Aug 15, 2026

Copy link
Copy Markdown

Draft. Do not merge. Exploration of two-way teleport. Opened as one PR because GitHub cannot stack cross-fork bases on this repo.

What Changed

T3 Code can list, import, and export native CLI sessions for Codex, and Claude.
Native files stay native. Import copies a CLI session onto a T3 thread. Export writes the thread back. Presence (t3 vs native) swaps Import/Export so both sides are not writers at once.
Codex export writes session_meta the CLI can resume. OpenCode imports text turns only, does not treat live opencode.db as a foreign lock, and does not match parent cwds into sibling codex / claude / grok folders. Stop settles Working when the turn is aborted, when there is no live session, or when interrupt fails.

UI

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

New UI

Draft hero Import a native CLI session link

Command palette Import sessions action

Native Claude and Codex sessions in the import picker

Hover

Teleport Out tooltip

Teleport In tooltip

Composer disabled after Teleport Out

Composer disabled when the thread is in the native CLI

Recordings

Codex
codex_teleport_roundtrip_nologo.mp4

Claude
claude_teleport_roundtrip_nologo.mp4

Why

Two-way teleport needs a shared engine, UI, and one adapter per CLI. This PR is that whole stack in one diff because stacked bases have to exist on pingdotgg/t3code.

UI Changes

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Relates to #207, #5146, #5741, and #6590.

Note

Add two-way teleport between app threads and native CLI sessions

  • Introduces a full teleport system allowing threads to be exported to native CLI sessions (Claude, Codex, Grok, OpenCode) and imported back, with message history synchronization via new thread.history.replace and thread.teleport.set orchestration commands.
  • Adds TeleportService with list/import/export session RPCs (teleport.listSessions, teleport.importSessions, teleport.exportSession) wired into the WS layer with scope-based authorization.
  • Adds per-provider JSONL/directory format adapters with schema-version gating, file-lock detection, and atomic writes; a registry pattern enables runtime format registration.
  • Extends the command palette and chat UI with session browsing, import flows, a TeleportOutButton in the chat header, and composer/send disabling when a thread is teleported-out.
  • Adds DB migration 041 adding teleport_json to projection_threads with backfill from existing runtime telemetry.
  • Risk: thread.turn.start now fails with OrchestrationCommandInvariantError if the thread's teleport presence is native, blocking turn creation on teleported-out threads.
📊 Macroscope summarized 18ed3c0. 52 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

cursoragentand others added 20 commits August 15, 2026 08:54
Contracts, orchestration, and the teleport service land first. Native CLI
formats register later, so list/import/export stay empty until a provider
adapter is added.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
The UI can list, import, and export native sessions. Until a format
adapter is registered, the picker stays empty and export fails closed.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Codex jsonl adapter so T3 can list, import, and export
rollouts the CLI can resume.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the OpenCode adapter so T3 can list, import, and export text
turns from opencode.db or JSON storage without treating the live db as a
foreign lock.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Claude jsonl adapter so T3 can list, import, and export
sessions from the Claude projects folder.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Grok session-directory adapter so T3 can list, import, and
export native Grok Build chats.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Stop marked the turn interrupted but left the session running, so the thread stayed Working after abort hung or only emitted turn.aborted.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
A projected running OpenCode thread stayed Working after Stop if the
in-memory provider session was already gone. Interrupt no longer
recovers a session just to abort it, and Stop settles the projection
when there is nothing live to interrupt.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep live-session titles and personal directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@coderabbitai

coderabbitaiBot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a86460d-dc34-4a24-9c87-02e715f5dd10

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 15, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small consistency findings in the new teleport UI. Everything else in the changed web files (command palette views, composer disabled/placeholder handling, ChatView toast) follows the existing primitives and layout conventions.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/DraftHeroHeadline.tsx Outdated
Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the new TeleportService (plus its contract errors). Four convention violations found; details inline.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/Services/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/orchestration/Layers/ProjectionPipeline.ts
Comment threadapps/server/src/teleport/formats/codex.ts
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/cwd.ts Outdated
Comment threadapps/server/src/teleport/formats/grok.ts Outdated
Comment threadapps/server/src/teleport/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadapps/server/src/orchestration/decider.ts Outdated
baanishand others added 3 commits August 15, 2026 15:30
The import CTA lacked cursor-pointer, and the header export control used
the text xs size instead of the square icon-xs used by neighboring actions.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Reject unsafe session ids on native reads/writes, fail closed when lock
checks cannot run, keep Codex whitespace, preserve in-place provider
instances, and clear stale history/approvals when replacing a thread.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new header control's disabled state suppresses the tooltip that explains why it is unavailable.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated
Effect 4 does not provide zipRight on Effect. Complete the sendTurn abort latch from a generator finalizer instead.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts Outdated
cursoragentand others added 4 commits August 17, 2026 20:35
Claim the in-flight abort through an atomic gate so a second interrupt waits instead of emitting another turn.aborted or calling session.abort again.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export writes the native session cwd from the thread worktree, which lives
outside the project root. Listing and import treated only the workspace root
as in-project, so Teleport Out was a one-way door.
Discover extra cwds from the project's thread worktrees, match subdirectory
sessions, and stop accepting ancestor cwds such as / or $HOME.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export set presence to native with a teleport-pending path before writing
the CLI file, then only reverted on write tapError. Interruptions, defects,
and later directory or teleport.set failures left the thread stuck: the UI
only offered Import, which rejected the fake path.
Wrap the pending presence in acquireUseRelease so any unsuccessful exit
reverts to T3, or persists the real native path if the file was written.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Release-path persist of a written native session can still raise a
filesystem error. Catch that so a failed bind cannot mask the export
failure or skip reverting pending presence.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two error-modeling convention issues in the new teleport code: message stored as data when it is a fixed template over existing attributes, and a helper whose only behavior is constructing that error.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Lock, schema, identity, and file-locked errors now derive `message` from
their fields, so the lockProbeError helper can go. A failed new-thread
import deletes the orphan thread instead of leaving it unbound.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/nativeWrite.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new teleport service against the Effect service conventions. Service shape (Context.Service with inline interface, exported make/layer), dependency acquisition via yield*, and Effect.catchTags usage all look right now. Three remaining error-modelling issues below.

Posted via Macroscope — Effect Service Conventions

Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/formats/codex.ts Outdated
cursoragentand others added 3 commits August 17, 2026 22:33
Store a write stage instead of a free-form message on TeleportNativeWriteError,
derive TeleportUnsupportedProviderError from the provider, and remap schema
verification with catchTags. On Windows, replace native files by moving the
destination aside so a failed rename can restore the previous session.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Persist teleport ownership first so a failed history replace cannot leave an
unbound thread with overwritten messages.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep the teleported-out composer disable path and use main's
disconnected placeholder constant.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/ChatView.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new chat-header teleport button loses the themed toolbar control styling because the tooltip wrapper overwrites data-slot="button". See the inline comment for the one-attribute fix.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx
cursoragentand others added 5 commits August 19, 2026 03:27
TooltipTrigger replaces data-slot=button, so custom themes skipped this
icon. Opt in with data-toolbar-control the same way ProjectScriptsControl does.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Send-disabled only grayed the editor. Type-to-focus, mention drops, and
file drops could still queue hidden draft content. Reject those paths too.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
In-place native session import persisted directory binding, teleport
presence, unarchive, history, and title as separate durable mutations.
A later failure left T3 ownership and history out of sync, and a
concurrent turn could run against that intermediate state.
Commit ownership, history, and unarchive in one orchestration command.
Fence thread.turn.start with importing presence, recover leftover
importing state on startup, and keep title plus directory finalize
best-effort. Import stays atomic per session, not all-or-nothing for
the batch.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/importTransaction.ts Outdated
cursoragentand others added 3 commits August 19, 2026 05:55
tapError only saw typed failures, so a cancelled or defective pre-commit
import step could leave presence "importing" until process restart.
onError reverts for fail, die, and interrupt, and keeps revert running.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatView's teleport send-disabled import. Main moved the collapsed
sidebar titlebar inset into WorkspacePageHeader, so that import is gone.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatComposer's teleport lock on the prompt editor after main
moved send/stop into the footer. Native and importing presence still
disable the editor and show the send-disabled reason.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/chat/ChatComposer.tsx
Paste/drop could start before teleport lock, then attach compressed
images after compression finished. Stash restore and stash-current
could also write into a native/importing draft. Recheck send-disabled
after awaits and reject those stash mutations while teleport-locked.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@t3-code

t3-codeBot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

closing because this is explicitly marked Draft. Do not merge. and documents cross-fork teleport exploration rather than merge-ready work.

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

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@baanish@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Draft: two-way teleport with native CLI sessions - #7136

Closed
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23
Closed

Draft: two-way teleport with native CLI sessions#7136
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23

Conversation

@baanish

@baanishbaanish commented Aug 15, 2026

Copy link
Copy Markdown

Draft. Do not merge. Exploration of two-way teleport. Opened as one PR because GitHub cannot stack cross-fork bases on this repo.

What Changed

T3 Code can list, import, and export native CLI sessions for Codex, and Claude.
Native files stay native. Import copies a CLI session onto a T3 thread. Export writes the thread back. Presence (t3 vs native) swaps Import/Export so both sides are not writers at once.
Codex export writes session_meta the CLI can resume. OpenCode imports text turns only, does not treat live opencode.db as a foreign lock, and does not match parent cwds into sibling codex / claude / grok folders. Stop settles Working when the turn is aborted, when there is no live session, or when interrupt fails.

UI

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

New UI

Draft hero Import a native CLI session link

Command palette Import sessions action

Native Claude and Codex sessions in the import picker

Hover

Teleport Out tooltip

Teleport In tooltip

Composer disabled after Teleport Out

Composer disabled when the thread is in the native CLI

Recordings

Codex
codex_teleport_roundtrip_nologo.mp4

Claude
claude_teleport_roundtrip_nologo.mp4

Why

Two-way teleport needs a shared engine, UI, and one adapter per CLI. This PR is that whole stack in one diff because stacked bases have to exist on pingdotgg/t3code.

UI Changes

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Relates to #207, #5146, #5741, and #6590.

Note

Add two-way teleport between app threads and native CLI sessions

  • Introduces a full teleport system allowing threads to be exported to native CLI sessions (Claude, Codex, Grok, OpenCode) and imported back, with message history synchronization via new thread.history.replace and thread.teleport.set orchestration commands.
  • Adds TeleportService with list/import/export session RPCs (teleport.listSessions, teleport.importSessions, teleport.exportSession) wired into the WS layer with scope-based authorization.
  • Adds per-provider JSONL/directory format adapters with schema-version gating, file-lock detection, and atomic writes; a registry pattern enables runtime format registration.
  • Extends the command palette and chat UI with session browsing, import flows, a TeleportOutButton in the chat header, and composer/send disabling when a thread is teleported-out.
  • Adds DB migration 041 adding teleport_json to projection_threads with backfill from existing runtime telemetry.
  • Risk: thread.turn.start now fails with OrchestrationCommandInvariantError if the thread's teleport presence is native, blocking turn creation on teleported-out threads.
📊 Macroscope summarized 18ed3c0. 52 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

cursoragentand others added 20 commits August 15, 2026 08:54
Contracts, orchestration, and the teleport service land first. Native CLI
formats register later, so list/import/export stay empty until a provider
adapter is added.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
The UI can list, import, and export native sessions. Until a format
adapter is registered, the picker stays empty and export fails closed.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Codex jsonl adapter so T3 can list, import, and export
rollouts the CLI can resume.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the OpenCode adapter so T3 can list, import, and export text
turns from opencode.db or JSON storage without treating the live db as a
foreign lock.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Claude jsonl adapter so T3 can list, import, and export
sessions from the Claude projects folder.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Grok session-directory adapter so T3 can list, import, and
export native Grok Build chats.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Stop marked the turn interrupted but left the session running, so the thread stayed Working after abort hung or only emitted turn.aborted.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
A projected running OpenCode thread stayed Working after Stop if the
in-memory provider session was already gone. Interrupt no longer
recovers a session just to abort it, and Stop settles the projection
when there is nothing live to interrupt.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep live-session titles and personal directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@coderabbitai

coderabbitaiBot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a86460d-dc34-4a24-9c87-02e715f5dd10

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 15, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small consistency findings in the new teleport UI. Everything else in the changed web files (command palette views, composer disabled/placeholder handling, ChatView toast) follows the existing primitives and layout conventions.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/DraftHeroHeadline.tsx Outdated
Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the new TeleportService (plus its contract errors). Four convention violations found; details inline.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/Services/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/orchestration/Layers/ProjectionPipeline.ts
Comment threadapps/server/src/teleport/formats/codex.ts
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/cwd.ts Outdated
Comment threadapps/server/src/teleport/formats/grok.ts Outdated
Comment threadapps/server/src/teleport/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadapps/server/src/orchestration/decider.ts Outdated
baanishand others added 3 commits August 15, 2026 15:30
The import CTA lacked cursor-pointer, and the header export control used
the text xs size instead of the square icon-xs used by neighboring actions.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Reject unsafe session ids on native reads/writes, fail closed when lock
checks cannot run, keep Codex whitespace, preserve in-place provider
instances, and clear stale history/approvals when replacing a thread.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new header control's disabled state suppresses the tooltip that explains why it is unavailable.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated
Effect 4 does not provide zipRight on Effect. Complete the sendTurn abort latch from a generator finalizer instead.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts Outdated
cursoragentand others added 4 commits August 17, 2026 20:35
Claim the in-flight abort through an atomic gate so a second interrupt waits instead of emitting another turn.aborted or calling session.abort again.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export writes the native session cwd from the thread worktree, which lives
outside the project root. Listing and import treated only the workspace root
as in-project, so Teleport Out was a one-way door.
Discover extra cwds from the project's thread worktrees, match subdirectory
sessions, and stop accepting ancestor cwds such as / or $HOME.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export set presence to native with a teleport-pending path before writing
the CLI file, then only reverted on write tapError. Interruptions, defects,
and later directory or teleport.set failures left the thread stuck: the UI
only offered Import, which rejected the fake path.
Wrap the pending presence in acquireUseRelease so any unsuccessful exit
reverts to T3, or persists the real native path if the file was written.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Release-path persist of a written native session can still raise a
filesystem error. Catch that so a failed bind cannot mask the export
failure or skip reverting pending presence.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two error-modeling convention issues in the new teleport code: message stored as data when it is a fixed template over existing attributes, and a helper whose only behavior is constructing that error.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Lock, schema, identity, and file-locked errors now derive `message` from
their fields, so the lockProbeError helper can go. A failed new-thread
import deletes the orphan thread instead of leaving it unbound.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/nativeWrite.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new teleport service against the Effect service conventions. Service shape (Context.Service with inline interface, exported make/layer), dependency acquisition via yield*, and Effect.catchTags usage all look right now. Three remaining error-modelling issues below.

Posted via Macroscope — Effect Service Conventions

Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/formats/codex.ts Outdated
cursoragentand others added 3 commits August 17, 2026 22:33
Store a write stage instead of a free-form message on TeleportNativeWriteError,
derive TeleportUnsupportedProviderError from the provider, and remap schema
verification with catchTags. On Windows, replace native files by moving the
destination aside so a failed rename can restore the previous session.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Persist teleport ownership first so a failed history replace cannot leave an
unbound thread with overwritten messages.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep the teleported-out composer disable path and use main's
disconnected placeholder constant.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/ChatView.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new chat-header teleport button loses the themed toolbar control styling because the tooltip wrapper overwrites data-slot="button". See the inline comment for the one-attribute fix.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx
cursoragentand others added 5 commits August 19, 2026 03:27
TooltipTrigger replaces data-slot=button, so custom themes skipped this
icon. Opt in with data-toolbar-control the same way ProjectScriptsControl does.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Send-disabled only grayed the editor. Type-to-focus, mention drops, and
file drops could still queue hidden draft content. Reject those paths too.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
In-place native session import persisted directory binding, teleport
presence, unarchive, history, and title as separate durable mutations.
A later failure left T3 ownership and history out of sync, and a
concurrent turn could run against that intermediate state.
Commit ownership, history, and unarchive in one orchestration command.
Fence thread.turn.start with importing presence, recover leftover
importing state on startup, and keep title plus directory finalize
best-effort. Import stays atomic per session, not all-or-nothing for
the batch.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/importTransaction.ts Outdated
cursoragentand others added 3 commits August 19, 2026 05:55
tapError only saw typed failures, so a cancelled or defective pre-commit
import step could leave presence "importing" until process restart.
onError reverts for fail, die, and interrupt, and keeps revert running.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatView's teleport send-disabled import. Main moved the collapsed
sidebar titlebar inset into WorkspacePageHeader, so that import is gone.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatComposer's teleport lock on the prompt editor after main
moved send/stop into the footer. Native and importing presence still
disable the editor and show the send-disabled reason.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/chat/ChatComposer.tsx
Paste/drop could start before teleport lock, then attach compressed
images after compression finished. Stash restore and stash-current
could also write into a native/importing draft. Recheck send-disabled
after awaits and reject those stash mutations while teleport-locked.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@t3-code

t3-codeBot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

closing because this is explicitly marked Draft. Do not merge. and documents cross-fork teleport exploration rather than merge-ready work.

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

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@baanish@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Draft: two-way teleport with native CLI sessions - #7136

Closed
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23
Closed

Draft: two-way teleport with native CLI sessions#7136
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23

Conversation

@baanish

@baanishbaanish commented Aug 15, 2026

Copy link
Copy Markdown

Draft. Do not merge. Exploration of two-way teleport. Opened as one PR because GitHub cannot stack cross-fork bases on this repo.

What Changed

T3 Code can list, import, and export native CLI sessions for Codex, and Claude.
Native files stay native. Import copies a CLI session onto a T3 thread. Export writes the thread back. Presence (t3 vs native) swaps Import/Export so both sides are not writers at once.
Codex export writes session_meta the CLI can resume. OpenCode imports text turns only, does not treat live opencode.db as a foreign lock, and does not match parent cwds into sibling codex / claude / grok folders. Stop settles Working when the turn is aborted, when there is no live session, or when interrupt fails.

UI

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

New UI

Draft hero Import a native CLI session link

Command palette Import sessions action

Native Claude and Codex sessions in the import picker

Hover

Teleport Out tooltip

Teleport In tooltip

Composer disabled after Teleport Out

Composer disabled when the thread is in the native CLI

Recordings

Codex
codex_teleport_roundtrip_nologo.mp4

Claude
claude_teleport_roundtrip_nologo.mp4

Why

Two-way teleport needs a shared engine, UI, and one adapter per CLI. This PR is that whole stack in one diff because stacked bases have to exist on pingdotgg/t3code.

UI Changes

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Relates to #207, #5146, #5741, and #6590.

Note

Add two-way teleport between app threads and native CLI sessions

  • Introduces a full teleport system allowing threads to be exported to native CLI sessions (Claude, Codex, Grok, OpenCode) and imported back, with message history synchronization via new thread.history.replace and thread.teleport.set orchestration commands.
  • Adds TeleportService with list/import/export session RPCs (teleport.listSessions, teleport.importSessions, teleport.exportSession) wired into the WS layer with scope-based authorization.
  • Adds per-provider JSONL/directory format adapters with schema-version gating, file-lock detection, and atomic writes; a registry pattern enables runtime format registration.
  • Extends the command palette and chat UI with session browsing, import flows, a TeleportOutButton in the chat header, and composer/send disabling when a thread is teleported-out.
  • Adds DB migration 041 adding teleport_json to projection_threads with backfill from existing runtime telemetry.
  • Risk: thread.turn.start now fails with OrchestrationCommandInvariantError if the thread's teleport presence is native, blocking turn creation on teleported-out threads.
📊 Macroscope summarized 18ed3c0. 52 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

cursoragentand others added 20 commits August 15, 2026 08:54
Contracts, orchestration, and the teleport service land first. Native CLI
formats register later, so list/import/export stay empty until a provider
adapter is added.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
The UI can list, import, and export native sessions. Until a format
adapter is registered, the picker stays empty and export fails closed.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Codex jsonl adapter so T3 can list, import, and export
rollouts the CLI can resume.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the OpenCode adapter so T3 can list, import, and export text
turns from opencode.db or JSON storage without treating the live db as a
foreign lock.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Claude jsonl adapter so T3 can list, import, and export
sessions from the Claude projects folder.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Grok session-directory adapter so T3 can list, import, and
export native Grok Build chats.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Stop marked the turn interrupted but left the session running, so the thread stayed Working after abort hung or only emitted turn.aborted.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
A projected running OpenCode thread stayed Working after Stop if the
in-memory provider session was already gone. Interrupt no longer
recovers a session just to abort it, and Stop settles the projection
when there is nothing live to interrupt.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep live-session titles and personal directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@coderabbitai

coderabbitaiBot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a86460d-dc34-4a24-9c87-02e715f5dd10

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 15, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small consistency findings in the new teleport UI. Everything else in the changed web files (command palette views, composer disabled/placeholder handling, ChatView toast) follows the existing primitives and layout conventions.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/DraftHeroHeadline.tsx Outdated
Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the new TeleportService (plus its contract errors). Four convention violations found; details inline.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/Services/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/orchestration/Layers/ProjectionPipeline.ts
Comment threadapps/server/src/teleport/formats/codex.ts
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/cwd.ts Outdated
Comment threadapps/server/src/teleport/formats/grok.ts Outdated
Comment threadapps/server/src/teleport/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadapps/server/src/orchestration/decider.ts Outdated
baanishand others added 3 commits August 15, 2026 15:30
The import CTA lacked cursor-pointer, and the header export control used
the text xs size instead of the square icon-xs used by neighboring actions.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Reject unsafe session ids on native reads/writes, fail closed when lock
checks cannot run, keep Codex whitespace, preserve in-place provider
instances, and clear stale history/approvals when replacing a thread.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new header control's disabled state suppresses the tooltip that explains why it is unavailable.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated
Effect 4 does not provide zipRight on Effect. Complete the sendTurn abort latch from a generator finalizer instead.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts Outdated
cursoragentand others added 4 commits August 17, 2026 20:35
Claim the in-flight abort through an atomic gate so a second interrupt waits instead of emitting another turn.aborted or calling session.abort again.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export writes the native session cwd from the thread worktree, which lives
outside the project root. Listing and import treated only the workspace root
as in-project, so Teleport Out was a one-way door.
Discover extra cwds from the project's thread worktrees, match subdirectory
sessions, and stop accepting ancestor cwds such as / or $HOME.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export set presence to native with a teleport-pending path before writing
the CLI file, then only reverted on write tapError. Interruptions, defects,
and later directory or teleport.set failures left the thread stuck: the UI
only offered Import, which rejected the fake path.
Wrap the pending presence in acquireUseRelease so any unsuccessful exit
reverts to T3, or persists the real native path if the file was written.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Release-path persist of a written native session can still raise a
filesystem error. Catch that so a failed bind cannot mask the export
failure or skip reverting pending presence.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two error-modeling convention issues in the new teleport code: message stored as data when it is a fixed template over existing attributes, and a helper whose only behavior is constructing that error.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Lock, schema, identity, and file-locked errors now derive `message` from
their fields, so the lockProbeError helper can go. A failed new-thread
import deletes the orphan thread instead of leaving it unbound.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/nativeWrite.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new teleport service against the Effect service conventions. Service shape (Context.Service with inline interface, exported make/layer), dependency acquisition via yield*, and Effect.catchTags usage all look right now. Three remaining error-modelling issues below.

Posted via Macroscope — Effect Service Conventions

Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/formats/codex.ts Outdated
cursoragentand others added 3 commits August 17, 2026 22:33
Store a write stage instead of a free-form message on TeleportNativeWriteError,
derive TeleportUnsupportedProviderError from the provider, and remap schema
verification with catchTags. On Windows, replace native files by moving the
destination aside so a failed rename can restore the previous session.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Persist teleport ownership first so a failed history replace cannot leave an
unbound thread with overwritten messages.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep the teleported-out composer disable path and use main's
disconnected placeholder constant.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/ChatView.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new chat-header teleport button loses the themed toolbar control styling because the tooltip wrapper overwrites data-slot="button". See the inline comment for the one-attribute fix.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx
cursoragentand others added 5 commits August 19, 2026 03:27
TooltipTrigger replaces data-slot=button, so custom themes skipped this
icon. Opt in with data-toolbar-control the same way ProjectScriptsControl does.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Send-disabled only grayed the editor. Type-to-focus, mention drops, and
file drops could still queue hidden draft content. Reject those paths too.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
In-place native session import persisted directory binding, teleport
presence, unarchive, history, and title as separate durable mutations.
A later failure left T3 ownership and history out of sync, and a
concurrent turn could run against that intermediate state.
Commit ownership, history, and unarchive in one orchestration command.
Fence thread.turn.start with importing presence, recover leftover
importing state on startup, and keep title plus directory finalize
best-effort. Import stays atomic per session, not all-or-nothing for
the batch.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/importTransaction.ts Outdated
cursoragentand others added 3 commits August 19, 2026 05:55
tapError only saw typed failures, so a cancelled or defective pre-commit
import step could leave presence "importing" until process restart.
onError reverts for fail, die, and interrupt, and keeps revert running.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatView's teleport send-disabled import. Main moved the collapsed
sidebar titlebar inset into WorkspacePageHeader, so that import is gone.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatComposer's teleport lock on the prompt editor after main
moved send/stop into the footer. Native and importing presence still
disable the editor and show the send-disabled reason.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/chat/ChatComposer.tsx
Paste/drop could start before teleport lock, then attach compressed
images after compression finished. Stash restore and stash-current
could also write into a native/importing draft. Recheck send-disabled
after awaits and reject those stash mutations while teleport-locked.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@t3-code

t3-codeBot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

closing because this is explicitly marked Draft. Do not merge. and documents cross-fork teleport exploration rather than merge-ready work.

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

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@baanish@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Draft: two-way teleport with native CLI sessions - #7136

Closed
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23
Closed

Draft: two-way teleport with native CLI sessions#7136
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23

Conversation

@baanish

@baanishbaanish commented Aug 15, 2026

Copy link
Copy Markdown

Draft. Do not merge. Exploration of two-way teleport. Opened as one PR because GitHub cannot stack cross-fork bases on this repo.

What Changed

T3 Code can list, import, and export native CLI sessions for Codex, and Claude.
Native files stay native. Import copies a CLI session onto a T3 thread. Export writes the thread back. Presence (t3 vs native) swaps Import/Export so both sides are not writers at once.
Codex export writes session_meta the CLI can resume. OpenCode imports text turns only, does not treat live opencode.db as a foreign lock, and does not match parent cwds into sibling codex / claude / grok folders. Stop settles Working when the turn is aborted, when there is no live session, or when interrupt fails.

UI

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

New UI

Draft hero Import a native CLI session link

Command palette Import sessions action

Native Claude and Codex sessions in the import picker

Hover

Teleport Out tooltip

Teleport In tooltip

Composer disabled after Teleport Out

Composer disabled when the thread is in the native CLI

Recordings

Codex
codex_teleport_roundtrip_nologo.mp4

Claude
claude_teleport_roundtrip_nologo.mp4

Why

Two-way teleport needs a shared engine, UI, and one adapter per CLI. This PR is that whole stack in one diff because stacked bases have to exist on pingdotgg/t3code.

UI Changes

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Relates to #207, #5146, #5741, and #6590.

Note

Add two-way teleport between app threads and native CLI sessions

  • Introduces a full teleport system allowing threads to be exported to native CLI sessions (Claude, Codex, Grok, OpenCode) and imported back, with message history synchronization via new thread.history.replace and thread.teleport.set orchestration commands.
  • Adds TeleportService with list/import/export session RPCs (teleport.listSessions, teleport.importSessions, teleport.exportSession) wired into the WS layer with scope-based authorization.
  • Adds per-provider JSONL/directory format adapters with schema-version gating, file-lock detection, and atomic writes; a registry pattern enables runtime format registration.
  • Extends the command palette and chat UI with session browsing, import flows, a TeleportOutButton in the chat header, and composer/send disabling when a thread is teleported-out.
  • Adds DB migration 041 adding teleport_json to projection_threads with backfill from existing runtime telemetry.
  • Risk: thread.turn.start now fails with OrchestrationCommandInvariantError if the thread's teleport presence is native, blocking turn creation on teleported-out threads.
📊 Macroscope summarized 18ed3c0. 52 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

cursoragentand others added 20 commits August 15, 2026 08:54
Contracts, orchestration, and the teleport service land first. Native CLI
formats register later, so list/import/export stay empty until a provider
adapter is added.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
The UI can list, import, and export native sessions. Until a format
adapter is registered, the picker stays empty and export fails closed.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Codex jsonl adapter so T3 can list, import, and export
rollouts the CLI can resume.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the OpenCode adapter so T3 can list, import, and export text
turns from opencode.db or JSON storage without treating the live db as a
foreign lock.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Claude jsonl adapter so T3 can list, import, and export
sessions from the Claude projects folder.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Grok session-directory adapter so T3 can list, import, and
export native Grok Build chats.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Stop marked the turn interrupted but left the session running, so the thread stayed Working after abort hung or only emitted turn.aborted.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
A projected running OpenCode thread stayed Working after Stop if the
in-memory provider session was already gone. Interrupt no longer
recovers a session just to abort it, and Stop settles the projection
when there is nothing live to interrupt.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep live-session titles and personal directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@coderabbitai

coderabbitaiBot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a86460d-dc34-4a24-9c87-02e715f5dd10

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 15, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small consistency findings in the new teleport UI. Everything else in the changed web files (command palette views, composer disabled/placeholder handling, ChatView toast) follows the existing primitives and layout conventions.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/DraftHeroHeadline.tsx Outdated
Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the new TeleportService (plus its contract errors). Four convention violations found; details inline.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/Services/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/orchestration/Layers/ProjectionPipeline.ts
Comment threadapps/server/src/teleport/formats/codex.ts
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/cwd.ts Outdated
Comment threadapps/server/src/teleport/formats/grok.ts Outdated
Comment threadapps/server/src/teleport/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadapps/server/src/orchestration/decider.ts Outdated
baanishand others added 3 commits August 15, 2026 15:30
The import CTA lacked cursor-pointer, and the header export control used
the text xs size instead of the square icon-xs used by neighboring actions.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Reject unsafe session ids on native reads/writes, fail closed when lock
checks cannot run, keep Codex whitespace, preserve in-place provider
instances, and clear stale history/approvals when replacing a thread.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new header control's disabled state suppresses the tooltip that explains why it is unavailable.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated
Effect 4 does not provide zipRight on Effect. Complete the sendTurn abort latch from a generator finalizer instead.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts Outdated
cursoragentand others added 4 commits August 17, 2026 20:35
Claim the in-flight abort through an atomic gate so a second interrupt waits instead of emitting another turn.aborted or calling session.abort again.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export writes the native session cwd from the thread worktree, which lives
outside the project root. Listing and import treated only the workspace root
as in-project, so Teleport Out was a one-way door.
Discover extra cwds from the project's thread worktrees, match subdirectory
sessions, and stop accepting ancestor cwds such as / or $HOME.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export set presence to native with a teleport-pending path before writing
the CLI file, then only reverted on write tapError. Interruptions, defects,
and later directory or teleport.set failures left the thread stuck: the UI
only offered Import, which rejected the fake path.
Wrap the pending presence in acquireUseRelease so any unsuccessful exit
reverts to T3, or persists the real native path if the file was written.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Release-path persist of a written native session can still raise a
filesystem error. Catch that so a failed bind cannot mask the export
failure or skip reverting pending presence.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two error-modeling convention issues in the new teleport code: message stored as data when it is a fixed template over existing attributes, and a helper whose only behavior is constructing that error.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Lock, schema, identity, and file-locked errors now derive `message` from
their fields, so the lockProbeError helper can go. A failed new-thread
import deletes the orphan thread instead of leaving it unbound.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/nativeWrite.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new teleport service against the Effect service conventions. Service shape (Context.Service with inline interface, exported make/layer), dependency acquisition via yield*, and Effect.catchTags usage all look right now. Three remaining error-modelling issues below.

Posted via Macroscope — Effect Service Conventions

Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/formats/codex.ts Outdated
cursoragentand others added 3 commits August 17, 2026 22:33
Store a write stage instead of a free-form message on TeleportNativeWriteError,
derive TeleportUnsupportedProviderError from the provider, and remap schema
verification with catchTags. On Windows, replace native files by moving the
destination aside so a failed rename can restore the previous session.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Persist teleport ownership first so a failed history replace cannot leave an
unbound thread with overwritten messages.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep the teleported-out composer disable path and use main's
disconnected placeholder constant.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/ChatView.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new chat-header teleport button loses the themed toolbar control styling because the tooltip wrapper overwrites data-slot="button". See the inline comment for the one-attribute fix.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx
cursoragentand others added 5 commits August 19, 2026 03:27
TooltipTrigger replaces data-slot=button, so custom themes skipped this
icon. Opt in with data-toolbar-control the same way ProjectScriptsControl does.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Send-disabled only grayed the editor. Type-to-focus, mention drops, and
file drops could still queue hidden draft content. Reject those paths too.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
In-place native session import persisted directory binding, teleport
presence, unarchive, history, and title as separate durable mutations.
A later failure left T3 ownership and history out of sync, and a
concurrent turn could run against that intermediate state.
Commit ownership, history, and unarchive in one orchestration command.
Fence thread.turn.start with importing presence, recover leftover
importing state on startup, and keep title plus directory finalize
best-effort. Import stays atomic per session, not all-or-nothing for
the batch.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/importTransaction.ts Outdated
cursoragentand others added 3 commits August 19, 2026 05:55
tapError only saw typed failures, so a cancelled or defective pre-commit
import step could leave presence "importing" until process restart.
onError reverts for fail, die, and interrupt, and keeps revert running.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatView's teleport send-disabled import. Main moved the collapsed
sidebar titlebar inset into WorkspacePageHeader, so that import is gone.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatComposer's teleport lock on the prompt editor after main
moved send/stop into the footer. Native and importing presence still
disable the editor and show the send-disabled reason.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/chat/ChatComposer.tsx
Paste/drop could start before teleport lock, then attach compressed
images after compression finished. Stash restore and stash-current
could also write into a native/importing draft. Recheck send-disabled
after awaits and reject those stash mutations while teleport-locked.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@t3-code

t3-codeBot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

closing because this is explicitly marked Draft. Do not merge. and documents cross-fork teleport exploration rather than merge-ready work.

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

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@baanish@cursoragent
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Draft: two-way teleport with native CLI sessions - #7136

Closed
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23
Closed

Draft: two-way teleport with native CLI sessions#7136
baanish wants to merge 62 commits into
pingdotgg:mainfrom
baanish:cursor/teleport-opencode-1e23

Conversation

@baanish

@baanishbaanish commented Aug 15, 2026

Copy link
Copy Markdown

Draft. Do not merge. Exploration of two-way teleport. Opened as one PR because GitHub cannot stack cross-fork bases on this repo.

What Changed

T3 Code can list, import, and export native CLI sessions for Codex, and Claude.
Native files stay native. Import copies a CLI session onto a T3 thread. Export writes the thread back. Presence (t3 vs native) swaps Import/Export so both sides are not writers at once.
Codex export writes session_meta the CLI can resume. OpenCode imports text turns only, does not treat live opencode.db as a foreign lock, and does not match parent cwds into sibling codex / claude / grok folders. Stop settles Working when the turn is aborted, when there is no live session, or when interrupt fails.

UI

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

New UI

Draft hero Import a native CLI session link

Command palette Import sessions action

Native Claude and Codex sessions in the import picker

Hover

Teleport Out tooltip

Teleport In tooltip

Composer disabled after Teleport Out

Composer disabled when the thread is in the native CLI

Recordings

Codex
codex_teleport_roundtrip_nologo.mp4

Claude
claude_teleport_roundtrip_nologo.mp4

Why

Two-way teleport needs a shared engine, UI, and one adapter per CLI. This PR is that whole stack in one diff because stacked bases have to exist on pingdotgg/t3code.

UI Changes

Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Relates to #207, #5146, #5741, and #6590.

Note

Add two-way teleport between app threads and native CLI sessions

  • Introduces a full teleport system allowing threads to be exported to native CLI sessions (Claude, Codex, Grok, OpenCode) and imported back, with message history synchronization via new thread.history.replace and thread.teleport.set orchestration commands.
  • Adds TeleportService with list/import/export session RPCs (teleport.listSessions, teleport.importSessions, teleport.exportSession) wired into the WS layer with scope-based authorization.
  • Adds per-provider JSONL/directory format adapters with schema-version gating, file-lock detection, and atomic writes; a registry pattern enables runtime format registration.
  • Extends the command palette and chat UI with session browsing, import flows, a TeleportOutButton in the chat header, and composer/send disabling when a thread is teleported-out.
  • Adds DB migration 041 adding teleport_json to projection_threads with backfill from existing runtime telemetry.
  • Risk: thread.turn.start now fails with OrchestrationCommandInvariantError if the thread's teleport presence is native, blocking turn creation on teleported-out threads.
📊 Macroscope summarized 18ed3c0. 52 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

cursoragentand others added 20 commits August 15, 2026 08:54
Contracts, orchestration, and the teleport service land first. Native CLI
formats register later, so list/import/export stay empty until a provider
adapter is added.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
The UI can list, import, and export native sessions. Until a format
adapter is registered, the picker stays empty and export fails closed.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Codex jsonl adapter so T3 can list, import, and export
rollouts the CLI can resume.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the OpenCode adapter so T3 can list, import, and export text
turns from opencode.db or JSON storage without treating the live db as a
foreign lock.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Claude jsonl adapter so T3 can list, import, and export
sessions from the Claude projects folder.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Grok session-directory adapter so T3 can list, import, and
export native Grok Build chats.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Stop marked the turn interrupted but left the session running, so the thread stayed Working after abort hung or only emitted turn.aborted.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
A projected running OpenCode thread stayed Working after Stop if the
in-memory provider session was already gone. Interrupt no longer
recovers a session just to abort it, and Stop settles the projection
when there is nothing live to interrupt.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep live-session titles and personal directories out of the public diff.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@coderabbitai

coderabbitaiBot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a86460d-dc34-4a24-9c87-02e715f5dd10

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 15, 2026

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small consistency findings in the new teleport UI. Everything else in the changed web files (command palette views, composer disabled/placeholder handling, ChatView toast) follows the existing primitives and layout conventions.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/chat/DraftHeroHeadline.tsx Outdated
Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the new TeleportService (plus its contract errors). Four convention violations found; details inline.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/Services/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/orchestration/Layers/ProjectionPipeline.ts
Comment threadapps/server/src/teleport/formats/codex.ts
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/formats/opencode.ts Outdated
Comment threadapps/server/src/teleport/cwd.ts Outdated
Comment threadapps/server/src/teleport/formats/grok.ts Outdated
Comment threadapps/server/src/teleport/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/Layers/TeleportService.ts Outdated
Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadapps/server/src/orchestration/decider.ts Outdated
baanishand others added 3 commits August 15, 2026 15:30
The import CTA lacked cursor-pointer, and the header export control used
the text xs size instead of the square icon-xs used by neighboring actions.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Reject unsafe session ids on native reads/writes, fail closed when lock
checks cannot run, keep Codex whitespace, preserve in-place provider
instances, and clear stale history/approvals when replacing a thread.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new header control's disabled state suppresses the tooltip that explains why it is unavailable.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx Outdated
Effect 4 does not provide zipRight on Effect. Complete the sendTurn abort latch from a generator finalizer instead.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/provider/Layers/OpenCodeAdapter.ts Outdated
cursoragentand others added 4 commits August 17, 2026 20:35
Claim the in-flight abort through an atomic gate so a second interrupt waits instead of emitting another turn.aborted or calling session.abort again.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export writes the native session cwd from the thread worktree, which lives
outside the project root. Listing and import treated only the workspace root
as in-project, so Teleport Out was a one-way door.
Discover extra cwds from the project's thread worktrees, match subdirectory
sessions, and stop accepting ancestor cwds such as / or $HOME.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export set presence to native with a teleport-pending path before writing
the CLI file, then only reverted on write tapError. Interruptions, defects,
and later directory or teleport.set failures left the thread stuck: the UI
only offered Import, which rejected the fake path.
Wrap the pending presence in acquireUseRelease so any unsuccessful exit
reverts to T3, or persists the real native path if the file was written.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Release-path persist of a written native session can still raise a
filesystem error. Catch that so a failed bind cannot mask the export
failure or skip reverting pending presence.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two error-modeling convention issues in the new teleport code: message stored as data when it is a fixed template over existing attributes, and a helper whose only behavior is constructing that error.

Posted via Macroscope — Effect Service Conventions

Comment threadapps/server/src/teleport/fileLock.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Lock, schema, identity, and file-locked errors now derive `message` from
their fields, so the lockProbeError helper can go. A failed new-thread
import deletes the orphan thread instead of leaving it unbound.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/nativeWrite.ts Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new teleport service against the Effect service conventions. Service shape (Context.Service with inline interface, exported make/layer), dependency acquisition via yield*, and Effect.catchTags usage all look right now. Three remaining error-modelling issues below.

Posted via Macroscope — Effect Service Conventions

Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadpackages/contracts/src/teleport.ts Outdated
Comment threadapps/server/src/teleport/formats/codex.ts Outdated
cursoragentand others added 3 commits August 17, 2026 22:33
Store a write stage instead of a free-form message on TeleportNativeWriteError,
derive TeleportUnsupportedProviderError from the provider, and remap schema
verification with catchTags. On Windows, replace native files by moving the
destination aside so a failed rename can restore the previous session.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Persist teleport ownership first so a failed history replace cannot leave an
unbound thread with overwritten messages.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep the teleported-out composer disable path and use main's
disconnected placeholder constant.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/ChatView.tsx Outdated

@macroscopeappmacroscopeappBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new chat-header teleport button loses the themed toolbar control styling because the tooltip wrapper overwrites data-slot="button". See the inline comment for the one-attribute fix.

Posted via Macroscope — UI Consistency

Comment threadapps/web/src/components/teleport/TeleportOutButton.tsx
cursoragentand others added 5 commits August 19, 2026 03:27
TooltipTrigger replaces data-slot=button, so custom themes skipped this
icon. Opt in with data-toolbar-control the same way ProjectScriptsControl does.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Send-disabled only grayed the editor. Type-to-focus, mention drops, and
file drops could still queue hidden draft content. Reject those paths too.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
In-place native session import persisted directory binding, teleport
presence, unarchive, history, and title as separate durable mutations.
A later failure left T3 ownership and history out of sync, and a
concurrent turn could run against that intermediate state.
Commit ownership, history, and unarchive in one orchestration command.
Fence thread.turn.start with importing presence, recover leftover
importing state on startup, and keep title plus directory finalize
best-effort. Import stays atomic per session, not all-or-nothing for
the batch.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/server/src/teleport/importTransaction.ts Outdated
cursoragentand others added 3 commits August 19, 2026 05:55
tapError only saw typed failures, so a cancelled or defective pre-commit
import step could leave presence "importing" until process restart.
onError reverts for fail, die, and interrupt, and keeps revert running.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatView's teleport send-disabled import. Main moved the collapsed
sidebar titlebar inset into WorkspacePageHeader, so that import is gone.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatComposer's teleport lock on the prompt editor after main
moved send/stop into the footer. Native and importing presence still
disable the editor and show the send-disabled reason.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Comment threadapps/web/src/components/chat/ChatComposer.tsx
Paste/drop could start before teleport lock, then attach compressed
images after compression finished. Stash restore and stash-current
could also write into a native/importing draft. Recheck send-disabled
after awaits and reject those stash mutations while teleport-locked.
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
@t3-code

t3-codeBot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

closing because this is explicitly marked Draft. Do not merge. and documents cross-fork teleport exploration rather than merge-ready work.

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

Labels

size:XXL1,000+ changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@baanish@cursoragent