Teitunnel

Guides

Links and integrations

Share and open things in Teitunnel from VS Code, JetBrains IDEs, Raycast, teitunnel:// links and scripts, through the app's local control connection, with every change approved by you.

The Teitunnel app can be driven from outside its window: by editor and launcher extensions, by teitunnel:// links, and by the teitunnel command, all through a local control connection to the running app. Nothing listens on the network, and nothing changes without your approval. You control all of it in AI & Integrations ▸ More.

Use it to share the dev server you're working on without leaving your editor, to keep an eye on shares from the status bar, or to wire Teitunnel into your own launcher and scripts.

AI & Integrations, More: Allow connections for the teitunnel command, editor extensions and launchers, programs that are always allowed, teitunnel links and the global shortcut

Editors and launchers

Each extension talks to the running app, so the app has to be running (turn on Open at login to have it there). When it isn't, the extension says so, offers Open Teitunnel, and connects as soon as it's up. Extensions introduce themselves as vscode, raycast and jetbrains: that's the name you see in the approval dialog and under Always allowed.

VS Code, Cursor and Windsurf

Install Teitunnel from the VS Code Marketplace, or from Open VSX in Cursor and Windsurf (or Extensions ▸ … ▸ Install from VSIX… with a .vsix file). VS Code 1.90 or later.

CommandDoes
Teitunnel: Share This Workspace's Dev ServerFinds the port in package.json scripts (Vite, Next.js, Astro, Angular, webpack, Storybook…) or from the framework (Django, Rails, Laravel, Flask, Jekyll, Hugo), checks something is listening, shares it and copies the address. With several running, it asks which one.
Teitunnel: Share Port…Share any port.
Share with TeitunnelOn a port in the Ports view. In a remote window it shares the forwarded local port.
Teitunnel: Run DoctorRun the app's Doctor and show what it found.
Teitunnel: Open TeitunnelBring the app to the front.

The Teitunnel view lists your shares and routes: Copy Address, Open in Browser, Stop Share, Open Inspector and Show in Teitunnel. A status bar item shows the number of live shares (teitunnel.statusBar).

Request notifications are off by default: turn on teitunnel.notifyRequests to hear about requests to inspected shares (at most one notification every few seconds; bursts are counted).

The extension runs on your computer even in remote windows (SSH, containers, WSL), where the app is.

JetBrains IDEs

Install Teitunnel from Settings ▸ Plugins ▸ Marketplace (IntelliJ IDEA, WebStorm, PyCharm, GoLand and the other IDEs, 2025.3 or later). It adds:

  • a Teitunnel tool window with your shares and routes: Copy Address, Open in Browser, Open Inspector, Stop Share, Show in Teitunnel, Refresh;
  • Tools ▸ Teitunnel: Share Port…, Run Doctor, Open Teitunnel;
  • a status bar widget.

Raycast

Install Teitunnel from the Raycast Store (macOS and Windows).

CommandDoes
Share PortShare a local port and copy the address.
List SharesCopy an address, open it, open its requests or stop it.
Open TeitunnelBring the app to the front.
Run DoctorCheck routes, shares and the connector for problems.

Without the extension, teitunnel:// links work from Raycast quicklinks and Alfred too.

The menu bar and a global shortcut

The menu bar (tray) icon shares a running dev server in one click, copies recent addresses, and pauses or stops every share; see The menu bar and tray.

AI & Integrations ▸ More ▸ Global shortcut shares your dev server from any app. It's off until you turn on Use a global shortcut. The default keys are ⌘⌥⇧S (Ctrl+Alt+Shift+S on Windows and Linux); choose Change and type another. When pressed:

  • Share the running dev server: shares the one dev server that's running and copies its address. With none or several, Quick Share opens so you can choose.
  • Open Quick Share: brings Teitunnel to the front, ready to share a port.

A dev server that's already shared just gets its address copied. A new share runs the exposure check first and opens the Quick Share sheet if it finds something. If another app already uses the keys, Teitunnel says so and keeps the previous shortcut. Global shortcuts don't work in Wayland sessions on Linux.

LinkDoes
teitunnel://share?port=3000Asks whether to share localhost:3000, then shares it in Quick Share.
teitunnel://openBrings Teitunnel to the front.
teitunnel://open?route=app.yourhost.comOpens the route in Routes.
teitunnel://open?share=<id>Opens the share in Quick Share.
teitunnel://inspect?share=<id>Opens the share's requests in the Inspector.

