pattan पत्तन
ports & tunnels

pattan

पत्तन · “port, harbour”

The ports your dev servers listen on, Docker's and the tunnels that make them public, in the terminal: Enter opens one in the browser.

v0.1.1 latest2 releases1 decisions recordedMIT license

#pattan

The ports your dev servers listen on, Docker's published ports, and the tunnels that make them public, in the terminal. Enter opens localhost:port in the browser.

pattan (पत्तन) is Sanskrit for a harbour: where things come in and go out.

 Dev servers 5   All listening 13   Tunnels 1   Docker 4                    󰒋 pattan
╭─ Dev servers · 5 ───────────────────────────╮╭─ :5173 · vite ──────────────────────────╮
│ PORT     APP          PROJECT        STATUS  ││ OnAds · Dashboard                       │
│▌:5173 󰖟  vite         onads/apps/web ● 200 OK││                                         │
│ :4000    express      onads/apps/api ● 404   ││ URL        http://localhost:5173        │
│ :4321    astro        onads/apps/docs● 200 OK││ also on    http://192.168.1.12:5173     │
│          FROM DOCKER                         ││ process    node (pid 48211)             │
│ :5432    postgres     onads-postgres-1 ● tcp ││ tmux pane  main:2.1 · claude            │
╰──────────────────────────────────────────────╯╰─────────────────────────────────────────╯
 ports   j/k move   ↵ open in browser   y copy URL   g its tmux pane   t share   x stop

#What it shows

t on a port starts a tunnel to it with any tool you have installed (ngrok, cloudflared, tailscale funnel, localtunnel, bore). It runs on its own, keeps running after pattan quits, and logs to ~/.local/state/pattan/<tool>-<port>.log.

Everything refreshes every 2 seconds; the HTTP check every 10.

#Keys

KeyDoes
j / kMove to the next / previous port
Home / EndJump to the first / last
Tab / Shift+Tab, h / l, 1–4Switch tabs
aShow every listening port
/Search the list (port, app, project, URL); Esc clears it
rRescan now
?Show every key
q / EscQuit

On a port:

KeyDoes
EnterOpen localhost:port in the browser
y / YCopy the URL / the URL for your local network
gJump to the tmux pane the server runs in
tStart a tunnel to it (share it)
TShow its tunnel in the Tunnels tab
xStop it (SIGTERM; a container: docker stop), asks first
KForce stop it (SIGKILL), asks first

On a tunnel:

KeyDoes
EnterOpen the public URL
oOpen the local server it points at
yCopy the public URL
J / KMove through ngrok's last requests
RSend the selected request again (ngrok replay)
iOpen ngrok's inspector
xStop the tunnel, asks first

#Install

Needs Linux with ss (iproute2). Docker, tmux and the tunnel tools are optional: pattan uses what's there.

curl -fsSL https://raw.githubusercontent.com/Theyashsawarkar/pattan/main/install.sh | bash

downloads the release binary (or builds it with Go) into ~/.local/share/pattan and links ~/.local/bin/pattan. Or make install (PREFIX, DESTDIR), or go install github.com/Theyashsawarkar/pattan/cmd/pattan@latest.

#As a tmux plugin

set -g @plugin 'Theyashsawarkar/pattan'

prefix P opens pattan in a popup; P inside closes it. Without pattan on your PATH, the plugin builds it with Go the first time.

OptionDefault
@pattan-keyPthe key after the prefix; none binds nothing
@pattan-width / @pattan-height90% / 88%popup size
@pattan-title pattan popup title
@pattan-launcheryour own popup command instead of display-popup; it gets display-popup's arguments (-E -d DIR -T TITLE CMD)

To open it from a status-line click, open a popup that runs ~/.tmux/plugins/pattan/scripts/pattan-run --client '#{client_name}'.

#Command line

pattan                 the screen
pattan list            the dev servers' ports: "5173 vite onads-super/apps/web"
pattan list --all      every listening port
pattan tunnels         the tunnels: "ngrok https://… -> :5173"
pattan --version

#Colours

pattan follows varna's desktop theme (~/.local/state/varna/palette.json, a tools.pattan pick if the theme has one) and changes live with it; without varna it is Catppuccin Mocha. Icons need a Nerd Font; NO_NERD_FONT=1 turns them off.

#Privacy

pattan reads /proc and ss, asks your own ports over localhost, and talks to ngrok's and cloudflared's local APIs. Nothing leaves the machine unless you start a tunnel, which makes that one port public.

#License

MIT