---
title: "Command Line"
description: "The thinkterm binary, its subcommands, and the cli subcommands that talk to a running multiplexer."
url: "https://docs.closex.org/thinkterm/cli.html"
markdown_url: "https://docs.closex.org/thinkterm/cli.md"
site: "CloseX Docs"
product: "ThinkTerm"
language: "en"
last_updated: "2026-11-08T12:04:16.000Z"
alternates:
  en: "https://docs.closex.org/thinkterm/cli.md"
  zh-Hans: "https://docs.closex.org/zh/thinkterm/cli.md"
  ja: "https://docs.closex.org/ja/thinkterm/cli.md"
---

# Command Line

> **Documentation in progress**
> Some sections are still incomplete.

`thinkterm` is the command you use from a shell day to day.

```
thinkterm --help
```

It is not the only binary installed. Desktop and server installations both carry `thinkterm-mux-server`, which is what actually serves remote clients and browsers — see [Remote](https://docs.closex.org/thinkterm/remote.md), [Web](https://docs.closex.org/thinkterm/web.md) and [The mux server](#the-mux-server) below. A compatibility `wezterm` name is installed alongside, and the shell completions cover both. Desktop and server installations also carry `thinkterm-plugin-server`, the program plugins run under, the built-in Snippets plugin among them; it is started when something first needs it and is never run by hand — see [Plugins](https://docs.closex.org/thinkterm/plugins.md).

## Subcommands

| Command | What it does |
|---|---|
| `start` | Start the GUI, optionally running an alternative program. Aliased as `-e` |
| `tui [DOMAIN…]` | Open the ThinkTerm interface in the current terminal |
| `connect <name>` | Connect to a ThinkTerm multiplexer |
| `ssh` | Establish an SSH session |
| `serial` | Open a serial port |
| `cli <subcommand>` | See and control panes, tabs and windows, and check on coding agents, through a running multiplexer server |
| `update` | Check for a newer release and install it. See [Updates](https://docs.closex.org/thinkterm/updates.md) |
| `plugin` | List plugins, turn them on and off, reload them and send one a call. See [Plugins](https://docs.closex.org/thinkterm/plugins.md) |
| `skill setup\|status\|remove\|show` | Install ThinkTerm's skill and a session-start hook into coding agents. See [Letting a coding agent use ThinkTerm](#skill) |
| `config check [FILE]` | Load a configuration file as the app would and report its errors and warnings, without applying it; the running app is left alone. Without a file it checks the one the app would load. Exits with status 1 when the file does not load |
| `imgcat <file>` | Output an image to the terminal |
| `ls-fonts` | Display information about the fonts in use |
| `show-keys` | Show the current key assignments |
| `set-working-directory` | Tell the terminal the current working directory, for shell integration |
| `record` | Record a terminal session as an asciicast |
| `replay` | Replay an asciicast |
| `shell-completion` | Emit a completion script for bash, zsh, fish, elvish, PowerShell or Fig |

One more subcommand is left out of `--help`. `list-files` writes a Project's file listing, and it is what the desktop runs on a remote host to search that host's files — see [Files and Notes](https://docs.closex.org/thinkterm/files-and-notes.md). It is not meant to be run by hand, but it has to be there: a host whose ThinkTerm predates it cannot be searched.

On a server install there is no GUI to start. `thinkterm start`, a bare `thinkterm` and the other commands that open a window answer `this ThinkTerm has no GUI to start`, and point at `thinkterm tui`; the desktop install adds the GUI.

## Talking to a running multiplexer

`thinkterm cli` addresses a server that is already running — the one behind your GUI window, or a background mux server. Because the multiplexer can address any pane across windows, Threads and connected clients, these commands reach sessions you are not currently looking at.

Which server answers is otherwise implicit, and it is the usual reason a command appears to do nothing: by default `thinkterm cli` prefers a running GUI, and starts a server if it finds none. `--prefer-mux` sends the command to the background mux server instead, and `--no-auto-start` makes the command fail rather than start a server just to answer it.

`--class <NAME>` picks out a GUI started under a window class of its own, with `--class` on `thinkterm start`. Without it, the command finds the GUI you started normally; you only need `--class` to reach one you started with a class of its own. `thinkterm tui` takes the same flag and works the same way.

A command that acts on a pane takes `--pane-id` with its number, and otherwise acts on the pane it runs in, which `WEZTERM_PANE` names. `--pane` names one instead, by a label you gave it — see [Naming panes](#naming-panes).

**Finding things**

| Command | What it does |
|---|---|
| `list` | List windows, tabs and panes, each with its label if it has one |
| `list-clients` | List connected clients |
| `get-pane-direction` | Report the pane in a given direction |

**Creating and destroying**

| Command | What it does |
|---|---|
| `spawn` | Start a new tab or window. Prints the new pane's id. `--label` names the pane; `--wait` waits for its program and exits with its status |
| `split-pane` | Split an existing pane. Prints the new pane's id, and takes `--label` and `--wait` as `spawn` does |
| `move-pane-to-new-tab` | Move a pane out into a tab of its own |
| `kill-pane` | Close a pane |

**Moving around and resizing**

| Command | What it does |
|---|---|
| `activate-pane` | Focus a pane |
| `activate-pane-direction` | Focus the pane in a direction |
| `activate-tab` | Focus a tab |
| `adjust-pane-size` | Resize a pane |
| `zoom-pane` | Zoom a pane to fill its tab |

**Text in and out**

| Command | What it does |
|---|---|
| `send-text` | Write text into a pane as a paste, bracketed if the program in it asked for that. No Enter is added: `--enter` presses it a moment after the text, and `--no-paste` sends the text as plain input |
| `send-key` | Press keys by name, one after another, encoded the way the program in the pane asked for keys, as if typed. `--wait` then waits for the command they start. See [Pressing keys](#send-key) |
| `get-text` | Read the text on a pane's screen. `--pane-id` or `--pane` picks the pane, by default the one the command runs in. `--start-line` and `--end-line` pick the rows: 0 is the top of the screen, and a negative number reaches back into the scrollback. `--format` is `text` (the default), `vt`, which keeps the colour and style sequences as `--escapes` does, or `html`, with its colours. `--trim` drops the spaces that end lines and the empty lines at the end, and `--unwrap` joins the lines the terminal wrapped back into the lines they were |

**Waiting and watching**

| Command | What it does |
|---|---|
| `wait` | Wait for a pane's program to end, or with `--command` for the command running in its shell, and exit with its status. See [Waiting for a program or a command](#wait) |
| `events` | Print what happens as it happens until interrupted. See [Watching what happens](#events) |

**Naming and infrastructure**

| Command | What it does |
|---|---|
| `set-tab-title` | Rename a tab |
| `set-pane-label` | Label a pane, so that `--pane` finds it. An empty label takes it away |
| `set-window-title` | Rename a window |
| `rename-workspace` | Rename a workspace |
| `agent list` | List the panes running a detected coding agent, and each one's state. Read-only |
| `agent context` | Print where the pane it runs in is and what shares its tab, for a coding agent starting there. See [Letting a coding agent use ThinkTerm](#skill) |
| `tlscreds` | Obtain TLS credentials |
| `proxy` | Start an RPC proxy pipe |
| `color-schemes` | List the built-in colour schemes. Answered from the binary, with no server involved; `--json` prints their colours too |
| `stop-server` | Stop the background session server. Every terminal inside it ends, so it asks first when run at a terminal; `--force` does not ask |
| `restore-output status\|on\|off` | Whether this machine keeps what its panes show when its terminals stop, to put it back when their layout is restored. Answered from a switch on this machine, with no server involved. See [Keeping pane output](#restore-output) |

**Browser access**

| Command | What it does |
|---|---|
| `web-server status\|on\|off` | Whether the server is accepting browsers, and where. `on` takes `--bind-address` |
| `web-token mint\|list\|revoke` | Mint, list and revoke the links a browser gets in with |

Both address the mux server rather than a GUI's own multiplexer, and a minted link is a login as your user on that machine. With [reaching other machines](https://docs.closex.org/thinkterm/web.md#reaching-other-machines) on, it is also a way into every machine that account can SSH to. [Web](https://docs.closex.org/thinkterm/web.md) covers what that means.

**Sharing**

| Command | What it does |
|---|---|
| `share list\|stop\|kick\|revoke\|deny` | See and take back the panes you share with other accounts on this machine. See [Shared panes](#shared-panes) |
| `share incoming\|watch` | List the panes other accounts on this machine share with you, and watch one in this terminal |

`list`, `list-clients`, `agent list` and `web-token list` print a table by default, and JSON with `--format json`. The first three, and `events`, take `--json` for short.

The commands that print a list or text — those four, `get-text` and `color-schemes` among them — end quietly, with a success status, when whatever they are piped into stops reading, as in `thinkterm cli list | head`.

## Stopping the session server

`thinkterm cli stop-server` stops the background session server at the default socket, and every terminal inside it ends with it. It never starts a server: with none running, it says so and changes nothing.

Run at a terminal, it names the server's process and socket and asks first, and anything but `y` or `yes` leaves the server running. It asks only when its standard input is a terminal, so a script or a pipe stops the server without a question; `--force` skips the question at a terminal too. It then waits up to ten seconds for the server to exit, and says so if it is still shutting down after that.

The next launch, `connect` or `cli` command that needs a server starts a fresh one. [Remote](https://docs.closex.org/thinkterm/remote.md) describes the other ways to stop it.

## Naming panes {#naming-panes}

A pane number changes from one run to the next. A label does not: `thinkterm cli set-pane-label --pane-id 12 build` names pane 12, `spawn` and `split-pane` take `--label build` to name the pane they create, and from then on `--pane build` finds it.

```
thinkterm cli set-pane-label build
thinkterm cli spawn --label tests -- npm test
thinkterm cli get-text --pane tests --trim
```

A label is the name a pane tab carries in the window, so renaming the tab there sets the same label. It is kept by the server, which means every window, the CLI, a browser and a restored Thread see it. A label has no control characters and at most 128 characters, and is trimmed. One of only digits is refused, since `--pane` reads digits as a pane number. An empty label takes the label away. `list` and `agent list` show the label in a `LABEL` column and a `label` field, and `events` reports a pane being labelled.

`--pane` accepts:

- **A pane number.** Digits and nothing else. If another pane's label is those same digits, the command stops and lists both rather than guess.
- **A label**, with case ignored.
- **A Thread's name**, alone or after its Project's as in the sidebar — `my-project · fix login` — when that Thread has one pane.
- **`thread/label`**, for a label that several Threads use.
- **`MACHINE/ID`** or **`MACHINE/LABEL`**, for a pane on a server your window is connected to, when [the setting for it](#servers-terminals) lets programs here reach it.
- **`desktop-0123abcd/21`**, on a server, for a terminal on the computer you connected from, once you approve that there; see [Letting a connected server reach your local terminals](https://docs.closex.org/thinkterm/remote.md#connect-reverse-access).

When a label is held by several panes and exactly one of them is in the Thread of the pane running the command, that one is meant. Otherwise the command stops, says how many panes the name could be, and lists each with its number, label, title and Thread; name one by number. `--pane` cannot be combined with `--pane-id`. Every command that takes a pane takes `--pane`, `spawn`, `split-pane` and `activate-tab` among them.

## Pressing keys {#send-key}

`send-key` takes one or more keys, each written as modifiers and a key joined with `+`, in any case:

```
thinkterm cli send-key --pane build ctrl+c
thinkterm cli send-key escape up up enter
```

The modifiers are `ctrl`, `alt` (or `opt`), `shift` and `cmd` (or `super`). A key is a single character, or `enter`, `tab`, `escape`, `backspace`, `delete`, `space`, `up`, `down`, `left`, `right`, `home`, `end`, `pageup`, `pagedown`, `insert`, or `f1` to `f24`. Each is encoded the way the program in the pane asked for keys, as if typed. A key it does not know stops the command before anything is sent.

## Waiting for a program or a command {#wait}

`wait` blocks until something in a pane ends, and exits with how it ended:

```
thinkterm cli spawn --label tests --wait -- npm test
thinkterm cli wait --pane tests --for 10m
thinkterm cli send-key --pane build --wait enter
```

- **`wait`** waits for the program the pane started to end, and exits with its status.
- **`wait --command`** waits for the command running in the pane's shell, and exits with that command's status. A command typed a moment ago has a second to start; when none has, it exits with the status of the last command that finished, or 0 if none ever did.
- **`send-key --wait KEY…`** presses the keys and then waits for the command they start. It counts the shell's finished commands first, so a command that ends at once is not missed. To type a command and wait for it, `send-text` and then `send-key --wait enter` is surer than `wait --command` afterwards.
- **`spawn --wait`** and **`split-pane --wait`** print the new pane's number first, then wait for its program.

`--timeout`, or `--for` for short, gives up after a number of seconds or a number with `s`, `m` or `h`: `90`, `30s`, `10m`, `1.5h`. A wait that gives up exits with status 124 and says `timed out`. A program or command that ended without a known status exits with 125, and says so: a command the shell ended without an exit status, and a program in a pane a new server took over with `--takeover`, which can no longer say how its program ended. Neither reads as a success. A pane that closes without its program's status arriving exits with 1, and a program ended by a signal names the signal on standard error.

`wait --command` and `send-key --wait` need a shell that reports where its commands start and end. That is ThinkTerm's shell integration; see [Install](https://docs.closex.org/thinkterm/install.md). Without it they stop with an error that says so, and `spawn --wait` still works.

## Watching what happens {#events}

`thinkterm cli events` prints one line for each thing that happens on the server until interrupted:

```
14:02:11  command_finished    pane 12  status 0
14:02:11  agent_status        pane 12  claude idle
```

`--pane` or `--pane-id` keeps only what happens to one pane; tab, window and client events drop out. `--format json`, or `--json`, prints one object per line instead, with a `type` and the event's own fields. These are kept stable: events and fields may be added, never removed or retyped. If more than a few thousand events pile up unprinted, the extra ones are dropped. The command reconnects by itself when the connection to the server is replaced, and stops with an error when it is lost.

| `type` | When | Fields besides `type` |
|---|---|---|
| `pane_added`, `pane_removed` | A pane opens or closes | `pane_id` |
| `program_exited` | The program the pane started ended | `pane_id`, `exit_code` (`null` when unknown), `signal` |
| `command_finished` | The pane's shell reported a command finished | `pane_id`, `exit_code` (`null` when it gave none) |
| `bell` | The pane rang the bell | `pane_id` |
| `notification` | A program raised a desktop notification | `pane_id`, `title`, `body` |
| `title_changed` | The pane's title changed | `pane_id`, `title` |
| `cwd_changed` | The pane's working directory changed | `pane_id` |
| `progress` | A progress report | `pane_id`, `state` (`none`, `percentage`, `error` or `indeterminate`), `percent` |
| `user_var` | A program set a user variable | `pane_id`, `name`, `value` |
| `clipboard_written` | A program wrote the clipboard. What it wrote is not repeated | `pane_id` |
| `agent_status` | A coding agent was found in the pane, changed state or went | `pane_id`, `agent`, `state` |
| `foreground_program` | The program in front in the pane changed | `pane_id`, `executable`, `runs` |
| `pane_focused` | A pane took focus | `pane_id` |
| `pane_label_changed` | A pane was labelled, or lost its label | `pane_id`, `label` (`null` when taken away) |
| `tab_added` | A tab was added to a window | `tab_id`, `window_id` |
| `tab_title_changed` | A tab was renamed | `tab_id`, `title` |
| `window_title_changed` | A window was renamed | `window_id`, `title` |
| `workspace_changed` | A window moved to another workspace | `window_id`, `workspace` |
| `workspace_renamed` | A workspace was renamed | `old_workspace`, `new_workspace` |
| `client_joined`, `client_left` | A window, browser or phone began or stopped showing panes | `hostname`, `username`, `pid`, `epoch`, `id` |

## Panes on connected servers {#servers-terminals}

A window connected to a server holds that server's terminals, and programs on this computer can reach them with `thinkterm cli` — but only as far as `Settings › Agents › Servers' Terminals › Programs on This Machine` lets them. It is `Off` by default. `Read` lets them list and read the terminals, and `Read & Type` lets them type too. The setting exists because a program in one of this computer's terminals, a coding agent or a plugin say, is not the person at the window, and what it reaches is a shell on another machine, logged in as you: it goes through the connection the window signed in on.

With it on and a ThinkTerm window open and connected, `list` adds the server's panes after this machine's. Each is named `MACHINE/ID`: the machine's name as the window calls it, a slash, and the pane's number on that server. In JSON that is a string, not a number. `--pane` takes the same name, or `MACHINE/LABEL` when the pane has a label there; case is ignored, and a machine's name may itself contain slashes. `get-text`, `send-text`, `send-key`, `wait` and `events` take such names; `--pane-id` and the other commands do not reach these panes. In `events`, an event about one of them names it in a `pane` field, and in the table in place of the pane number. A name that matches no pane there stops with exit status 3. If the setting is off or no window is open, the error says that a pane on a server is named `MACHINE/NAME`, as `list` shows it, with ThinkTerm open and the setting letting programs here reach it.

The reverse also exists. A program on a server can reach the terminals of the computer you connected from, once you approve it there; its `list` shows them as `desktop-0123abcd/21`, and the same commands take that name with `--pane`. See [Letting a connected server reach your local terminals](https://docs.closex.org/thinkterm/remote.md#connect-reverse-access).

## Shared panes {#shared-panes}

A terminal can be shared with other accounts on this machine from its share button in ThinkTerm, once `Settings › Share & Sync › Share terminals` is on; [Sharing a terminal](https://docs.closex.org/thinkterm/window.md#sharing-a-terminal) covers the button and its panel. It is off by default and marked experimental. Sharing is a decision for a person, so the command line cannot start a share: what it does is look at shares, take them back, and watch the ones shared with you. The people a pane is shared with see it live but cannot type in it; to type they ask, and the owner decides. A share ends after at most 30 minutes, or when the desktop that started it goes away. Typing is granted for 30 minutes at a time, and the owner can take it back at any time.

| Command | What it does |
|---|---|
| `share list` | List your shares: the pane, who it is for, who is watching, who may type, who has asked to, and when it ends. `--format json` prints JSON |
| `share stop SHARE` | End a share; everyone watching it is dropped |
| `share kick SHARE VIEWER` | Drop one viewer from a share. The viewer is the id `list` shows, or the account name |
| `share revoke SHARE` | Take typing back |
| `share deny SHARE VIEWER` | Turn down a viewer's request to type; it goes on watching |
| `share incoming` | List the panes other accounts on this machine share with you, as `OWNER/SHARE`, with the title, since when and who is typing. `--format json` prints JSON |
| `share watch [OWNER/SHARE]` | Watch one in this terminal |

The first five talk to the background mux server, as `web-token` does, not to a window. `incoming` and `watch` ask the other accounts' servers instead, each on the socket it shares from, and need no server of your own.

`watch` names the share as `OWNER/SHARE`, as `incoming` shows it, or `OWNER` alone when that account shares one pane with you, or nothing when only one pane is shared with you. If more than one fits, it stops with exit status 2 and lists them; if none does, with status 3. What an account running another version of ThinkTerm shares shows up once both run the same, and the command says so. The pane is drawn at the owner's size: a smaller terminal shows the part around the cursor, a larger one leaves the rest blank. Until the owner lets you type, your keys only look around: the arrows or `j` and `k`, Page Up and Page Down scroll through the history, `g` or Home goes to the top and `G` or End back to the live screen, and `h` and `l` or the left and right arrows pan. `Ctrl-]` starts a command of its own: `q` quits, and `r` asks the owner to let you type, or gives typing back once you have it. While you can type, your keys go to the pane, and `Ctrl-]` twice sends a literal `Ctrl-]`. `--once` prints the shared screen once, as text, and exits.

## Keeping pane output {#restore-output}

`thinkterm cli restore-output` is the command-line side of `Settings › General › Restore pane contents`, for the machine you run it on. `status` says whether this machine keeps what its panes show when its terminals stop, `on` turns that on, and `off` turns it off and deletes what was kept. It reads and writes a switch on this machine, so no server is involved or started. Where the desktop runs, the switch is on unless it was turned off; on any other machine, a remote host say, it is off until `restore-output on` runs there. What is kept, with passwords and tokens masked before anything is saved, and how it comes back are described in [Restoring pane contents](https://docs.closex.org/thinkterm/configuration.md#restoring-pane-contents).

## Exit statuses

A `cli` command that fails exits with 1, except these:

| Status | Meaning |
|---|---|
| 2 | The command line asks for something that cannot be: arguments that do not parse, an unknown key, a label of only digits |
| 3 | A pane that is not there, or a `--pane` name that matches none or several |
| 4 | The server cannot be reached, or will not talk to this version of the program |

A command that waits exits with what it waited for instead, as [above](#wait).

## Agent status from a script

`thinkterm cli agent list` prints one row for each pane in which ThinkTerm has found a coding agent:

| Column | What it holds |
|---|---|
| `PANEID` | The pane, by the id the other `cli` commands take |
| `AGENT` | The agent's id, such as `claude` |
| `STATE` | `working`, `blocked`, `idle`, `error` or `unknown` |
| `EVIDENCE` | What decided the state: `report` when the program sent its own status report, `contract` when the program reported it through `THINKTERM_AGENT`, `screen` when a screen rule matched, `fallback` when nothing matched and a known agent is taken to be idle |
| `AGE` | How long ago the state last changed |
| `WORKSPACE` | The multiplexer workspace the pane is in. For a pane in a Thread this is an internal name, not the Thread's |
| `TITLE` | The pane's title |
| `LABEL` | The pane's [label](#naming-panes), empty when it has none |

`--format json` prints an array of objects instead, with the fields `pane_id`, `label` (`null` when there is none), `agent`, `state`, `evidence`, `session_id` (`null` when there is none), `since_unix` (when the state last changed, in Unix seconds by the clock of the machine that detected it), `workspace` and `title`. These fields are meant for scripts and are kept stable. [Agent Status](https://docs.closex.org/thinkterm/agents.md) explains where the states come from.

## Letting a coding agent use ThinkTerm {#skill}

A coding agent running in a ThinkTerm pane can use `thinkterm cli` to see the other panes, read them, type into them and open new ones. `thinkterm skill setup` teaches Claude Code and Codex to, and tells each one where it is when it starts. It is separate from [recognising agents](https://docs.closex.org/thinkterm/agents.md), which installs nothing, and it changes nothing until you run it.

```
thinkterm skill setup --dry-run
thinkterm skill setup
```

| Command | What it does |
|---|---|
| `skill setup` | Installs or updates the skill and the hook in the agents found on this machine. Safe to run again. `--dry-run` says what would change without changing it |
| `skill status` | Shows, for each agent, whether the skill and the hook are `current`, `outdated`, `missing`, `someone else's` or `unreadable` |
| `skill remove` | Takes the skill and the hook out again |
| `skill show` | Prints the skill, for an agent `setup` does not know. `npx skills add RoversX/ThinkTerm --skill thinkterm -g` installs the same skill from the repository for other agents, such as Cursor |

`setup`, `status` and `remove` take `--agent claude` or `--agent codex` to name one agent whether or not it was found. Without it they go through the agents whose own folder exists here, and say so when there is none.

**What `setup` writes**

| Agent | The skill | The hook |
|---|---|---|
| Claude Code | `~/.claude/skills/thinkterm/SKILL.md` | A `SessionStart` entry in `~/.claude/settings.json` |
| Codex | `~/.agents/skills/thinkterm/SKILL.md` | A `SessionStart` entry in `~/.codex/hooks.json` |

`CLAUDE_CONFIG_DIR` and `CODEX_HOME` move an agent's own folder, and with it Claude Code's skill and both settings files. The skill is a short note: that the agent is inside ThinkTerm, that `thinkterm cli --help` lists the commands, where `thinkterm` is if it is not on `PATH`, and that typing into a pane it did not open, closing panes or stopping the server may deserve asking you first. A pane has `THINKTERM=1` set, which the skill's description keys on.

The hook runs when the agent starts. In a ThinkTerm pane it prints the pane's number, label and title and its tab's title, then the other panes in that tab — up to twelve, then how many more — how many panes other tabs hold, and how to read a pane. This is `thinkterm cli agent context`. Outside a ThinkTerm pane, or when ThinkTerm does not answer, it prints nothing and succeeds, and it never starts a server, so the agent starts as it would without it. Waiting for it is capped at ten seconds. The hook is not installed on Windows yet; the skill is.

`setup` edits only the `hooks` entry of the settings file and leaves the rest of its text as it was. It leaves alone a settings file that is not a JSON object, and a skill file called `thinkterm` that is not ThinkTerm's, and says so. Claude Code runs hooks only in folders you have trusted, and Codex runs a new hook once you approve it with `/hooks`. Run `setup` again after an update to bring an `outdated` skill or hook up to date.

**Undoing it.** `thinkterm skill remove` deletes the skill file, and its folder when nothing else is in it, and takes the hook out of the settings file together with any `SessionStart` list or `hooks` object that leaves empty. Other hooks and other skills stay. By hand, delete the file and remove the entry.

## Colour schemes as data

`thinkterm cli color-schemes` prints the names of the built-in colour schemes, one per line. `--json` prints a JSON array instead, one object per scheme, with `name`, `foreground`, `background`, `cursor_bg`, `cursor_fg`, `cursor_border`, `selection_bg` and `selection_fg` as `#rrggbb` strings, and `ansi` and `brights` as lists of eight. A scheme that names no cursor or selection colours gets the defaults filled in.

The list is the one compiled into the binary, so it needs no server and reads no config. Schemes defined in your config, or kept in a colours directory, are not in it.

## The mux server {#the-mux-server}

`thinkterm-mux-server` is the multiplexer on its own, with no window. When the desktop keeps its terminals in a session server, that server is one of these, started for you; on a host with no desktop you start it yourself, usually with `--daemonize`.

| Flag | What it does |
|---|---|
| `--daemonize` | Detach from the terminal and run in the background |
| `--takeover` | Take over from the mux server already running on the same socket: its panes, windows and clients carry on under the new binary, and the old server exits. The running server must support it, and it refuses a build older than itself |
| `--no-initial-pane` | Start with no pane, instead of one running the default program. The desktop's session server starts this way, since every pane in it is one the desktop asked for |
| `--cwd <DIR>` | The working directory of the first pane's program |
| `-- <PROG>…` | Run this program in the first pane instead of your shell |
| `-n`, `--config-file`, `--config name=value` | Skip the config, pick a config file, or override one option — the same global flags `thinkterm` takes |

## Two programs in two panes can talk to each other

`send-text` and `get-text` are enough to let one program drive another, with no changes to either of them:

```
Program A ──send-text──►  Program B's terminal input
                          B does the work and prints a response
Program A ◄──get-text───  reads the result back
```

Anything interactive can take part — a coding assistant, a shell script, a REPL. The pane is the interface, so nothing has to be built for this specifically.

Today the exchange happens by injecting terminal input, which means there is no message identity and no structured response. `send-text --enter` and `send-key` do the typing, and `get-text --trim` reads the screen back. Completion need not be polled for: when B is a shell command, `send-key --wait enter` returns when it ends, with its status, and `wait` does the same for a program. When B is a coding agent, `events --pane` reports its `agent_status` going back to idle. A more structured protocol is under design.

## Related

- [Agent Status](https://docs.closex.org/thinkterm/agents.md) — what `cli agent` and `cli events` report on
- [Web](https://docs.closex.org/thinkterm/web.md) — what `web-server` and `web-token` turn on
- [TUI](https://docs.closex.org/thinkterm/tui.md) — the workspace in a plain terminal
- [Plugins](https://docs.closex.org/thinkterm/plugins.md) — what `thinkterm plugin` manages
- [Keyboard and Commands](https://docs.closex.org/thinkterm/keyboard.md) — the keymap `show-keys` prints
