> ## Documentation Index
> Fetch the complete documentation index at: https://docs.threadify.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Threadify CLI

> Sign in and manage contracts, entity profiles and threads from your terminal.

A standalone client for managing a running Threadify Engine. This repository has
its own Go module, tests, CI and release archives. It does not link or start the
Engine, PostgreSQL, Valkey or NATS.

Build with `make build`, or download a release archive for Apple Silicon macOS,
x86-64 Linux or x86-64 Windows. Verify it against `checksums.txt`, extract it and
put `threadify-cli` (`threadify-cli.exe` on Windows) on your PATH. Archives include
this guide and example contract/profile-type YAML. To use the shorter command on
a client machine, you can set `alias threadify=threadify-cli` in your shell.

## Connect and sign in

Use the same setup pattern as Fused CLI:

```sh theme={null}
threadify-cli config set api-url https://threadify.example.com
threadify-cli login
threadify-cli whoami
```

Or select the Engine during login:

```sh theme={null}
threadify-cli login --api-url https://threadify.example.com
# On a remote terminal, print the approval URL without opening a browser:
threadify-cli login --api-url https://threadify.example.com --no-browser
```

With no configured URL, `login` prompts for it. Use `--no-input` or `CI=true`
to require an explicit/configured URL. The browser opens the Engine's configured
Threadify UI. Sign in through Fused Registry or with an existing API key, then
click **Approve CLI login**. Approval is explicit even if already signed in.
The CLI generates its credential locally; neither the browser nor the Engine
receives that credential in plaintext. Enrollment expires after five minutes;
the resulting credential expires after 30 days. User status and source-key
revocation are checked on requests, and user role/status changes revoke existing
CLI logins. Service-account approval retains the service identity and permissions.

The Engine needs `registry.browser_origin` / `THREADIFY_BROWSER_ORIGIN` set to
the deployed UI origin, and that UI must connect to this Engine. Both need the
CLI-login update. The Engine doesn't bundle the UI. Email/SSO continues to use
Registry's existing identity flow.

```sh theme={null}
threadify-cli logout                # Revoke the saved managed CLI login
threadify-cli config get api-url
threadify-cli config show           # Key redacted
```

Logout targets the saved login at its saved Engine, regardless of ambient
URL/key overrides. It retains local state on a failed revocation so you can
retry. Manually configured API keys are not revoked by logout. Ambient
`THREADIFY_API_KEY` credentials remain available after logout.

## Automation and configuration

For scripts and service accounts, configure the URL and supply an API key:

```sh theme={null}
threadify-cli config set api-url https://threadify.example.com
export THREADIFY_API_KEY='<personal-or-service-account-key>'
threadify-cli contracts list
```

To save a key without putting it in command arguments, pipe it on stdin:

```sh theme={null}
printf '%s' "$THREADIFY_API_KEY" | threadify-cli config set --api-key-stdin
```

`threadify-cli config set api-key KEY` is also supported, but shell history can
record arguments. CLI config lives at `$XDG_CONFIG_HOME/threadify/cli.yaml`,
defaulting to `$HOME/.config/threadify/cli.yaml`. Override it with
`THREADIFY_CLI_CONFIG`. It is separate from the server's `config.yaml` and is
written atomically with file mode `0600` on Unix. Changing its API URL clears
the saved credential to avoid sending it to a different Engine.

URL precedence: `--api-url` (alias `--engine-url`), `THREADIFY_API_URL`,
`THREADIFY_ENGINE_URL`, saved config. Credential precedence: `--key`, saved
credential for that exact Engine URL, then `THREADIFY_API_KEY`. Global
connection flags can precede the command or follow it. Proxy path prefixes
are retained. HTTP redirects are rejected so credentials cannot be forwarded
to a different endpoint.

Resource commands print JSON to stdout and errors to stderr, exit nonzero on
failure, and accept `--timeout 30s`. Writes are not automatically retried.
An acknowledgement timeout can mean the operation succeeded; query its state
before retrying. Use `--file -` to read a document from stdin.

## Contracts

```sh theme={null}
threadify-cli contracts preview --file contract.yaml
threadify-cli contracts create --file contract.yaml
threadify-cli contracts list --search checkout --limit 25 --offset 0
threadify-cli contracts get --id CONTRACT_ID
threadify-cli contracts update --id CONTRACT_ID --file contract-v2.yaml
threadify-cli contracts versions --id CONTRACT_ID
threadify-cli contracts get --id CONTRACT_ID --version 1
threadify-cli contracts delete --id CONTRACT_ID --yes
```

Files can contain YAML or Gherkin accepted by the Engine. Update creates a
contract version according to Engine semantics. Deletion requires `--yes`.
Contract validation and permissions are enforced by the Engine.

## Entity profile types and profiles

Define `customers.yaml`:

```yaml theme={null}
name: Customers
type: [customer_id]
description: Customer workflows
```

```sh theme={null}
threadify-cli profile-types create --file customers.yaml
threadify-cli profile-types list
threadify-cli profiles create --type-id TYPE_ID --ref-value CUST-001 --name 'Jane Doe'
threadify-cli profiles list --type Customers
threadify-cli profiles get --type Customers --ref-value CUST-001
threadify-cli profiles get --id PROFILE_ID
threadify-cli profiles history --id PROFILE_ID
```

A profile type maps one to five reference keys to an entity category. This first
CLI version creates basic definitions; custom metric definitions, profile-type
updates and archiving remain in the Web API/UI. Unsupported fields are rejected.

Explicit profile creation uses an upsert: the same type/ref pair keeps its ID
and updates the name. It requires `entity_profile_type.update`; creating types
requires `entity_profile_type.create`. Engine quotas apply. Profiles also appear
automatically when thread references match a configured type; persistence is
asynchronous, so allow a short delay before querying newly derived profiles.

## Threads and references

```sh theme={null}
threadify-cli threads start --label 'Order ORD-1001' --contract checkout --role worker \
  --refs '{"order_id":"ORD-1001","customer_id":"CUST-001"}' --tags '["checkout"]'
threadify-cli threads get --id THREAD_ID
threadify-cli threads list --status active --limit 25 --offset 0
threadify-cli threads find --ref-key order_id --ref-value ORD-1001
threadify-cli threads add-refs --id THREAD_ID --refs '{"ticket_id":"T-123"}'
threadify-cli threads close --id THREAD_ID --status completed
threadify-cli threads verify --id THREAD_ID
```

`--contract` and `--role` are optional for contract-free threads. Finding by ref
returns every matching thread; refs are not unique thread identifiers. `close`
requires an explicit `completed` or `cancelled` status. `verify` prints integrity
results and exits nonzero when verification fails. Use SDKs or OTEL for event
instrumentation; the CLI manages and inspects resources.

For other Engine queries:

```sh theme={null}
threadify-cli graphql --file query.graphql --variables '{"id":"THREAD_ID"}'
threadify-cli help
```
