Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
U

upterm

> 编程语言
Open source

Instant Terminal Sharing

1.3K stars0 likes0 views
WebsiteGitHub

About

Instant Terminal Sharing

Upterm

Upterm is an open-source tool enabling developers to share terminal sessions securely over the web. It’s perfect for remote pair programming, accessing computers behind NATs/firewalls, remote debugging, and more.

This is a blog post to describe Upterm in depth.

:movie_camera: Quick Demo

:rocket: Getting Started

Installation

Mac

brew install --cask owenthereal/upterm/upterm

Migrating from Formula to Cask

If you previously installed upterm using the Homebrew formula (without --cask), you'll need to migrate to the Cask version:

# Uninstall the old formula version
brew uninstall upterm

# Install the new Cask version
brew install --cask owenthereal/upterm/upterm

Note: Running brew upgrade with the old formula installed will fail with an error. Follow the migration steps above to resolve this.

Windows

scoop bucket add upterm https://github.com/owenthereal/scoop-upterm
scoop install upterm

Standalone

upterm can be easily installed as an executable. Download the latest compiled binaries and put it in your executable path.

Go

go install github.com/owenthereal/upterm/cmd/upterm@latest

From source

git clone https://github.com/owenthereal/upterm.git
cd upterm
go install ./cmd/upterm/...

:wrench: Basic Usage

  1. Host starts a terminal session:

    upterm host
    
  2. Host retrieves and shares the SSH connection string:

    upterm session current
    
  3. Client connects using the shared string:

    ssh [email protected]
    

:blue_book: Quick Reference

Dive into more commands and advanced usage in the documentation. Below are some notable highlights:

Command Execution

Host a session with any desired command:

upterm host -- docker run --rm -ti ubuntu bash

Access Control

Host a session with specified client public key(s) authorized to connect:

upterm host --authorized-keys PATH_TO_PUBLIC_KEY

Or authorize users by provider:username, fetching their public keys from a code-hosting service:

upterm host --authorized-user github:username
upterm host --authorized-user gitlab:username
upterm host --authorized-user srht:username
upterm host --authorized-user codeberg:username

Self-hosted instances are supported by naming the host. gitea and forgejo always require one, since there is no default instance. Keys are always fetched over HTTPS:

upterm host --authorized-user github:[email protected]
upterm host --authorized-user gitea:[email protected]
upterm host --authorized-user forgejo:[email protected]
upterm host --authorized-user https://git.example.com/username

For a GitHub Enterprise Server instance that requires a login, authenticate first with gh auth login --hostname ghe.example.com; only credentials stored for that host are used.

Force command

Host a session initiating tmux new -t pair-programming, while ensuring clients join with tmux attach -t pair-programming. This mirrors functionality provided by tmate:

upterm host --force-command 'tmux attach -t pair-programming' -- tmux new -t pair-programming

Running Without a Terminal

Host a session from a script or CI step with nothing attached to its terminal. --accept skips the confirmation prompt, --name gives the session a local name you choose, and --pty-size pins the terminal geometry so the command renders the same for every client:

upterm host --accept --name build-shell --pty-size 132x43 -- bash &

In a fresh environment known_hosts does not yet hold the relay's key, and the host-key confirmation cannot be answered without a terminal. Add it first, or pass --skip-host-key-check to accept an unknown key on the first connection:

mkdir -p ~/.ssh && ssh-keyscan uptermd.upterm.dev >> ~/.ssh/known_hosts

Look the session up by name while it runs and after it ends. The record outlives the process and carries how the command finished:

upterm session info build-shell -o json

The status field is starting, ready, disconnected or ending while the session still holds its name, and ended once nobody does; reason is exited (with exitCode), signaled, stopped, startup_failed, startup_abandoned (declined at the confirmation prompt) or unknown. The hosted command sees its own name in UPTERM_SESSION_NAME. upterm session list shows every live session, including one started under a different XDG_RUNTIME_DIR — a cron job or a system service — reached through the admin socket path its record carries. Records outlive the sessions that wrote them for seven days, and the listing prunes the ones past that.

File Transfer (SFTP/SCP)

Clients can transfer files using standard scp or sftp commands. The connection details are shown when running upterm session current:

# Download a file from host
scp -P PORT USER@HOST:/path/to/file.txt ./local/

# Upload a file to host
scp -P PORT ./local/file.txt USER@HOST:/path/to/destination/

Security model:

  • File transfers have the same access as the terminal session (clients can already access any file via the shell)
  • Without --accept, each file operation prompts the host for approval via a dialog
  • Use --read-only to restrict SFTP to downloads only (no uploads, deletes, or modifications)
  • Use --no-sftp to disable file transfers entirely

Local TCP Forwarding

Clients can use standard SSH local forwarding through a hosted session when the host opts in:

upterm host --allow-local-tcp-forwarding
ssh -L 5555:127.0.0.1:8080 [email protected]

WebSocket Connection

In scenarios where your host restricts ssh transport, establish a connection to uptermd.upterm.dev (or your self-hosted server) via WebSocket:

