hpctun

For HPC users

Use apps on compute nodes from your laptop

hpctun lets you open Jupyter, RStudio Server, Shiny and other web apps running in your cluster jobs in your own browser, copy files to and from the cluster, and run VS Code inside a Slurm job, without writing ssh commands. It uses the ssh already on your computer; tunnels and copies need nothing installed on the cluster.

Web apps on a compute nodeJupyter Lab, RStudio Server, Shiny, a Dask or Ray dashboard, MultiQC reports: open them in your browser.
Copying fileshpctun cp and rsync to the cluster's shared filesystem, with Tab completion of remote paths.
VS Code in a Slurm jobEditor, terminals and notebooks run on the job's node instead of the login node.
Campus-only pagesA browser window routed through the cluster, for sites that only answer on campus.

Why use it

Compared with what you do now

Everything hpctun does can be done with plain ssh, and hpctun runs plain ssh underneath. It saves you remembering the commands and cleaning up after them.

If you now…With hpctun
type ssh -L 8888:localhost:8888 -J you@login… you@node42 to reach Jupyter hpctun up jupyter. hpctun status lists what is open; hpctun down closes it. No stray ssh processes to hunt for.
approve a 2FA prompt for every terminal, copy and tunnel One login is shared by tunnels, ssh, scp and rsync. hpctun ssh-config key sets up key login, which at some sites (OSU included) skips 2FA.
copy with scp to the login node, typing remote paths from memory hpctun cp goes to the transfer node (faster link, same files), and Tab completes remote paths.
lose your tunnels when the laptop sleeps or the Wi-Fi changes hpctun up --all, or one click in the menu bar, puts them all back.
use Open OnDemand Keep using it for the apps it offers. hpctun covers what it doesn't: your own Shiny app or dashboard, any port, in your own browser.
use VS Code Remote-SSH to the login node hpctun code runs VS Code's server inside your own Slurm job, so your terminals and language servers use the job's CPUs, not the shared login node.
turn on the VPN to reach a campus-only website hpctun browse opens one browser window that goes through the cluster; the rest of your traffic is unaffected.
edit ~/.ssh/config by hand, or copy someone else's hpctun init asks a few questions and shows the changes before writing them.

The network

How a cluster is usually laid out

Compute nodes sit on a private network. From the internet you can reach the machines on its edge: the login node and the transfer node.

The HPC network Your laptop can reach the login node and the transfer node over the internet. Compute nodes sit behind them on a private network; your laptop has no route to them. HPC cluster · private network Your laptop home, office, café Internet scp, rsync ✓ fast link no route Login node log in, submit jobs Transfer node move data, fast node41 RStudio Server :8787 node42 Jupyter Lab :8888 node43 Shiny app :3838 Compute nodes: no direct internet
The teal and blue lines reach the login and transfer nodes from the internet. The red dashed line has no route: your laptop can't reach the compute nodes (purple) directly.
Login nodeReachable from the internet with ssh, and it can reach every compute node, so tunnels go through it.
Transfer nodeAlso reachable from the internet, with a faster external connection. Copies go here.
Compute nodesWhere jobs and their web apps run. Reachable only from inside the cluster.

Port forwarding

What a tunnel does

A tunnel (an ssh port forward) makes a port on a compute node appear as a port on your laptop. The traffic travels inside the ssh connection to the login node, which passes it on.

How a tunnel carries a request The browser asks localhost port 8888. ssh on the laptop listens there and sends the request through its encrypted connection to the login node, which passes it to node42 port 8888, where Jupyter answers. Your laptop HPC cluster encrypted ssh private Browser http://localhost:8888 ssh, run by hpctun listening on localhost:8888 Login node passes it on node42 Jupyter on :8888

hpctun opens the forward, records it, shows it in hpctun status, reopens it after a sleep or network change, and closes it.

$ hpctun up 8888 --host node42 --loopback
$ open http://localhost:8888        # Jupyter, from your laptop
$ hpctun down 8888

One login

One shared connection

hpctun sets ssh up so everything shares one connection to the login node. Tunnels, ssh sessions, scp and rsync all ride the connection that is already open, so you type your password and approve 2FA once.

Separate connections: a login each

Three separate connections, each asking for 2FA Jupyter tunnel ssh node42 scp results 2FA 2FA 2FA Loginnode

Shared connection: one login

Three uses sharing one connection, one 2FA prompt Jupyter tunnel ssh node42 scp results 2FA once Loginnode

