UPTERM(1)
okay so this is UPTERM(1) from the Upterm Manual, and today's main character is upterm-host β the page about hosting a terminal session. pull up a chair, bestie, we're getting into it π
β¨
πΈ NAME πΈ
upterm-host β host a terminal session. that's it, that's the job, and it ate π«Ά
π¦ SYNOPSIS π¦
upterm host [flags] [-- COMMAND [ARGS...]]
β¨ DESCRIPTION β¨
Host a terminal session: run COMMAND, or $SHELL if you didn't give one, and share it through a relay β so guests can join it from their own terminals with upterm join or plain ssh. two doors, same party π
upterm prints the session, with the commands guests join it with, and asks before starting it; --accept starts it without asking, plus --allow-sftp. The relay is --server, and upterm authenticates to it with the first of these it has:
- The SSH agent's keys, when an agent is running and holds any
- Otherwise, the private key files that load:
~/.ssh/id_{ed25519,ed25519_sk,ecdsa,ecdsa_sk,dsa,rsa} - Otherwise, a generated key
Supplying --private-key makes the named list the whole set instead; see its help.
Who can join: anyone with the session's connect string, unless --authorized-keys (an authorized_keys file) or --authorized-user names the keys a guest must have. so like, link-only party, or guest-list party, you pick π
What guests can do: type into the session, or only watch it with --read-only. A guest's plain ssh shares this terminal, or runs the program --login-command names instead. Anything more needs a grant:
- commands β
ssh SESSION CMD, VS Code,herdr --remote, run as you (--allow-exec,--no-exec) - files β
scpandsftp, with your access (--allow-sftp,--no-sftp) - forwarding β
ssh -L 8080:127.0.0.1:8080, to this machine's loopback addresses (--allow-forwarding=loopback,--no-forwarding)
--allow-X lets guests do X without asking, --no-X never lets them, and with neither, upterm asks in your terminal. --full-access allows all three, for the keys --authorized-user or --authorized-keys names. Forwards anywhere else are refused unless --allow-forwarding=any, which lets guests reach anything this machine can, without asking. --read-only also turns off commands, uploads and forwarding.
heads up: --allow-forwarding=any is the "keys to the whole house" option β anything this machine can reach, they can reach, no questions asked. know what you're doing, bestie π
The session runs in a process of its own, and this terminal is attached to it. NAME is the session's name, which upterm prints (--name chooses it).
Keys, at the start of a line (--escape-char changes the ~, or turns them off):
~.β detach: the session keeps running;upterm attach NAMEreattaches andupterm session stop NAMEends it~?β show the session's status and keys, in this terminal only; the program may need its own redraw afterwards~aβ review a guest's request, in the primary local terminal, and answer with the confirmation it shows as CODE:y CODE Enterallows it on its connection;a CODE Enterallows that guest every request of its kind (commands, files or forwards) until the session ends;n CODE Enterdenies it; Esc decides later, and the request still expires.~^Zβ suspend this terminal (Unix);fgresumes it~~β send a~;~~asends literal~a
Through an outersshconnection, ssh's own~escapes come first: type~~.,~~?,~~aand~~^Z, or connect withssh -e noneand type them plain. genuinely the number of tildes is not a vibe, it's a requirement π
With --escape-char none or without a capable primary local terminal, interactive approval is unavailable; requests without a grant are denied.
On Unix you can also suspend with ~^Z, run upterm session info NAME, and return with fg. A session that keeps producing output while this terminal is suspended may disconnect it (254 below); upterm attach NAME brings it back.
With --detach nothing is attached: the session starts in the background, and upterm prints how to reach it. It still asks before starting it, on this terminal; with no terminal to ask in, --detach needs --accept.
Exit status, aka the receipts π
- the command's own status when it exits
1whenuptermfails, or the session is stopped or ends by a signal (whatever the command returns while it is torn down)254when this terminal is disconnected130for Ctrl+C at a prompt,143for aSIGTERMthere0after declining at the prompt or detaching (~.)
A command's own 1 or 254 reads the same. With --detach: 0 once the session has started, 1 when it can't start; upterm session wait NAME reports the command's status.
π OPTIONS π
--accept[=false]β Start the session without asking, plus--allow-sftp. the "yes queen just go" flag β¨--allow-exec[=false]β Let guests run commands (ssh SESSION CMD, VS Code,herdr --remote) without approval. Each runs as you, and its stdin can carry further code. not scary at all, nope π--allow-forwarding=β Let guests forward ports (ssh -L) without approval:loopback, to this machine's literal127.0.0.0/8and::1addresses;any, to anything this machine can reach.--allow-sftp[=false]β Let guests transfer files (scp,sftp) without approval, with your access; downloads only with--read-only. π--authorized-keys=""β An authorized_keys file: only guests with a key it lists, or that--authorized-usernames, can join. the bouncer with the clipboard π--authorized-user=β Let a user join with the public keys a code-hosting service lists for them, fetched through--proxywhen it is set. Repeatable. Providers:github,gitlab,codeberg,srht(host optional),gitea,forgejo(host required). Examples:github:alice,github:bob@ghe.example.com,gitea:carol@git.example.com,https://git.example.com/dave--detach[=false]β Start the session in the background and exit once it is running. On a terminal,uptermasks before starting it, as it does without--detach; with no terminal to ask in, pass--accept. Attach a terminal later withupterm attach NAME; stop it withupterm session stop NAME. ghost host mode π»--escape-char="~"β The character that startsupterm's keys at the start of a line, ornoneto turn them off.-f,--force-command=""β Run this host-chosen command for guest shell and exec requests, with a private PTY when requested and pipes otherwise.--no-execand--read-onlystill deny explicit exec. Mutually exclusive with--login-command.--full-access[=false]β Let authorized guests do what an SSH login to your account can, without asking: run commands (ssh SESSION CMD, VS Code,herdr --remote), transfer files (scp,sftp), and forward ports to this machine's loopback addresses (ssh -L 8080:127.0.0.1:8080). Requires--authorized-useror--authorized-keys. the whole entire vibe, unlocked π-h,--help[=false]β help for host--hide-client-ip[=false]β Hide guests' IP addresses fromupterm's output, and from forced commands'SSH_CONNECTIONandSSH_CLIENT. When it isn't set (by flag, environment or config file), they are hidden in CI only;--hide-client-ip=falseshows them there too.--join-timeout=0sβ End the session if no guest has joined within this long (e.g.10m).0waits forever. A guest who joins disarms it permanently, so a guest who joins and then leaves does not re-arm it. Change it later withupterm session set NAME --join-timeout. the "if nobody shows up in 10 minutes i'm leaving" rule π--known-hosts="~/.ssh/known_hosts"β Known keys of relays. An unknown relay key is shown for confirmation, assshdoes.--login-command=""β Run this host-chosen command for guest shell requests, without exec approval. Mutually exclusive with--force-command; explicit guest exec still needs approval.--name=""β Name the session, forupterm attachand the session commands to find it by. Defaults to the command's name and four hex digits, e.g.bash-1f3a.--no-exec[=false]β Deny explicit guest exec requests, including forced exec. Host-chosen login and forced shell commands still run.--no-forwarding[=false]β Deny guest TCP forwarding, including pregranted and approved destinations.--no-sftp[=false]β Turn off file transfer (sftpandscp) for guests.-o,--output=""β With--detach, print the started session as JSON: a superset of the fieldsupterm session info NAME -o jsonreports at launch, withsshCommandandjoinCommandpresent even when its status says guests can't join.-i,--private-key=[~/.ssh/id_{ed25519,ed25519_sk,ecdsa,ecdsa_sk,dsa,rsa}]β Identity files to authenticate to the relay with. Supplying this makes the list the whole set, like OpenSSH'sIdentitiesOnly: each file must load, a public key (.pub) file selects that key in the SSH agent, and other agent keys are not offered. By default it offers the agent's keys alone when the agent holds any, and otherwise the listed files that load, or a generated key when none do.--proxy=""β HTTP proxy to reach the relay through (e.g.http://proxy.example.com:3128). Works withssh,wsandwssrelays. Without it,wsandwssuseHTTPS_PROXY/HTTP_PROXY, andsshgoes direct.--pty-size=""β Pin the session's terminal size as COLSx*ROWS* (e.g.132x43); resize requests are then ignored. Defaults to the attached terminal's size, or80x24when there is none.-r,--read-only[=false]β Let guests only watch: they can't type into the session, run commands or forward ports, and can only download files. audience mode, no stage invasion π--server="ssh://uptermd.upterm.dev:22"β Relay to host the session on:ssh://HOST[:PORT],ws://HOST[:PORT]orwss://HOST[:PORT]. Without a port,sshuses22,ws80andwss443.--skip-host-key-check[=false]β Accept an unknown relay key and record it without asking (similar to SSH'sStrictHostKeyChecking=accept-new). A changed key is still refused. π₯--term=""β SetTERMfor the hosted command. Defaults to the inheritedTERM, orxterm-256colorwhenTERMis unset ordumb.
π OPTIONS INHERITED FROM PARENT COMMANDS π
--debug[=false]β Enable debug logging (log file:/build/.upterm/upterm.log). A non-emptyDEBUGturns it on too. π
π EXAMPLE π
okay bestie this is the part you actually came for β real commands, real vibes, copy-paste away β¨
the classic: just host your shell π
# Host $SHELL; upterm prints how guests join it:
upterm host
no flags, no stress β it hosts your $SHELL and literally just tells you how your guests join. that's it. that's the whole thing. π«Ά
hosting a whole command instead π
# Host a command:
upterm host -- docker run --rm -ti ubuntu bash
see that --? everything after it is the command being hosted, not upterm's own flags. so here your guests get a throwaway ubuntu container. iconic. π³
locking it to alice's GitHub keys π
# Let only the keys alice has on GitHub join:
upterm host --authorized-user github:alice
or locking it to a keys file ποΈ
# Let only the keys in an authorized_keys file join:
upterm host --authorized-keys ~/.ssh/guests_authorized_keys
same energy, but the guest list lives in a file you control.
no approvals, no knocking π
# Start without asking, and let guests transfer files without approval:
upterm host --accept
the tmux duo, and this one's a serve π
# Host 'tmux new -t pair-programming', and give each guest
# 'tmux attach -t pair-programming' instead of the session itself:
upterm host --force-command 'tmux attach -t pair-programming' -- tmux new -t pair-programming
read it twice bestie β you host the tmux new, but guests get handed the --force-command version instead. so nobody's out here creating their own sessions. chef's kiss. π
letting guests forward ports π
# Let guests forward TCP ports (ssh -L) to what this machine can reach:
upterm host --allow-forwarding=any
any means any β this one is powerful, so know what you're opening up, fr fr.
different relay, WebSocket style π
# Host on another relay, over a WebSocket:
upterm host --server wss://relay.example.com
background mode: the multitasker's dream π
# Start a session in the background and print how to reach it:
upterm host --detach --accept --authorized-user github:alice
you get your terminal back immediately, plus the info on how to reach the session. lowkey the best way to live.
same thing but make it JSON for your script π€
# The same, as JSON for a script:
upterm host --detach --accept --authorized-user github:alice -o json
machine-readable output, because your scripts don't wanna read pretty text, they want data. π
the big one: full-access door for alice's keys only πͺβ¨
# A door to this machine for alice's keys alone, in the background: plain
# ssh opens Herdr, and alice can also run commands, transfer files and
# forward to this machine's loopback ports:
upterm host --detach --name home --full-access --authorized-user github:alice --login-command herdr
okay this one is main character energy: backgrounded, named home, full access, locked to github:alice, and a plain ssh lands you in Herdr. she can also run commands, transfer files, and forward to this machine's loopback ports. that is a LOT of power β hand it out carefully, bestie. π
CI runner edition: nobody's home to click "accept" πββοΈπ¨
# On a CI runner, with nobody there to ask: a session alice can open in
# VS Code (Remote-SSH), which runs its server and forwards to its port:
upterm host --detach --accept --authorized-user github:alice --allow-exec --allow-forwarding=loopback
on CI there's literally no human to approve anything, so --accept is doing the heavy lifting, and --allow-exec + --allow-forwarding=loopback give VS Code's Remote-SSH exactly what it needs to spin up its server and reach its port. slay. π¦
heads up babe:--accept,--allow-exec,--full-accessand forwarding are all real permissions. start small, add only what the example actually needs, and don't leave doors open you forgot about. ππ
β SEE ALSO β
upterm(1)β yeah it's just the one, but she's the whole universe. go read the parent page if you haven't. π«Ά
πΈ HISTORY πΈ
2-Nov-2026 Auto generated by spf13/cobra
yep, cobra made this page automatically β no human hand-wrote these flags, the codegen did. respect the pipeline. π€β¨
and that's the page, bestie!! π this was Upterm 0.0.0+dev, dated Nov 2026 β go host something cute, lock it to someone you trust, and don't forget to close it after π
ππ
π¦ where this page comes from
- arch rolling: upterm 0.41.0-1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms