wikis / T3 Code / wiki / concepts / t3-connect.md view as markdown report a mistake
Definition
T3 Connect is T3 Code's managed relay/tunnel solution for remote access — the mechanism behind
RelayConnectionTarget (see remote access). It uses a single Clerk application for
web, desktop, and mobile authentication, and answers the case where the host is behind NAT,
inbound ports are unavailable, or a mobile client needs to reach a desktop-hosted environment
without router or firewall changes.
How It Works
Authentication
The relay verifies two kinds of bearer credential: template JWTs generated from the t3-relay
Clerk JWT template with the shared t3-code-relay audience, and Clerk OAuth tokens issued to the
CLI. verifyRelayClientBearerToken tries the template/session path first and falls back to OAuth
verification, so the CLI's OAuth credential works without needing a JWT template.
T3 Connect is disabled in a fresh clone; enabling it for source builds requires a repository-root
.env/.env.local with T3CODE_CLERK_PUBLISHABLE_KEY, T3CODE_CLERK_JWT_TEMPLATE,
T3CODE_CLERK_CLI_OAUTH_CLIENT_ID, and T3CODE_RELAY_URL. These are public identifiers, not
secrets, and are statically injected into client builds; a built artifact needs no environment
file at runtime. When client-facing public values are absent, cloud UI is omitted, but the
t3 connect command group always registers — it reports the missing configuration rather than
silently disappearing from help.
The t3 connect command group
t3 connect # default: onboarding
t3 connect login
t3 connect link # --publish-only
t3 connect status # --json
t3 connect publish # --disable
t3 connect unlink
t3 connect logout
t3 serve is a separate top-level command, not a connect subcommand (see
remote access). t3 connect login opens the Clerk authorization flow and stores the
CLI credential without enabling cloud exposure. t3 connect link installs the pinned managed
cloudflared binary when needed, authorizes when needed, and records durable intent to expose the
environment — it works without a running T3 server; the next t3 serve/t3 start reconciles the
relay link and launches the managed tunnel. t3 connect unlink records disabled intent
immediately, stops a reachable running connector, and attempts to revoke the relay-side
environment record, but keeps the stored CLI authorization so link can re-enable exposure
without another browser flow. t3 connect logout does the same cleanup and also removes the
stored CLI authorization.
The headless CLI OAuth flow uses a separate Clerk OAuth application, configured as a public
client with PKCE (no client secret stored by the CLI), with allowed redirect URIs for both a
loopback listener (http://127.0.0.1:34338/callback) and a hosted out-of-band flow
(https://app.t3.codes/connect/callback, or $T3CODE_HOSTED_APP_URL/connect/callback when
T3CODE_HOSTED_APP_URL is customized). The relay is not involved in the OAuth handshake itself —
it only validates the resulting Clerk bearer token when the CLI manages an environment link. When
--headless is passed, or SSH is detected via SSH_CONNECTION/SSH_TTY, authorizeCli
automatically selects the out-of-band flow (prints a hosted authorization URL, accepts a pasted
code) instead of the loopback listener, so port forwarding is optional rather than required.
Relay traffic path
From the client's perspective, a relay-tunneled connection is still an ordinary WebSocket connection — the route is simply mediated. The relay Worker only brokers credentials and a managed endpoint; application traffic then flows over the provisioned Cloudflare tunnel hostname for the life of the connection, not through the relay Worker itself.
Client-side handling of relay connections
On the client, T3 Connect's relay path is one of the four connection target kinds resolved by the
shared connection runtime (ConnectionResolver, ConnectionDriver) described in
architecture. Two relay-specific behaviors are called out as required test coverage
for that runtime: relay token reuse and refresh, and progressive relay discovery. Credential
changes interrupt an in-flight connection establishment only for relay targets specifically,
because a new credential changes what is actually being established — unlike primary, bearer, or
SSH targets, where a credential change does not interrupt establishment the same way.
Background service interaction
The background service (background service) has an independent lifecycle from T3
Connect: Connect setup may offer to install the service during onboarding, but t3 connect logout
leaves the service running. Manage the service separately with t3 service status, install,
update, and uninstall.
Key Parameters
- Shared audience:
t3-code-relay(Clerk JWT template namet3-relay). - Config precedence: process/CI env vars > repository-root
.env.local> repository-root.env. - Loopback OAuth callback port:
34338. - Redirect URIs:
http://127.0.0.1:34338/callback(loopback) andhttps://app.t3.codes/connect/callback(hosted out-of-band). - Desktop custom URL schemes:
t3code-dev://app/(dev),t3code://app/(packaged). - Production macOS bundle ID:
com.t3tools.t3code. - Tunnel binary: a pinned, managed
cloudflaredbuild, installed byt3 connect link.
When To Use
Reach for T3 Connect when direct WebSocket access (remote access) isn't viable — the host is behind NAT, there's no way to open inbound ports, or you want a mobile client to reach a desktop-hosted environment without any router/firewall configuration. It's also the mechanism an operator sets up once for a self-hosted or team deployment (via the relay's own Clerk/Cloudflare configuration).
Risks & Pitfalls
CLERK_SECRET_KEYmust never appear in a client application environment, the desktop app, or be committed to the repository — onlyinfra/relayserver-side config and Alchemy secrets should hold it.- Enabling an empty Clerk allowlist blocks all new sign-ups — a documented footgun for closed deployments.
- Clerk allowlists control sign-up only; they do not revoke an existing user's active session — banning the user in Clerk is required to end active sessions and block future sign-in.
- Omitting the hosted out-of-band redirect URI breaks both headless and SSH authorization.
- The
prodAlchemy stage owns the retained PlanetScale database; deployprodbefore creating a personal developer stage, since non-production stages reference that same database.
Related Concepts
Sources
- raw/github_doc-docs-internals-t3-connect-md.md
- raw/github_doc-docs-internals-connection-runtime-md.md