The shared connection stays open in the background. If it drops (the laptop slept, the Wi-Fi changed, the VPN reconnected), hpctun up --all reopens it and puts back every tunnel. With an ssh key, which hpctun ssh-config key sets up for you, there is no password to type, and some sites (OSU among them) skip the 2FA prompt too. While it is open, any program running as you on your computer can use it without a password or 2FA; hpctun logout closes it.

Routes

Apps that listen on localhost only

Many apps, Jupyter included, accept connections only from the machine they run on (127.0.0.1, “localhost”). The login node can't connect to those, so the tunnel has to continue to the node itself. In practice: if a tunnel to Jupyter opens but the page doesn't load, add --loopback. For an app you start yourself, start it on 127.0.0.1 and use --loopback: then the rest of the cluster cannot reach it.

Direct: the login node connects to the app

Direct route The login node reaches an app listening on all addresses, but not one listening on localhost only. Laptop Loginnode node42 Dashboardall addresses localhost only Jupyter127.0.0.1 ✓
Cheapest: no extra ssh process. But the app listens on all addresses, so everyone on the cluster can reach it: only for apps that ask for a password or token.

Through: ssh continues on to the node itself

Jump route A second ssh connection passes through the login node to node42 and connects to Jupyter from inside, on localhost. Laptop Login node node42 Dashboardall addresses localhost only Jupyter127.0.0.1 ssh to node42
For localhost-only apps, and the safer choice for anything you start on a compute node. hpctun runs a separate ssh process for this tunnel.
Which one do I need? For an app you start yourself, start it on 127.0.0.1 and add --loopback (or route = "jump" in the config). To check an existing app, run ssh node42 ss -ltn | grep 8888: 127.0.0.1:8888 means localhost only, so add --loopback; 0.0.0.0:8888 or *:8888 means the direct route works, but also that other cluster users can reach the app, so make sure it asks for a password or token.

Files

Copying files

Copies go to the transfer node. It has the faster external link and sees the cluster's shared, networked filesystem: the same home, lab and project folders as every compute node.

Two ways to copy files Copies go from the laptop to the transfer node, which sees the shared networked storage mounted on every node. As a bonus, a copy can hop through the transfer node to node7, whose local /scratch only node7 sees, if ssh to node7 is allowed. HPC cluster Shared filesystem /home /lab /project mounted on every node hpctun cp node7 /scratch only node7 sees this Your laptop results/ Transfer node files fast external link bonus: hop to node7needs ssh to the node

Copy to and from the shared filesystem

Your home, lab and project folders, the same ones every compute node sees. hpctun cp, hpctun rsync and hpctun sftp take the usual scp, rsync and sftp arguments, with the ssh setup already done.

$ hpctun cp results.tsv files:/lab/project/run1/
$ hpctun rsync -av files:/lab/project/run1/plots/ plots/
$ hpctun sftp files

Tab completes paths on the cluster

Press Tab after a remote path and the shell lists what is there, just as it does for files on your laptop. The listing uses the connection that is already open, so it never asks you to log in. Turn it on once with hpctun completion zsh --help (or bash, fish).

$ hpctun cp files:/lab/project/<Tab>
run1/   run2/   samples.tsv   README.md
$ hpctun cp files:/lab/project/run1/<Tab>
counts.tsv   multiqc_report.html   plots/

Bonus: a node's own disk. For files on one node's local /scratch, hpctun cp node7:/scratch/you/run.log . hops through the transfer node for you (it runs scp -J files … and prints it). This needs ssh access to that node, which some clusters allow only while you have a job there.

Browser

Opening a tunnel's page

hpctun browse opens the tunnel if it is not up yet, then opens the page. A port forward opens in your usual browser. A SOCKS proxy tunnel opens a separate browser window that sends its web traffic through the cluster (it still reaches localhost on your laptop directly), which is useful for sites that only answer on campus. Other browser windows are not affected.

hpctun browse Your usual browser opens localhost:8888, carried to Jupyter on node42. A separate proxied window sends its web traffic through the login node to campus-only sites. Every other window goes straight to the internet. Your laptop Cluster & campus network Your usual browser localhost:8888 → Jupyter Separate proxied window web traffic via SOCKS :1080 Every other window unchanged: straight to the internet Login node ssh node42 Jupyter :8888 Campus-only site internal chat, licenses… Internet
The proxied window is its own browser profile (Chrome, Edge, Brave or Chromium). hpctun never changes your system proxy settings or your other windows.
$ hpctun browse jupyter                  # http://localhost:8888 in your usual browser
$ hpctun browse proxy                    # a proxied window on the tunnel's saved page
$ hpctun browse proxy https://intranet.example.edu