upterm host --server wss://uptermd.upterm.dev -- bash

Clients can connect to the host session via WebSocket as well:

ssh -o ProxyCommand='upterm proxy wss://[email protected]' [email protected]:443

HTTP Proxy

If the host can only reach the internet through an HTTP proxy, pass it with --proxy. It works with ssh://, ws:// and wss:// servers, so the default server works too as long as the proxy allows CONNECT to port 22:

upterm host --proxy http://proxy.example.com:3128 -- bash

Without --proxy, ws:// and wss:// connections already use HTTPS_PROXY/HTTP_PROXY, but ssh:// connections go direct. Many corporate proxies only allow CONNECT to port 443; in that case, use --server wss://uptermd.upterm.dev as well.

Like other flags, --proxy can be set with UPTERM_PROXY or as proxy in the config file, which keeps proxy credentials off the command line. Clients behind a proxy pass the same flag to upterm proxy.

Debug GitHub Actions

upterm can be integrated with GitHub Actions to enable real-time SSH debugging, allowing you to interact directly with the runner system during workflow execution. This is achieved through action-upterm, which sets up an upterm session within your CI pipeline.

To get started, include action-upterm in your GitHub Actions workflow as follows:

name: CI
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Setup upterm session
      uses: owenthereal/action-upterm@v1

This setup allows you to SSH into the workflow runner whenever you need to troubleshoot or inspect the execution environment. Find the SSH connection string in the Checks tab of your Pull Request or in the workflow logs.

For comprehensive details on configuring and using this integration, visit the action-upterm GitHub repo.

:bulb: Tips

Resolving Tmux Session Display Issue

Issue: The command upterm session current does not display the current session when used within Tmux.

Cause: This occurs because upterm session current requires the UPTERM_ADMIN_SOCKET environment variable, which is set in the specified command. Tmux, however, does not carry over environment variables not on its default list to any Tmux session unless instructed to do so (Reference).

Solution: To rectify this, add the following line to your ~/.tmux.conf:

set-option -ga update-environment " UPTERM_ADMIN_SOCKET UPTERM_SESSION_NAME"

Identifying Upterm Session

Issue: It might be unclear whether your shell command is running in an upterm session, especially with common shell commands like bash or zsh.

Solution: Use upterm session current -o go-template to customize your shell prompt with session info. Add to your ~/.bashrc or ~/.zshrc:

# Show  emoji and connected client count when in upterm session
export PS1='$(upterm session current -o go-template=" {{.ClientCount}} " 2>/dev/null)'"$PS1"

Template variables available (Go templates use PascalCase field names):

  • {{.SessionID}} - Session ID
  • {{.ClientCount}} - Number of connected clients
  • {{.Host}} - Server host
  • {{.Command}} - Command being shared
  • {{.ForceCommand}} - Force command (if set)

Note: JSON output (-o json) uses camelCase keys (e.g., sessionId, clientCount).

Tip: The same template mechanism can be used for terminal titles or other integrations.

Alternative (simpler, without client count):

export PS1="$([[ ! -z "${UPTERM_ADMIN_SOCKET}"  ]] && echo -e '\xF0\x9F\x86\x99 ')$PS1"

:gear: How it works

Upterm starts an SSH server (a.k.a. sshd) in the host machine and sets up a reverse SSH tunnel to a Upterm server (a.k.a. uptermd). Clients connect to a terminal session over the public internet via uptermd using ssh or ssh over WebSocket.

:hammer_and_wrench: Deployment

Kubernetes

You can deploy uptermd to a Kubernetes cluster. Install it with helm:

helm repo add upterm https://upterm.dev
helm repo update
helm install uptermd upterm/uptermd

Fly.io

The cheapest way to deploy a worry-free Upterm server (a.k.a. uptermd) is to use Fly.io. Fly offers a generous free tier and excellent global performance. The official uptermd community server is hosted on Fly.

  1. Install the Fly CLI and authenticate:

    curl -L https://fly.io/install.sh | sh
    flyctl auth login
    
  2. Copy fly.example.toml to fly.toml and set your app name. It pulls the published ghcr.io/owenthereal/upterm/uptermd image, so no local build is needed.

  3. Deploy your uptermd server:

flyctl deploy

Your uptermd server will be available at your-app-name.fly.dev. You can connect using either SSH or WebSocket protocols.

Upgrading from an earlier release: uptermd-fly no longer exists. Replace your [build] dockerfile/build-target and [experimental] entrypoint settings with the [build] image and [env] blocks shown in fly.example.toml.

Variable expansion in configuration

uptermd expands environment variable references in its text configuration values — flags, UPTERMD_* environment variables, and config files alike. This exists because the container image has no shell, so values that need a runtime value (a machine ID, a pod IP) cannot be interpolated before the process starts.

Expansion applies to text value

GitHub Issues· 0 open

View all on GitHub

No open issues yet, or sync has not completed.

> Tags

Gogolangsharingsshterminal

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言