---
source: https://threa.io/developers/cli
notes: Markdown mirror generated from the page above. YOUR_WORKSPACE_ID is the ws_… id in the app URL after /w/; YOUR_API_KEY is a key from Settings > API keys.
---

# The threa command line.

`threa` wraps the public API as a command-line tool: search messages and memos, read streams, post, and run the delegation lifecycle from a shell. The same binary serves those operations over the Model Context Protocol with `threa mcp serve`, so agent hosts like Claude Desktop can connect too.

## Install

The CLI lives in the open-source repo at [github.com/threahq/threa](https://github.com/threahq/threa) under `packages/cli`. It runs on [Bun](https://bun.sh) and is not yet published to a package registry, so you install it from a checkout:

*install from a checkout:*

```bash
git clone https://github.com/threahq/threa.git
cd threa && bun install
cd packages/cli && bun link   # puts a global `threa` on your PATH
```

Without `bun link` you can run it in place with `bun packages/cli/src/cli.ts`. After pulling a newer checkout the linked binary picks up the changes automatically.

## Configure

The tool binds one workspace with one API key. Create the key in **Settings → API keys** (see [Authentication](https://threa.io/developers/authentication.md)), then set environment variables or write a config file. Environment variables win when both exist.

*environment variables:*

```bash
export THREA_API_KEY=threa_uk_...
export THREA_WORKSPACE_ID=YOUR_WORKSPACE_ID
threa whoami
```

*~/.threa/config.json:*

```json
{
  "apiKey": "threa_uk_...",
  "workspaceId": "YOUR_WORKSPACE_ID",
  "output": "text"
}
```

A user key acts as you and shows a via-API badge on what it posts; a workspace key acts as its bot. The key's scopes decide which commands work. Start with `threa whoami` to confirm the binding.

## Commands

Commands group by resource, verb second. `threa --help` lists everything; each command documents its own flags with `--help`.

*the surface:*

```bash
threa whoami
threa search "release plan" --what messages|memos|attachments
threa streams list --type channel
threa streams read "#general" --members
threa conversations list --stream "#general"
threa conversations read conv_...
threa messages send "#general" "Hello from the CLI"
threa messages edit msg_... "Edited"
threa messages delete msg_...
threa messages find-by-metadata source=ci
threa memos get memo_...
threa attachments get att_... --url
threa labels list
threa labels add triage "#general"
threa users list
threa delegations list
threa delegations claim dlg_... --label "My machine"
threa delegations update dlg_... --note "tests passing"
threa delegations finish dlg_... --outcome complete --result - < report.md
threa mcp serve
```

Two commands worth calling out. `search` is the one retrieval entry point: `--what memos` searches the memory Threa builds from your conversations, and an empty memo query browses the most recent. `messages send` can open a conversation with `--new-conversation` and continue one with `--conversation conv_...`, which is how an external agent keeps a thread of work going across runs.

## Referring to things

Anywhere a command takes a stream you can pass the raw `stream_...` id or a `#channel-slug`. User slugs work as `@user-slug`. Lookups are exact and cached; a miss or an ambiguous match fails with an error that names the candidates and how to find the id.

## Output and exit codes

The CLI prints short human-readable tables by default, piped or not. `-o json` (or `--json`) switches to JSON and works anywhere in the command line, so `threa --json streams list | jq` and `threa streams list -o json` both behave the way you expect. An `"output": "json"` entry in the config file sets the default; an explicit flag wins. Errors go to stderr as a single JSON object with a `code`, a `message`, and often a `hint`. Exit codes: 0 for success, 1 for an API or reference error, 2 for a usage mistake.

## The MCP server

`threa mcp serve` exposes the same operations as 22 typed MCP tools over stdio, for hosts that speak MCP rather than a shell. Register it with Claude Code:

*register with Claude Code:*

```bash
claude mcp add threa \
  --env THREA_API_KEY=threa_uk_... \
  --env THREA_WORKSPACE_ID=YOUR_WORKSPACE_ID \
  -- bun /path/to/threa/packages/cli/src/cli.ts mcp serve
```

Other MCP hosts use their own registration format with the same command and environment. The tool names mirror the CLI surface: `search`, `read_stream`, `send_message`, `claim_delegation`, and so on.

## Using it from agents

For a coding agent with shell access the CLI is usually the better integration: no per-session registration, output that pipes into other tools, and no tool schemas taking up context. The repo ships an agent skill teaching effective use; `threa skill install` copies it to `~/.claude/skills/threa-cli/` for Claude Code.

The delegation commands close the loop described in [Recipes](https://threa.io/developers/recipes.md): a Threa persona hands work to your machine, your agent claims it, posts progress, and the finished result lands back in the stream where Threa's memory keeps it. Claim tokens persist in `~/.threa/state.json`, so a crashed run can pick its claim back up.