VS Code

VS Code in a Slurm job

hpctun code gets you a Slurm job, starts VS Code's tunnel inside it, and opens VS Code on your laptop connected to that job. Terminals, language servers and notebook kernels run on the compute node, not on the shared login node.

hpctun code 1: hpctun logs in to the login node and submits a Slurm job. 2: Slurm starts the job on a compute node. 3: the job starts VS Code's tunnel, which connects out to Microsoft's tunnel relay. 4: VS Code on your laptop connects to the relay and reaches the job. HPC cluster VS Code tunnel relay Microsoft, on the internet VS Code on your laptop Login node sbatch Compute node your Slurm job · 4 CPUs · 24 h VS Code server terminals, extensions, notebook kernels 1 2 Slurm starts it 3 connects out 4
Nothing connects into the compute node: the job reaches out to the relay (through the site's web proxy), and VS Code meets it there.
$ hpctun code project                  # ~/project on the cluster, in a job of your own
$ hpctun code -- --gres=gpu:1          # anything after -- goes to sbatch
$ hpctun code --status                 # the job, its node and time left
$ hpctun code --stop

The job keeps running when you close VS Code, and running hpctun code again reconnects to it. Your files are on the cluster the whole time.

The first time on each computer, hpctun shows the VS Code Server License Terms and asks you to accept them. Your editor reaches the job through Microsoft's dev tunnels service, which your files, terminals and edits pass through; check your institution's rules before working with restricted data this way.

Optional

Menu-bar app

hpctun-tray puts your tunnels in the macOS menu bar, the Linux system tray or the Windows notification area. Log in, open or close each tunnel, open a tunnel's page in the browser, and see your VS Code job, without a terminal. A password or 2FA prompt appears in a small window, and hpctun never stores what you type.

The icon tells you the state at a glance:

  • every tunnel is up
  • logged in, some tunnels down
  • not logged in
  • something is wrong
The hpctun menu: shell.hpc and files connected, Log out, the chat and socks SOCKS proxies ticked as open, the llm tunnel to ai-gateway.hpc.oregonstate.edu:8090, Open all, Close all, Open chat in browser, Open llm in browser, Code job: none, Open config, Start at login, Quit.
Screenshot of the menu-bar menu
(add site/img/tray-menu.png)
The hpctun menu on macOS.

Commands

Plain ssh and hpctun side by side

Plain ssh

One command per forward; closing one means finding its process.

ssh -N -f -L 8888:localhost:8888 \
    -J you@login.cluster.edu you@node42
ssh -N -f -L 8787:node41:8787 you@login.cluster.edu
# later: which of these is still running?
ps aux | grep 'ssh -N'
lsof -i :8888
kill 48213

With hpctun

Tunnels are named once in a config file and used by name.

hpctun up --all      # safe to re-run
hpctun status
hpctun browse jupyter
hpctun down --all

hpctun status answers “what's open, where does it go, is anyone using it?”:

gateway login: running (pid 86660, ssh-config)
transfer files: connected (pid 86811)

NAME      PORT   ROUTE   TARGET        STATE   CONNS
jupyter   8888   jump    node42:8888   up      3
rstudio   8787   master  node41:8787   up      1
proxy     1080   socks   -             up      5
shiny     3838   master  node43:3838   down    -

Tunnels are named once in a short config file. hpctun add asks the questions for you, or you can open one ad hoc (hpctun up 8888 --host node42 --loopback) and save it if you want to keep it.

# ~/.config/hpctun/config.toml
gateway = "login"
default_host = "node42"

[tunnel.jupyter]
port = 8888
route = "jump"          # Jupyter listens on localhost only

[tunnel.rstudio]
port = 8787
host = "node41"

[tunnel.proxy]
socks = 1080
url = "https://intranet.example.edu"

Scope

What it touches

No stored passwords

Every connection is made by your own OpenSSH. Your keys, agent and ~/.ssh/config apply. hpctun never stores a password: its password window (menu-bar app, --askpass) only passes what you type on to ssh.

Little on the cluster

Tunnels and copies need no server, daemon or admin request: if you can ssh to the login node, hpctun works. hpctun code runs VS Code's server in your own Slurm job and keeps its sign-in in your cluster home.

Edits shown first

Changes to your ssh setup are shown as a diff and written only when you say yes, with a backup. Your own host entries are left alone.

Observed state

status looks at what is really listening every time it runs, so it can't drift from reality. Tunnels it didn't open are shown and never touched.

Runs on macOS, Linux and Windows. On Windows, OpenSSH has no shared connection, so each tunnel is its own ssh and signs in with a key from the ssh agent; hpctun login checks that it can.

Tunnel ports on your computer have no password of their own: any program on it can use them, so keep your apps' own logins on. Releases are signed, and hpctun self-update checks the signature before installing anything. The README's “Security notes” say more.

hpctun is written with AI coding agents (Claude Code, with reviews by Codex) under its maintainer's direction, and had a security review before its first public release. See “How hpctun is made” in the README.

At Oregon State

hpctun on the OSU HPC cluster

The release comes with osu.toml, which fills in OSU's hosts for you. The setup wizard asks for your ONID username and little else.

Login node
shell.hpc.oregonstate.edu
alias shell: logins, jobs, tunnels
Transfer node
files.hpc.oregonstate.edu
alias files: copies, node-local /scratch
Compute nodes
Slurm nodes such as chrom1
reached through the login node
  1. Get the release

    # Apple silicon Mac; see the releases page for other systems
    $ v=$(curl -fsSL https://github.com/davised/hpctun/releases/latest/download/VERSION)
    $ curl -fLO "https://github.com/davised/hpctun/releases/download/$v/hpctun-$v-darwin-arm64.tar.gz"
    $ tar xzf hpctun-$v-darwin-arm64.tar.gz
    $ cd hpctun-$v-darwin-arm64 && mkdir -p ~/.local/bin && mv hpctun ~/.local/bin/
    $ export PATH="$HOME/.local/bin:$PATH"

    On a Mac, hpctun-tray-<version>-darwin-universal.zip is the menu-bar app with hpctun inside. Use curl, not a browser: macOS blocks unsigned programs that a browser downloaded. To keep ~/.local/bin on your PATH in new terminals, add that export PATH line to ~/.zshrc.

  2. Set up with OSU's defaults

    $ hpctun init --from osu.toml
    $ hpctun ssh-config key        # optional: log in with a key

    Without a key, every new connection asks for your password and a Duo push. With a key, OSU skips Duo. hpctun code needs the key.

    With the menu-bar app, run hpctun init --from /Applications/hpctun-tray.app/Contents/osu.toml: the preset ships inside the app bundle.

  3. Use it

    $ hpctun up 8888 --host chrom1 --loopback   # Jupyter on chrom1
    $ hpctun cp chrom1:/scratch/ONID/out.tsv .  # a node's /scratch, via files
    $ hpctun code myproject                     # VS Code in a Slurm job
OSU LLM gateway from off campus, no VPN

osu.toml carries two optional tunnels (the wizard asks; or hpctun add later):

hpctun up llm       # API at http://127.0.0.1:8090/v1
hpctun browse chat  # the chat site, in a proxied window
VS Code on a compute node

The first time, VS Code asks you to sign in with Microsoft: use your ONID (you@oregonstate.edu). The first job on each node shows a one-time device code. hpctun vscode-settings adds recommended settings for the cluster.

Staying current: hpctun self-update downloads the latest release from GitHub, checks that it is signed with hpctun's release key and matches its checksums, and replaces hpctun (and the menu-bar app).

Anywhere else

Get started

  1. Install

    Download the archive for your computer from the releases page and put hpctun on your PATH, or build it with Go 1.26.9+: go build -o ~/.local/bin/hpctun ./cmd/hpctun. You need an OpenSSH client and lsof, both standard on macOS and Linux.

  2. Tell it about your cluster

    $ hpctun init      # login node, transfer node, node name patterns
  3. Open, check, close

    $ hpctun add             # name a tunnel
    $ hpctun up --all
    $ hpctun status
    $ hpctun down --all
hpctun up / downOpen or close tunnels, named or ad hoc. up is safe to re-run and restores everything after sleep.
hpctun statusWhat is open, where it goes, and how many connections use it. --json for scripts.
hpctun browseOpen a tunnel's page, or a proxied browser window.
hpctun login / logoutOpen the shared connections up front, so prompts happen once.
hpctun cp / rsync / sftpThe real tools, hopping through the transfer node for paths on nodes.
hpctun codeVS Code inside a Slurm job.
hpctun ssh-configShow, check and update the ssh setup; key sets up key logins.