Termic ships a termic command that drives the running app from any shell. Anything you do by clicking — create a task, prompt an agent, wait for it to go quiet, check a diff, archive it — has a verb, so the same workflow fits in a script, a Makefile target, or another agent’s hands.
The app itself is the daemon. Every command talks to the running Termic over a local socket and fails fast when it cannot, so a command never silently half-works.
Getting the command
The CLI is enabled by default and installs itself on first launch. Termic automatically drops the command into ~/.local/bin/termic in the background, without a prompt. If that directory is not on your PATH, Settings → Termic CLI offers Install system-wide, which symlinks into /usr/local/bin instead and asks for your password.
Check it works:
termic --version
termic list
If termic list reports that the app is not running, launch Termic and try again, or pass --no-launch to make that an explicit failure instead of auto-launching.
Your first commands
Run these from inside a repo you have registered as a project. Most verbs resolve the task from your current directory, so you can usually leave the name out.
# Create a task, start its agent, and give it something to do
termic new fix-auth -p "fix the login redirect"
# See everything that is running
termic list
# Block until that agent stops
termic wait fix-auth
# Prompt an agent that is already running
termic send fix-auth -p "now add a regression test"
# Where does its worktree live?
cd "$(termic path fix-auth)"
new returns as soon as the agent spawns. Add --wait to block until the prompt is confirmed delivered and that turn settles.
Targeting a task
Most verbs take an optional task name. When you omit it, the task is resolved from your working directory.
| Form | Meaning |
|---|---|
termic status | The task your shell is currently inside |
termic status fix-auth | By name |
termic status myrepo/fix-auth | Qualified, when two projects share a name |
termic status --project myrepo fix-auth | Same, explicitly |
termic status --tab 2 | One tab inside the task, by index, id, or title |
A selector that matches nothing is a typed error naming the candidates, rather than a silent default. Tasks can hold several tabs, so send, logs, wait and friends all accept --tab to aim at one.
Getting results out
This is the part worth reading twice, because it surprises people: the agent’s terminal output is not readable from the CLI. logs and result can peek at a running agent, but they are not a reliable machine-readable channel.
For anything scripted, ask for a file in the prompt and read it afterwards:
termic new audit -p "review the auth module; write your findings to RESULT.md" \
--sandbox enforce --wait
cat "$(termic path audit)/RESULT.md"
Two details that make unattended runs actually work:
- Pass
--sandbox enforceor--yolo. Otherwise the agent stops to ask for permission and your script waits forever. Permission prompts self-approve inside the cage. --waitexiting0means the agent stopped, not that the work is correct. Settle detection is a heuristic. Check the artifact, not the exit code alone.
Letting agents drive other agents
Every task’s terminal is handed TERMIC_CLI, TERMIC_TASK_ID and a short TERMIC_CLI_HELP in its environment. An agent working inside Termic can therefore discover the CLI with no setup and dispatch work to other tasks: fan a job out across several agents, wait on them, and read back what they produced, without you brokering it.
# From inside an agent's own terminal
"$TERMIC_CLI" new schema-check --sandbox enforce --wait \
-p "check the migrations for destructive changes; write to RESULT.md"
cat "$("$TERMIC_CLI" path schema-check)/RESULT.md"
Two guardrails apply here:
- Agents running in an enforced sandbox never get access. The control socket is outside the cage, so a caged agent that tries gets an explicit “control plane unavailable” refusal rather than a hang.
- The auth token is deliberately never placed in any child’s environment, so an agent cannot stash it and hand a caged sibling a way in.
Have the agent rename its own task once it knows what it is really working on, so your sidebar stays readable:
"$TERMIC_CLI" rename "fix the login redirect"
Scripting: JSON and exit codes
Every verb takes --json (one object on stdout) or --output-format stream-json (NDJSON events ending in exactly one result line). Fields only ever grow, so parsing is safe across upgrades.
termic list --json | jq -r '.tasks[] | select(.state == "idle") | .name'
Branch on the exit code rather than scraping text:
| Code | Meaning |
|---|---|
0 | Success. With --wait, the agent settled |
1 | Error: bad task or project name, ambiguity, server failure |
2 | Usage error |
3 | The agent stopped but is asking for input |
4 | Termic is not running (with --no-launch) |
5 | The CLI is disabled in Settings |
6 | Refused |
7 | --timeout expired |
8 | Connection lost |
9 | The prompt was never delivered |
Exit 3 is the one worth handling explicitly: the agent is alive and blocked on a question, which is very different from failing.
termic help --json prints the entire command surface machine-readably, which is the fastest way for a script or an agent to learn what is available on the version actually installed.
termic:// deep links
A shell is not the only thing outside Termic that might want to start a task. A termic:// URL opens a pre-filled New Task dialog:
termic://new?project=web&worktree=1&name=fix-login&p=Fix%20the%20login%20bug
| Parameter | What it sets |
|---|---|
project | Which project the task belongs to |
worktree | 1 for a worktree task, otherwise the main checkout |
name | The task name, which also fills the branch field |
p | The first message, URL-encoded |
The link only fills the form. A human still presses Create, and that is the entire security model: any page that can navigate to a URL scheme can hand you a prompt, so nothing is allowed to run on arrival. You read what it wants before it happens.
This is what makes an internal dashboard, a bug tracker or a wiki able to offer “open this in Termic” without either side integrating with the other.
Security
Access is gated by a per-boot token stored in Termic’s data directory with 0600 permissions, so only your own user account can read it. Enabling the CLI does not open a network port and does not widen what another user on the machine can reach.
You can turn it off at any time in Settings → Termic CLI. Turning it off refuses every command immediately, and the command stays installed so re-enabling costs nothing.
Related
- MCP endpoint: the same verbs as tools, for an MCP client rather than a shell.
- Tasks & worktrees: what
termic newcreates. - Parallel agents: one agent farming work out to several others.
- Settings reference: enabling the CLI.