threatcluster-cli
Command-line client for ThreatCluster. Installs the tc command.
pipx install threatcluster-cli
Getting started (3 steps)
1. Install
pipx install threatcluster-cli
2. Mint an agent key
Sign in at https://threatcluster.io → Settings → CLI → Mint key.
Tick the scopes you want, click mint, copy the tc_agent_… value.
Shown once — store it somewhere safe.
3. Log in
tc auth login
Paste the key when prompted. The CLI stores it in your OS keyring (Keychain on macOS, SecretService on Linux desktop, Credential Manager on Windows) and you're ready.
tc threats list --limit 5 | jq -r '.threats[].ai_title'
That's it.
Commands
Every command outputs JSON. Pipe through jq for reading. tc <command> --help
for full options.
tc auth — credentials
tc auth login # paste a refresh credential
tc auth status # show what's loaded
tc auth status -v # + storage backend, bearer jti, key id
tc auth logout # hard kill: revokes server-side AND clears local
tc auth logout --keep-remote # local clear only (e.g. moving the key)
tc search — smart router (entities + threats)
tc search "Volt Typhoon"
tc search lockbit --only entities # entity-only
tc search cisco --only threats --limit 20
tc threats — clusters and IOCs
tc threats list # latest trending
tc threats list --query ransomware --limit 20 # filter by keyword
tc threats list --watch --interval 30 # live feed (NDJSON)
tc threats get <cluster-id> # one cluster
tc threats iocs <cluster-id> # IOCs for one cluster
tc threats iocs <id> --types ip,domain # filter IOC types
tc threats stix <cluster-id> # STIX 2.1 export
tc iocs — bulk indicators
tc iocs feed # plaintext, one per line (last 30d, confirmed)
tc iocs feed --type ip # filter by type (all, ip, domain, hash, email)
tc iocs feed --type hash --hours 24 # last 24h hashes only
tc iocs export --format csv # for spreadsheets / SIEM (txt, csv, json)
tc iocs export --format json # structured
tc iocs export --type domain --format csv # domains, CSV
STIX 2.1 is per-cluster, not bulk:
tc threats stix <id>(or-from stdin).
tc entities — actors, malware, tools
tc entities search "lazarus" --type apt_group
tc entities get apt_group "Lazarus Group"
tc entities related apt_group "Lazarus Group" # co-occurring entities
tc entities trending # top by recent mentions
tc entities trending --window 7d
tc vulns — CVEs
tc vulns list # latest CVEs
tc vulns list --severity CRITICAL --limit 10
tc vulns list --watch --interval 120 # live CVE feed
tc vulns get CVE-2026-1234 # one CVE detail
tc darkweb — ransomware leak sites
tc darkweb ransomware victims # last 30 days
tc darkweb ransomware victims --group lockbit
tc darkweb ransomware victims --days 7 --limit 100
tc darkweb ransomware victims --watch # live feed
tc darkweb keyword-hits -k acme,'acme corp' # your suppliers/brands/clients
tc darkweb keyword-hits -k acme --watch
tc darkweb trends # weekly volume + group heat
tc feeds — your custom intel feeds
tc feeds list
tc feeds get <feed-id>
tc cluster — analyst pivots
tc cluster open <cluster-id> # opens in browser
tc cluster open <id> --no-browser # just print the URL
Accepts a full cluster UUID or its 8-char short_id (full UUIDs are shortened automatically). Resolves to
https://threatcluster.io/cluster/<short_id>.
Stdin chaining (-)
Any command that takes an id accepts - to read ids from stdin.
Compose freely:
# Top 5 trending clusters → IOCs for each
tc threats list --limit 5 \
| jq -r '.threats[].cluster_id' \
| tc threats iocs -
# CVE detail for everything new in 24h
tc vulns list --since 24h \
| jq -r '.cves[].cve_id' \
| tc vulns get -
# Open every LockBit-related cluster in the browser
tc threats list --query lockbit --limit 3 \
| jq -r '.threats[].cluster_id' \
| tc cluster open -
# STIX bundle for every "ransomware" cluster
tc threats list --query ransomware --limit 20 \
| jq -r '.threats[].cluster_id' \
| tc threats stix -
Use cases
SOC analyst — "what's worth my attention right now?"
# Trending ransomware clusters
tc threats list --query ransomware --limit 10 \
| jq -r '.threats[] | "[\(.threat_score)] \(.ai_title)"'
# CVEs newly added to CISA KEV-style catalogs
tc vulns list --severity CRITICAL --limit 10 \
| jq -r '.cves[] | "\(.cve_id) — \(.description[:120])"'
# What ransomware groups are most active this week?
tc entities trending --window 7d \
| jq -r '.trending.ransomware_group[:10][] | "\(.value) freq=\(.frequency)"'
Threat hunter — "is X in our intel?"
# Pivot from a malware family to clusters mentioning it
tc entities search "cobalt strike" --type malware \
| jq -r '.entities[].entity_value'
# All IOCs from clusters mentioning a tool you're hunting
tc threats list --query "cobalt strike" --limit 50 \
| jq -r '.threats[].cluster_id' \
| tc threats iocs - \
| jq -r '.iocs[]'
MSSP — "give me a feed for $CUSTOMER"
# Live ransomware victims into a Slack webhook
tc darkweb ransomware victims --watch --interval 60 \
| while read line; do
msg=$(echo "$line" | jq -r '"🔒 new victim: \(.group): \(.name)"')
curl -s -X POST -d "{\"text\":\"$msg\"}" "$SLACK_WEBHOOK_URL"
done
# Daily IOC blocklists (cron)
tc iocs feed --type ip > /etc/blocklists/tc-ips.txt
tc iocs feed --type domain > /etc/blocklists/tc-domains.txt
Engineer — "feed our SIEM"
# Bulk IOC export for SIEM ingest
tc iocs export --format csv > tc-iocs.csv
# Filter to only the IOCs from clusters scoring 80+
tc threats list --limit 100 \
| jq -r '.threats[] | select(.threat_score >= 80) | .cluster_id' \
| tc threats iocs - > high-confidence-iocs.json
AI agent — "scoped, budgeted access"
Hand a sub-agent a narrower bearer than your own. The server enforces it — the child cannot escalate scopes or exceed the budget.
TC_SCOPES=threats:read,iocs:read \
TC_SESSION_ID="$(uuidgen)" \
TC_MAX_REQUESTS=50 \
tc threats list --limit 5
Environment
| Var | Purpose |
|---|---|
TC_API_URL |
Override API base (default https://threatcluster.io) |
TC_REFRESH_TOKEN |
Refresh credential (overrides keyring + file). For CI only. |
TC_SCOPES |
Comma-separated subset of refresh scopes for the bearer. |
TC_SESSION_ID |
Session id for per-session request budgeting. |
TC_MAX_REQUESTS |
Cap requests per session; subsequent ones get 429. |
TC_PROPAGATE_AUTH |
Set to 1 to propagate auth env to subprocesses. |
TC_DEBUG |
Set to 1 for verbose stderr (auth headers redacted). |
Shell completion
tc --install-completion bash # or zsh, fish
exec $SHELL # restart your shell
tc thr<TAB> # → tc threats
Security notes
- Refresh credential is never sent on argv (
--api-keyflag is rejected). - Bearer JWTs (15 min ttl) are minted on demand, cached in memory only.
- The CLI refuses plaintext
http://URLs unless the host is127.0.0.1/localhost. - Auth env vars are scrubbed from subprocess environments unless
TC_PROPAGATE_AUTH=1. - Credential file is mode 0600 + uid-checked; loose perms are refused.
See the docs for the full reference, and Agent keys & scopes for the security model in detail.
Release flow
See PUBLISHING.md.
Metadata
Release files for threatcluster-cli 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| threatcluster_cli-0.1.2.tar.gz | 20.4 kB | With provenance | Details for threatcluster_cli-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| threatcluster_cli-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for threatcluster_cli-0.1.2-py3-none-any.whl |
Total release size: 42.9 kB
Release files / threatcluster_cli-0.1.2.tar.gz
| Download URL | threatcluster_cli-0.1.2.tar.gz |
|---|---|
| Size | 20.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f9e0fba42aad9b9a8f1d05177d957b894f741d4f2fdff1027985df51ccba490a
|
|
BLAKE2b-256 checksum How to use checksums |
e0ce0d3dfc0aaaaa26f51786558a3d8c42159eeb3e218566a4790637c84158e7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.
Transparency logRelease files / threatcluster_cli-0.1.2-py3-none-any.whl
| Download URL | threatcluster_cli-0.1.2-py3-none-any.whl |
|---|---|
| Size | 22.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ceb997d2df6c10b5c90676d3ccddb5b8787810533d4b80371177e83182507db6
|
|
BLAKE2b-256 checksum How to use checksums |
336b0c3a35aa6568e45645755e1721f51591ad36e4f87dda9f46f4412b01a5be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.
Transparency logSecurity for threatcluster-cli 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for threatcluster_cli-0.1.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.