Threa Developers

    The threa command line.

    Search, read, post, and run delegations from a shell. The same binary is an MCP server, so agent hosts like Claude Desktop can connect too.

    Install

    The CLI is published to npm as @threahq/cli and needs Node.js 22.13 or newer. Install it globally to put threa on your PATH:

    Install
    npm install -g @threahq/cli

    Or run it without installing with npx -y @threahq/cli. The source is in the open-source repo at github.com/threahq/threa under packages/cli.

    Configure

    The tool binds one workspace with one API key. Create the key in Workspace Settings → API Keys (see Authentication), then set environment variables or write a config file. Environment variables win when both exist.

    Environment variables
    export THREA_API_KEY=threa_uk_...
    export THREA_WORKSPACE_ID=
    threa whoami
    ~/.threa/config.json
    {
      "apiKey": "threa_uk_...",
      "workspaceId": "",
      "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 endpoints
    threa whoami
    threa search "release plan" --what messages|memos|attachments
    threa streams list --type channel
    threa streams read "#general" --members
    threa streams archive stream_...
    threa streams unarchive stream_...
    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 list --stream "#general"
    threa memos get memo_...
    threa attachments list --stream "#general"
    threa attachments get att_... --url
    threa attachments download att_... ./out.png
    threa labels list
    threa labels add triage "#general"
    threa labels remove triage "#general"
    threa users list
    threa delegations list
    threa delegations get dlg_...
    threa delegations claim dlg_... --label "My machine"
    threa delegations update dlg_... --note "tests passing"
    threa delegations release dlg_...
    threa delegations finish dlg_... --outcome complete --result - < report.md
    threa delegations request-access dlg_...
    threa e2e unlock
    threa e2e status
    threa e2e lock
    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.

    Sealed streams

    An end-to-end-encrypted stream stores only ciphertext, so reading or posting needs the key that opens it. threa e2e unlock fetches the encrypted bundle holding your identity key, opens it with your passphrase and files the key on this machine. Type the passphrase at the prompt, where it is not echoed, or pipe it on stdin. Neither it nor the key leaves the machine.

    Open a sealed stream
    threa e2e unlock                         # prompts, then: unlocked uik_... into the OS keychain
    threa e2e status                         # holding uik_... (current)
    threa streams read stream_...            # bodies opened here, with that key
    threa messages send stream_... "on it"   # sealed here, then sent
    threa e2e lock                           # forget this machine's copy

    The key goes in the OS keychain by default, reached through the keychain's command-line tool so a reinstall does not lose it. --key-store file writes a 0600 file under ~/.threa/e2e-keys instead, and --key-dir moves that directory. Both also read from keyStore and keyDir in the config file, or THREA_E2E_KEY_STORE and THREA_E2E_KEY_DIR in the environment; a flag wins over both, which is how a runtime hands its own settings to the CLI it launches. Every command that touches a sealed stream takes the same two flags.

    threa e2e status compares the key this machine holds against the one the workspace has active for you. They differ after the web app rotates your key, which is when sealed streams stop opening here until you unlock again. threa e2e lock removes the copy on this machine and revokes nothing.

    Reads and writes fail loudly rather than degrade. Without a key, streams read says so instead of printing the placeholder the server stores, and messages send refuses rather than posting in the clear. A single message sealed to a key generation you were never wrapped to comes back with null content and its own reason, alone among the page. A sealed stream takes no --metadata and no conversation flags: both would travel in the clear, so they are refused instead of quietly dropped.

    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 24 typed MCP tools over stdio, for hosts that speak MCP rather than a shell. Register it with Claude Code:

    Register with Claude Code
    claude mcp add threa \
      --env THREA_API_KEY=threa_uk_... \
      --env THREA_WORKSPACE_ID= \
      -- threa mcp serve

    Sealed streams work over MCP the same as in the shell: read_stream opens bodies and send_message seals them, with the key threa e2e unlock filed on this machine. A workspace with no sealed streams never touches the key store.

    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, get_delegation, claim_delegation, release_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: a Threa persona hands work to your machine, your agent inspects it before claiming, posts progress or a manual heartbeat while working, and completes, fails, or releases the claim. Claim tokens persist in ~/.threa/state.json; successful completion or failure clears the stored token. A successful release clears only the matching stored token and preserves a replacement; a failed request leaves the token available for recovery.