Command line
Three programs have a command line today. All of them are built from source; there are no packages yet. A fourth, tealhand-power, is not built yet (it is planned for the next milestone).
tealhand-host
Section titled “tealhand-host”usage: tealhand-host <command> [options]
commands: run run Tealhand Host until Ctrl-C or SIGTERM connect show a code in this terminal and connect a phone (quit a running Tealhand Host first) unpair forget the connected phone, for a lost phone (refused while Tealhand Host is running) remote off keep remote control off from the next start; only this computer can switch it on again (refused while Tealhand Host is running) share list | add <path> | remove <id> | default <id>|none the folders phones may browse; add takes --name <name>, --read-only and --downloads (the folder phones offer first for downloads; default sets it later); refused while Tealhand Host is running downloads [cancel <id>] what phones downloaded here, and stop one (works while Tealhand Host runs) ssh on | off SSH access: connected phones may open a terminal here and add commands (with their fingerprint); off by default; `terminal` works as `ssh` (refused while Tealhand Host is running) commands list | add <key> <label> -- <line> | remove <key> commands a phone may run by name; add takes --cwd <folder>, --fingerprint (the phone must ask for the fingerprint) and --timeout <seconds> (default 1 day, at most 7 days); the line is everything after --; refused while Tealhand Host is running mcp for AI apps on this computer (Claude Desktop, LM Studio, ...): they launch this command to read your other devices (status, shared folders, files; never a change) mcp add | remove claude|lmstudio|cursor add Tealhand to that AI app's MCP config, or take it out; the app's other settings stay as they are, and the first change keeps a .tealhand-backup copy mcp on | off | setup | folder <dir> | limit <MB> let AI apps read your other devices (off by default); setup prints what to paste into the AI app; folder is where copies go (default ~/Downloads/Tealhand); limit is the largest copy (default 1024 MB); refused while Tealhand Host is running, except setup agent setup | remove claude connect Claude Code: every tool call it would ask you about goes to your phone (approve with your fingerprint; declined, no answer or Tealhand not running: denied); writes hooks into ~/.claude/settings.json with a .tealhand-backup copy; remove takes out only Tealhand's hooks agent hook PermissionRequest | Notification | Stop what Claude Code runs as a hook (set up by agent setup)
options: --data-dir <dir> Tealhand Host's files (default: this user's Tealhand folder) --relay <choice> disabled (default: this network only), public (n0's public relays), or the https address of your own Tealhand Relay. With `connect` the choice is saved and `run` uses it when no --relay is given. --relay-pin <sha256:...> your relay's certificate fingerprint, only for a self-signed certificate (get it with tealhand-relay fingerprint). Needs --relay with your relay's address; that relay must use this certificate. --port <n> the UDP port to listen on (default: the one used last time, else a free one). It is saved; if it is taken, a free one is used and saved instead. --power-helper <path> the tealhand-power program (default: next to this program) --name <name> this computer's name on the phone (default: its host name) --help, --version
exit codes: 0 done, 1 failed while running, 2 wrong command, option or setting
A sample systemd user unit is in packaging/tealhand-host.service (Restart=on-failure).| Command | What it does |
|---|---|
run |
Starts Tealhand Host and keeps it running until Ctrl-C or SIGTERM. It logs “Tealhand Host is running”, with “, relay pinned” when a certificate fingerprint is in use |
connect |
Starts a Host just for connecting a phone: prints the QR code in the terminal (or a note that it can’t be drawn), the code as text for “Paste the code” on the phone, then the phone’s name and the check code, and asks Connect? [y/N] (y, Y, yes or Yes connects). The QR works for 10 minutes. A --relay (with its --relay-pin, or none) given here is saved for run. The old name pair still works as an alias |
unpair |
Forgets the connected phone: removes the device list and the rules, keeps the computer’s key, and writes a journal line |
remote off |
Keeps remote control off from the next start, writes a journal line, and prints “Remote control is off from the next start. Only this computer can switch it on again.” Refused while a Host runs on the data folder. remote with anything but off is a command line error |
share list |
Prints one line per shared folder: its number, name and path, then tags in brackets: read-only, default for downloads, and missing: share it again for a folder that was deleted or replaced. With none shared it says “No folder is shared. Share one with tealhand-host share add |
share add <path> |
Shares a folder with connected phones. --name <name> (1 to 64 characters; default: the folder’s own name), --read-only (no changes from the phone), --downloads (makes it the default for downloads, which phones offer before the other folders; not with --read-only; only one folder can be the default). Prints “Shared it as folder N. Connected phones see it the next time they open Files.” |
share remove <id> |
Stops sharing the folder with that number, from share list. Deletes nothing. Prints “Stopped sharing folder N. Phones can no longer open it.” |
share default <id>, share default none |
Makes the folder with that number the default for downloads, or clears the default. Prints “Folder N is the default for downloads now.” or “No folder is the default for downloads now.” Refused while a Host runs on the data folder |
downloads (or downloads list) |
Lists what phones downloaded here, one line each: the number, the file’s name, from <host>, into <folder> and the state: downloading 40%, paused (remote control is off), done, failed, stopped, or a web page; pick the file on the phone. With none it says “Nothing was downloaded here yet. Share a link with Tealhand on your phone.” Works while a Host runs |
downloads cancel <id> |
Stops the running or paused download with that number. With no Host running it prints “Stopped download N. Its partial file was removed.”; with a Host running it prints “Asked the running Tealhand Host to stop download N. It stops within a second.” Works while a Host runs |
ssh on, ssh off |
Turns SSH access on or off: with it on, a connected phone may open a terminal on this computer and add or remove saved commands, after its fingerprint. Off by default. The old name terminal on and terminal off still works. Refused while a Host runs on the data folder |
commands list, commands add <key> <label> -- <line>, commands remove <key> |
The saved commands a phone may run by name. add takes --cwd <folder>, --fingerprint (the phone must ask for the fingerprint) and --timeout <seconds> (default 1 day, at most 7 days). The line is everything after --. A phone can also add and remove saved commands while SSH access is on; this is the way to do it at the computer. Refused while a Host runs on the data folder |
mcp |
The stdio side of AI apps: an AI app launches it and it relays the app’s requests to the running Tealhand on this computer. While AI apps are off, or no Tealhand runs, it answers each request with how to fix that. Takes --data-dir |
mcp on, mcp off |
Lets AI apps on this computer read your other devices, or stops it, from the next start. Off by default. A terminal at the computer needs no Windows Hello (the Tealhand app asks for it). Off also deletes the endpoint’s port and token, and takes Tealhand’s entry out of every AI app config it was added to. Writes a journal line. Refused while a Host runs on the data folder |
mcp add <app>, mcp remove <app> |
Adds a tealhand entry that launches tealhand-host mcp to the MCP config of claude (Claude Desktop), lmstudio (LM Studio) or cursor (Cursor), or takes it out. Everything else in that file stays as it was; the first change copies the file to <file>.tealhand-backup once. Prints “Added Tealhand to Claude Desktop (mcp setup. Works while a Host runs |
mcp setup |
Prints the MCP config to paste into the AI app (the tealhand-host mcp command form, with no token in it) and where copies go. Works while a Host runs |
mcp folder <dir>, mcp limit <MB> |
Where download_file saves copies (default ~/Downloads/Tealhand), and the largest file it copies (1 to 65536 MB, default 1024). Refused while a Host runs on the data folder |
agent setup claude, agent remove claude |
Connects Claude Code to your phone (guide): writes three hooks (PermissionRequest, Notification, Stop) that run this program into Claude Code’s user settings (~/.claude/settings.json, or CLAUDE_CONFIG_DIR), keeping everything else and copying the file to settings.json.tealhand-backup once; remove takes out only Tealhand’s hooks. Works while a Host runs (it notices within 5 s) |
agent hook <event> |
What Claude Code runs. Reads the hook’s JSON on stdin; for PermissionRequest asks the phone through the running Host and prints Claude Code’s decision (allow only when a phone approved with the fingerprint; deny otherwise, with a short reason); for Notification and Stop sends a notice and prints nothing. Always exits 0 |
help, --help, -h |
Prints the usage above |
--version |
Prints tealhand-host and its version |
unpair, remote off, ssh, commands, the share commands and mcp on, off, folder and limit change files
that a running Host also uses, so they refuse while one runs on the data folder: “Tealhand Host is already running
for this data folder: quit it first”. Stop it first. downloads, downloads cancel, mcp, mcp setup and
mcp add or remove are the exceptions: they work while the Host runs.
A folder can’t be shared when it is a whole drive, a system folder, Tealhand’s data folder, a link, or inside or around a folder that is already shared. At most 64 folders can be shared. See Share folders.
| Option | Default | Notes |
|---|---|---|
--data-dir <dir> |
Windows %LOCALAPPDATA%\Tealhand\host; Linux $XDG_DATA_HOME/tealhand/host or ~/.local/share/tealhand/host |
Made if missing |
--relay <choice> |
The choice saved by connect, else disabled |
disabled, public, or an https:// address (at most 512 characters to be saved). connect saves it in settings.bin; run only reads it |
--relay-pin <sha256:...> |
The fingerprint saved with the saved relay, else none | sha256: and 64 hex digits. Only with --relay and your relay’s https:// address, never with disabled or public. For a relay with a self-signed certificate: the relay connection then accepts only that certificate. connect saves it; a connect --relay without --relay-pin clears a saved one |
--port <n> |
The port used last time, else a free one | 1 to 65535. The UDP port iroh listens on. It is saved in the data folder, so the address in a connection QR stays valid for run. If it is taken, a free port is used and saved instead |
--power-helper <path> |
tealhand-power (tealhand-power.exe on Windows) in the same folder as tealhand-host |
Must be an absolute path. In release builds the file must exist, and on Unix neither it nor its folder may be writable by group or others, and both must be owned by you or root. tealhand-power is not built yet, so use a debug build for now |
--name <name> |
The host name, cleaned and cut to 64 characters; “This computer” when there is none | 1 to 64 characters, no control characters. With share add, it names the folder instead |
--read-only, --downloads |
off | Only with share add. --downloads makes the folder the default for downloads |
Options come after the command. Each option that takes a value takes one value.
The sample unit for systemd is crates/tealhand-host/packaging/tealhand-host.service: see
Install Tealhand Host on Linux.
| Environment variable | Used for |
|---|---|
RUST_LOG |
Log filter. Default error,tealhand_host=info,tealhand_mesh=warn |
LOCALAPPDATA (Windows), XDG_DATA_HOME and HOME (Linux) |
The default data folder. A relative XDG_DATA_HOME is ignored |
COMPUTERNAME, then HOSTNAME, then /etc/hostname |
The default computer name |
| Exit code | Meaning |
|---|---|
| 0 | Done: run stopped cleanly, connect connected a phone, unpair forgot the phone, remote off, ssh, commands, downloads, an mcp command or a share command did its work, or help and version |
| 1 | Failed while running: Tealhand Host could not start (for example “Tealhand Host is already running for this data folder: quit it first”, a bad computer name, a power helper path that is not absolute, or in a release build a missing power helper), connecting was cancelled, timed out or failed, or unpair, remote off, ssh, commands, downloads, an mcp command or a share command could not do their work (for example mcp add for an AI app that isn’t installed) |
| 2 | Wrong command, option or setting: an unknown command or option, remote without off, share without list, add, remove or default, ssh without on or off, downloads cancel without a number, mcp with an unknown word, mcp add or remove without claude, lmstudio or cursor, mcp limit outside 1 to 65536, a missing value, a relay address that is not https://, a bad --port or --relay-pin, a folder that can’t be shared, or no data folder found |
Every error is two lines on stderr: error: and what happened, then the fix. For example:
error: --relay-pin needs --relayAdd your relay's address with --relay https://..., or leave --relay-pin out.tealhand-relay
Section titled “tealhand-relay”usage: tealhand-relay --config <file.toml> tealhand-relay fingerprint --config <file.toml>| Command and option | What it does |
|---|---|
--config <file> |
Runs the relay with this config file until Ctrl-C or SIGTERM. The format: Relay config |
fingerprint --config <file> |
Prints the SHA-256 fingerprint of the certificate named in the config, alone on one line: sha256: and 64 hex digits. It is the value for the phone’s Certificate fingerprint field and for tealhand-host --relay-pin. The relay also logs it at every start |
--help, -h |
Prints the usage, the licence (GNU AGPL-3.0-only, no warranty) and the source code address |
| Environment variable | Used for |
|---|---|
RUST_LOG |
Log filter. Default error,iroh_relay=error,tealhand_relay=info |
| Exit code | Meaning |
|---|---|
| 0 | Stopped by Ctrl-C or SIGTERM, or printed help or a fingerprint |
| 1 | The relay could not start (for example the TLS key is readable by others, a stored device list does not verify, or a port is taken), or the relay server stopped by itself (it logs “the relay server stopped”), so a supervisor with restart-on-failure restarts it |
| 2 | Bad command line, or the config file could not be read or is not valid |
tealhand-planner
Section titled “tealhand-planner”tealhand-planner --bind 127.0.0.1:8787 --model <ollama model>| Option | Environment variable | Default | Notes |
|---|---|---|---|
--bind <addr> |
TEALHAND_PLANNER_BIND |
none, required | An IP and port. 0.0.0.0, :: and their IPv4-mapped form are refused |
--model <name> |
TEALHAND_PLANNER_MODEL |
none, required | Names containing :cloud or -cloud are refused |
--ollama-url <url> |
TEALHAND_PLANNER_OLLAMA_URL |
http://127.0.0.1:11434 |
http:// with a loopback IP, no host names, no user or password |
--timeout-secs <n> |
30 | 1 or more. Seconds for one request, the model call included | |
--max-concurrent <n> |
2 | 1 or more. Model calls at once | |
--rate-burst <n> |
10 | 1 or more. Requests one client address may send in a burst | |
--rate-per-minute <n> |
30 | 1 or more. Requests per minute one client address may keep up | |
--help, --version |
Print help or the version |
It logs at info level to standard output: the listening address, then one line per request with the status code, the duration in milliseconds and the number of steps. Ctrl-C stops it.
| Exit code | Meaning |
|---|---|
| 0 | Stopped by Ctrl-C, or printed help or version |
| 1 | Could not start: a refused bind address, Ollama URL or model name, or the port is taken |
| 2 | Bad command line (a missing or invalid option) |