Tailge is a local-first Tailscale exposure manager with an opinionated, keyboard-first workspace heavily inspired by Vim: j/k navigation, gg/G jumps, and v/V selection, alongside arrow-key navigation. It discovers local TCP listeners and lets you deliberately share selected services through exact raw-TCP routes, explicit named HTTPS paths, or private/public HTTPS roots for listeners the operator confirms speak HTTP. This matters because a listening port alone does not tell Tailge whether a service speaks HTTP. Tailge never implicitly starts, stops, or restarts services; its TUI may send one explicitly confirmed SIGTERM to a revalidated local process.
Tailge is a local control and observation plane. Application traffic flows through Tailscale directly to the selected local service.
flowchart LR
Operator[Operator]
subgraph Local["Local machine"]
Service["Local TCP service"]
Discovery["Listener discovery<br/>lsof / ss"]
Tailge["tailge<br/>CLI / TUI"]
Tailscale["Tailscale client<br/>Serve / Funnel"]
Service -->|TCP listener| Discovery
Discovery -->|observed state| Tailge
Tailge -->|readiness and exact route changes| Tailscale
Tailscale -->|forwards traffic| Service
end
Operator --> Tailge
Tailscale <-->|identity and route coordination| ControlPlane["Tailscale control plane"]
Tailscale -->|Serve: private| Tailnet["Tailnet peers"]
Tailscale -->|Funnel: public| Internet(("Public internet"))
- Go 1.25.10+ and
maketo build from source - macOS or Linux for listener discovery
- An installed and logged-in Tailscale client for exposure features (optional for local scans)
- An interactive TTY for the workspace; CLI commands also work in scripts and CI
From a terminal, clone the repository, download its Go dependencies, and install the binary:
git clone https://github.com/arrokh/tailge.git
cd tailge
go mod download
make setup
export PATH="$HOME/.local/bin:$PATH"make setup installs tailge in $HOME/.local/bin; add the PATH line to your shell profile to keep it available in new terminals. To build without installing, run make build and use ./tailge from the repository root.
# Inspect local listeners, then open the interactive workspace
tailge scan
tailge
# Check Tailscale readiness and current routes
tailge doctor --tailscale
tailge exposure status
# If the selected listener actually speaks HTTP, choose a private HTTPS root on its same port
# Example: local HTTP on :3000 remains unchanged; Tailscale serves HTTPS on :3000
tailge exposure http serve 127.0.0.1:3000 --root --https-port 3000Open the provider-observed HTTPS URL shown by Tailge or tailge exposure status. For arbitrary non-web services, use the raw-TCP tailge exposure serve command shown below and connect with the service's own client.
tailge scan --json
tailge doctor --tailscale
tailge exposure status --json
tailge exposure serve 127.0.0.1:3000
tailge exposure funnel 127.0.0.1:3000 --confirm-public
tailge exposure disable 127.0.0.1:3000
# Explicit HTTPS path route to an existing local HTTP service
tailge exposure http serve '[::1]:4321' --path api
# Opt in if this Tailscale client rejects numeric IPv6 proxy destinations
tailge exposure http serve '[::1]:4321' --path api --localhost-backend
tailge exposure http funnel '[::1]:4321' --path preview --confirm-public
tailge exposure http disable '[::1]:4321' --path api --confirm-external
# Private HTTPS root on the same port as the local HTTP listener
# URL: https://<reported-MagicDNS>:4321/; backend remains http://[::1]:4321
tailge exposure http serve '[::1]:4321' --root --https-port 4321
# If that exact port currently has a raw-TCP Serve route, explicitly convert it
# Unknown/external ownership also requires --confirm-external
tailge exposure http serve '[::1]:4321' --root --https-port 4321 --replace-raw-tcp --confirm-external
tailge exposure http disable '[::1]:4321' --root --https-port 4321 --confirm-externalTCP listener discovery never implies HTTP: raw routes remain protocol-agnostic. In the TUI, s previews a private HTTPS Serve root and f previews a public HTTPS Funnel root for the selected HTTP-speaking service; both show the HTTP-backend assumption, exact route replacement, and HTTPS endpoint before confirmation. s uses the local listener's port. f preserves an existing Funnel HTTPS-capable port (for example, converts funnel:tcp=10000 to funnel:https=10000) or uses 443 for a new route, and always requires explicit public confirmation. Route changes use fresh identity checks and exact rollback. The CLI's raw exposure serve/funnel commands remain protocol-agnostic, and its separate exposure http commands are explicit HTTP intent. o uses an observed HTTPS URL when available; for an active Serve TCP route, it may open a UI-only HTTP preview using Tailscale-reported MagicDNS and the exact port. That convenience does not change route identity or prove the service speaks HTTP. See the usage guide and architecture guide for transport and route-identity context.
| Key | Action |
|---|---|
j / k, arrows |
Navigate the service list |
gg / G |
Jump to the first / last service |
/ |
Search the list |
w |
Toggle filter to services whose mode is not OFF (default: all services) |
Tab / Shift-Tab |
Switch between list and details |
s / f / d |
Open the action selector; choose private HTTPS Serve / public HTTPS Funnel / Disable, then confirm separately |
o |
Open an observed HTTPS URL, or preview a Serve TCP route via Tailscale MagicDNS |
O |
Open the selected local listener at http://localhost:<port>/ |
y |
Copy an observed HTTPS URL or the same Serve TCP preview |
v / V |
Toggle an item / enter Vim-style visual-line selection |
x |
Confirm process termination; identity is revalidated and only SIGTERM is sent |
e / S |
Cycle sort order |
z |
Zoom the focused pane; press again to restore the split |
? |
Open help |
The workspace keeps a high-contrast SEARCH ribbon below status and warnings, shows the active or accepted query, and preserves listener ports when compact rows abbreviate target addresses. See the interactive workspace guide for the full shortcut reference, process metrics, and modal behavior.
docs/usage.md— installation, CLI and TUI usage, configuration, safety, and development checksdocs/architecture.md— system context, domain-scoped TUI modules, internal control flow, and safety invariantsdocs/adr/0001-full-screen-tui.md— full-screen Bubble Tea decisionCONTEXT.md— domain language and interaction rules
make check
make quality FUZZTIME=1s
make cross-buildTailge is licensed under the MIT License.