Use them from a launcher, a script (open teitunnel://share?port=3000 on macOS, start teitunnel://share?port=3000 on Windows, xdg-open on Linux) or a link on a page.

Any web page can open a link, so a link never shares anything on its own: Teitunnel asks first, every time, never remembers the answer, and shows only one question at a time. Links that only open a view don't ask. Teitunnel ignores links with anything it doesn't expect (another action, other or repeated parameters, a port that isn't a number, a hostname that isn't one). Turn links off with Open teitunnel:// links.

The installers register the link type on macOS, Windows and Linux (.deb, .rpm). An AppImage is registered only if your AppImage launcher does it.

The control connection

While the app runs, programs on your computer can ask it for its status, shares and routes, share a port, stop, pause or resume a share, open a view, run the Doctor, or change routes through a plan. The teitunnel command uses it for share, shares, routes, status and top (see Command line), and teitunnel mcp uses it to ask you to approve AI agents' changes (AI agents).

  • Only you: it's a Unix socket (macOS, Linux) or a named pipe (Windows) that only your user can open. Nothing listens on a network port.
  • A secret, too: each program presents a random token from a file only you can read.
  • You approve changes: sharing, stopping, pausing or resuming a share, or changing routes shows a dialog naming the program, with Allow, Always Allow and Don't Allow. Always Allow skips the question for that program from then on; it's listed under Always allowed in AI & Integrations ▸ More, where Remove undoes it. Replacing or deleting DNS records Teitunnel didn't create is asked about every time and never offers Always Allow.
  • Recorded: route changes show up in Activity with the program's name.
  • Limited: 20 requests a second per connection (bursts of 40), 12 changes a minute, and at most 32 connections.

Turn it off with Allow connections: open connections close, and teitunnel works on its own again.

For extension authors

The protocol is newline-delimited JSON-RPC 2.0: one JSON message per line, at most 1 MiB. A TypeScript client without dependencies (Node 20+), used by the VS Code and Raycast extensions, is in the repository at integrations/control-client.

Where: in Teitunnel's data folder (~/Library/Application Support/com.teispace.teitunnel on macOS, %APPDATA%\com.teispace.teitunnel on Windows, ~/.local/share/com.teispace.teitunnel on Linux), the control folder holds token and either sock (the Unix socket) or pipe (a file with the named pipe's name).

Hello first: within 5 seconds of connecting, send

{"jsonrpc":"2.0","id":1,"method":"hello","params":{"protocol":1,"token":"<contents of control/token>","client":{"name":"my-extension","version":"1.0.0"}}}

The answer names the app's version, whether your program is always allowed, and the methods and events available. A wrong token or protocol version closes the connection.

MethodParametersAnswer
statusnoneaccounts, this machine's tunnels, every share
shares.listnoneevery share (id, kind, url, origin, status, paused, requests…)
shares.startorigin ("3000", host:port or a URL), stopAfterSeconds, hostHeader ({"mode":"auto"}, {"mode":"off"} or {"mode":"set","value":"localhost:5173"})the share once it has its address
shares.stopid (a share's id, URL or hostname){}
shares.pause, shares.resumeid (a share on your domain or a route: hostname or URL), account{}
routes.listaccount (id or name; needed with several)the account, its tunnels and routes with status
routes.previewaccount, tunnel, change (e.g. {"type":"addRoute","route":{"hostname":"app.yourhost.com","origin":"3000"}})the plan: steps, warnings, fingerprint
routes.applythe same, plus fingerprint and confirmedhow it ended, and hostnames to check
open{"view":"route","hostname":"…"}, {"view":"share","id":"…"}, {"view":"inspector","share":"…"}, {"view":"doctor"} or {"view":"overview"}{}
doctor.runnonethe problems found
events.subscribeevents (default: all)then notifications {"method":"event","params":{"type":"sharesChanged"}}
localDomains.list, localDomains.reloadnonelocal domains and whether the app serves them; reload re-reads them

agent.register and agent.approve are used by teitunnel mcp for agents' approvals. Methods that change something (shares.start, .stop, .pause, .resume, routes.apply) ask the person unless the program is always allowed. The change types for routes.preview are the same as the server API's.

Events are sharesChanged, routesChanged and requestArrived; ignore types you don't know, since new ones will be added. requestArrived carries share (a share's id, or a route's hostname), method, path (secrets masked, as in the inspector), status and durationMs, once per finished request to an inspected share or route. Bursts are thinned to at most 10 events every 250 ms, so treat it as a live feed, not a complete log.

Error codeMeaning
-32001Unauthorized: hello missing, or a wrong token
-32002Too many requests; slow down
-32003The person said no
-32004The plan touches DNS records Teitunnel didn't create; pass confirmed: true
-32005Cloudflare changed since the preview; the new plan is in data
-32006The control connection is turned off in Settings
-32007Message too large
-32008Not found
-32009Timed out
-32010Unsupported protocol version; data.supported lists the ones the app speaks

Plus JSON-RPC's own codes (-32700 parse error, -32600, -32601 no such method, -32602 bad parameters, -32603 internal error).

Troubleshooting

Messages from the teitunnel command and from extensions that use the control connection:

  • "Teitunnel isn't running. Open it, or leave out --app to use this terminal." --app needs the app. Open it, or run the command without --app (it then works on its own).
  • "Not allowed in Teitunnel. Nothing changed." Someone chose Don't Allow in the dialog, or the program was refused.
  • "Teitunnel didn't get an answer in time (the question may still be open there)." The app asked you and nobody answered. Look for the dialog in Teitunnel's window.
  • "Cloudflare didn't hand out an address within 45 seconds. Check the internet connection and try again." A share the app started for a program got no address; see Quick Share.
  • "Something changed in Cloudflare since this plan was made. Review the new plan." The account changed between planning and applying. Plan the change again.
  • An extension says it can't reach Teitunnel. Check that the app is running and that AI & Integrations ▸ More ▸ Allow connections is on.
Edit on GitHub

Last updated on

On this page