CLI reference
Every terminalhire subcommand, grouped by what it's for. th works as a
short alias everywhere you see terminalhire. Run terminalhire --help for
the live, in-terminal version of this list.
Account
| Command | What it does |
|---|---|
init |
One-command onboarding — start here |
login |
Sign in with GitHub (enriches your profile instantly) |
logout |
Clear the stored GitHub token |
link |
Connect this terminal to your terminalhire account |
link --logout |
Revoke this terminal's linked session |
profile --show |
Display your encrypted local profile |
profile --edit |
Set display name, contact email, preferences |
profile --delete |
Wipe your profile and encryption key from disk |
config --show |
Print current config |
refresh |
Fetch the latest index + re-match, update the local cache |
sync --push |
Opt-in: send your profile to staqs (typed-yes consent) |
sync --status |
Show whether you've consented (local read) |
sync --delete |
Hard-delete your synced profile (revocation) |
Matching — see Getting started
| Command | What it does |
|---|---|
jobs |
Fetch the index, browse roles matched to your profile |
jobs --all / --page N / --limit N |
Page through the full ranked list |
jobs --status <s> |
Filter by applied/saved/dismissed/clicked/unactioned |
jobs mark <id> <status> |
Track your funnel — see Job statuses |
save <jobId> / saved / unsave <jobId> |
Save, list, or remove a saved job |
Credential — see Proof of Work
| Command | What it does |
|---|---|
trajectory |
Trajectory from your local Claude Code corpus |
trajectory --export |
Write a derived score + Markdown locally |
trajectory --push |
Opt-in: link your trajectory to your dashboard (typed-yes) |
contribute |
Feed of credential-building open issues (on by default; opt out with contributeEnabled: false) |
contribute <owner/repo> |
Open, unassigned issues in ONE project you name, ranked to your stack; also adds the repo to the shared index |
Postings — see Postings and claims
| Command | What it does |
|---|---|
bounties [--priced] |
First-party postings by default; --priced adds scraped paid open-source supply |
claim preview <id|url> |
Read-only preview of a posting before claiming |
claim record <id|url> |
Claim work locally; a first-party posting is also registered server-side to your verified identity |
claim start <id|url> [--watch] |
The one-verb path: records if unrecorded, then provisions — OSS forks + clones; a first-party posting delivers your workspace, --watch waiting out a pending approval |
claim attach <id> --worktree … --branch … |
Link a claim to your working branch |
claim slice <id> |
First-party postings: fetch the shared file slice, contents included — no clone, no credential (claim start runs this for you) |
claim submit [id] |
Open the PR from your fork — or, on a first-party posting, submit the patch over HTTP (no fork). From the claim’s worktree the id is optional |
claim runs <id> |
First-party postings: read the poster’s own CI verdict on your submitted patch |
claim status [<id>] |
Check poster approvals or poll source PR merge state |
claim list [--active] |
Your claims + accepted-PR rate |
claim release <id> |
Give up a claim on this machine. terminalhire is not told, so the poster hears nothing |
claim resolve <id> --reason <r> [--note …] |
Hand a claim back and tell the poster why. Some reasons take the posting off the market until they act; the rest hand it on. --help lists which is which |
claim notes [--json] |
Read what the poster wrote on your claims. Clears the 📝 statusline badge |
protocol register / unregister / status |
Wire (or unwire) th://claim/<token> links on this machine — see Claim links |
claim start and claim slice both take --dir <path>, which names where the
workspace lands, and --open <agent>, which hands that directory to claude,
codex, agy or cursor-agent once it is ready. A directory that already holds
files is never written into: the delivery goes to a numbered sibling and prints
where it went.
Both commands finish by leaving you in the workspace — your own shell, started
there, with exit bringing you back where you were. --open <agent> starts that
agent instead. --stay prints the cd and returns, which is also what you get
with no terminal attached, so scripts and --watch are unaffected.
Verification — see Verifying your work
| Command | What it does |
|---|---|
run |
Apply your working diff to a clean clone and run the project's tests in a container |
run --watch |
Re-run on every save |
run --keep <s> / --no-preview |
Hold the preview URL open (local runs), or skip the preview. A hosted terminal run needs --no-preview until venue ingress exists — without it, it refuses at the preview step |
run --test-command <cmd> |
Disclosed override of the derived test command |
run --placement <kind> |
Where the run happens. local-docker (default) or hosted — a per-run cloud VM; needs launch credentials, and is what our dispatch worker runs once pointed at it |
Defaults come from .th-run.json in the checkout, so a claim you run repeatedly needs no flags. Needs Docker running.
Connect — see Connect
| Command | What it does |
|---|---|
devs / devs --as-project |
Rank opted-in builders locally |
project "<title>: <skills>" / project --show |
Declare or view a local project |
intro <login> / intro --list / intro --accept @<login> |
Request, list, or accept intros |
connect / connect --mute / connect --unmute |
Overview + toggle inbound nudges |
chat / chat <login> --read / --send |
Inbox, read, or send in a connection thread |
inbox |
Interactive inbox TUI |
Surfaces — see Claude Code surfaces
| Command | What it does |
|---|---|
spinner --show / --off / --mode append|replace |
Toggle and configure the spinner |
statusline --on / --off |
Toggle the connection-only status line |
mcp / mcp --print-config |
Run the MCP server; print host config — see MCP |
config --nudge session|always|every:N |
Tune nudge frequency |
config --connect on|off |
Opt in/out of ambient peer/poster surfacing |
config set mix jobs|balanced|credential / config get mix |
Balance roles vs. contribution items on the surface (default balanced; env TH_MIX overrides) |
Spinner tips lead with claimable first-party paid work when available. Otherwise they favor roughly ten contribution opportunities per role; relevant public bounties follow the role.
Pointing the CLI somewhere other than terminalhire.com
Every command talks to https://terminalhire.com unless you say otherwise. If you
are working against the dev deployment, or against a copy of the web app running on
your own machine, a bare command asks production instead — and production answers
about a claim it has never heard of, which reads as "this work does not exist".
| Variable | What it does |
|---|---|
TERMINALHIRE_API_URL |
The deployment to talk to. Allowlisted: the apex, dev.terminalhire.com, loopback |
TERMINALHIRE_ALLOW_LOCAL_API |
Set to 1 before any http://localhost:<port> base is accepted |
TERMINALHIRE_ALLOW_LOCAL_OAUTH |
Set to 1 as well before login will open a browser sign-in against loopback |
TERMINALHIRE_DIR |
Where sessions and claims live. Unset: ~/.terminalhire, or ~/.terminalhire-dev when pointed at dev |
For the dev deployment, use thdev instead — it is the same CLI with that origin
pinned, so it needs no variable at all and works the same in PowerShell, cmd.exe and
bash. VAR=value command is a POSIX-shell one-command assignment: on Windows it does
not set anything, and the command silently reaches production.
# the dev deployment — every command, no variable
thdev claim slice <id>
thdev bounties
thdev login
# a web app running on your own machine, on whatever port it serves
TERMINALHIRE_ALLOW_LOCAL_API=1 TERMINALHIRE_API_URL=http://localhost:3000 \
terminalhire claim slice <id>
The dev deployment has its own credential store, ~/.terminalhire-dev, and
every way of pointing at dev uses it: thdev, the variable, an MCP server entry
that sets the variable. So thdev login and terminalhire login are separate
accounts on disk, neither overwrites the other, and a sign-in through one spelling
is visible to the others. Set TERMINALHIRE_DIR to choose a store yourself; it
wins over that default. Loopback keeps ~/.terminalhire and still uses the
variables above: there is no pinned binary for an arbitrary local port.
Any other host is refused outright rather than quietly falling back to production — writing a claim to the wrong environment is not something a later command can undo. The two loopback flags are separate because they grant different things: the first lets stored credentials reach a local listener, the second lets a browser sign-in happen there, and neither is implied by the other.
Your session belongs to one deployment. Signing in on production does not sign
you in on dev, so point login at the same place before anything that says a claim
is not registered to you:
thdev login
The claim page prints the right form into its own copy buttons — thdev … on dev, a
prefixed command on loopback — so a command copied from a page is already pointed at
the deployment that served it.