mitre-attack-cli
A fast, dependency-light Python CLI for MITRE ATT&CK. Built for coding agents
to invoke through the Bash tool: clean JSON on stdout, useful errors on stderr,
predictable exit codes. No MCP daemon required.
Why
Coding agents that need MITRE ATT&CK knowledge currently rely on MCP servers
(e.g. stoyky/mitre-attack-mcp,
MHaggis/mitre-attack-mcp). An MCP
brings infrastructure — a long-lived process, a transport, an MCP-aware host —
to what is fundamentally a read-only data lookup. This CLI is just a binary on
$PATH, easier to install (uvx mitre-attack-cli ...), easier to use in CI or
sandboxes, and equally agent-friendly: every command returns parseable JSON.
Quickstart
# One-shot via uvx (no install)
uvx mitre-attack-cli technique get T1059.001
# Or install globally
uv tool install mitre-attack-cli
mitre technique get T1059.001
First invocation downloads the ATT&CK Enterprise STIX bundle (~25–45 MB) into
~/.cache/mitre-attack-cli/. Subsequent calls are local.
Output
Default is compact JSON on stdout. Errors are JSON envelopes on stderr.
$ mitre technique get T1059.001
{"attack_id":"T1059.001","name":"PowerShell","tactics":["execution"],"platforms":["Windows"],"is_subtechnique":true}
$ mitre technique get T9999
# stdout: empty
# stderr:
{"error":"Not found: 'T9999' in enterprise@v19.0.","code":"NOT_FOUND","hint":"Try `mitre search T9999` or `mitre update`."}
# exit code: 3
Three formats:
| Flag | Behavior |
|---|---|
--format json (default) |
Compact JSON. Single line per object, single array for lists. |
--format jsonl |
Newline-delimited JSON. Best for piping large lists to jq. |
--pretty (or --format pretty) |
Markdown for objects, table for lists. For humans. |
Exit codes: 0 success · 2 invalid usage · 3 not found · 4 missing data · 5 network · 1 other.
Subcommands
mitre technique get | list | subtechniques | parent | groups-using | software-using
| mitigations | detections | procedures | tactics
mitre tactic get | list | techniques
mitre group get | list | techniques | software | campaigns
mitre software get | list | groups-using | techniques | campaigns
mitre mitigation get | list | techniques
mitre campaign get | list | groups | techniques | software
mitre data-source get | list | components | techniques
mitre search <query> [--type … --regex --limit N]
mitre update [--domain … --all-domains --force]
mitre info # diagnostic JSON: cache path, active version, etc.
Global flags must precede the subcommand:
--domain {enterprise|mobile|ics} # default: enterprise
--attack-version v19.0 # default; or MITRE_ATTACK_VERSION env
--data-path PATH # pre-downloaded STIX dir/file (or MITRE_ATTACK_DATA_PATH)
--format {json|jsonl|pretty} # default: json
--pretty # human-readable
--fields a,b,c # whitelisted field projection
--full # all fields
--include-revoked # include revoked/deprecated objects
--offline # fail rather than download
--quiet # suppress stderr progress logs
Examples
# Lookup
mitre --pretty technique get T1059.001
mitre group get APT28 # alias resolves to G0007
# Relationships
mitre technique groups-using T1059.001
mitre technique mitigations T1059.001
mitre group techniques G0007
# Listings + filtering + field selection
mitre technique list --tactic lateral-movement --platform Windows
mitre --fields attack_id,name --format jsonl technique list
# Search
mitre search "kerberoasting" --limit 5
mitre search '^Power' --regex --type technique
# Diagnostics
mitre info
Data: bring your own or let it download
Three resolution paths, in order:
--data-path PATH(orMITRE_ATTACK_DATA_PATHenv). Accepts:- A direct file (
/path/to/enterprise-attack.json) - A flat directory containing
enterprise-attack.json - A
{version}/{domain}-attack.jsonlayout (e.g.~/cache/v19.0/enterprise-attack.json). This matches common ETL cache layouts, so pre-downloaded bundles are reused without re-downloading.
- A direct file (
- Local cache at
~/.cache/mitre-attack-cli/{version}/{domain}-attack.json(honorsXDG_CACHE_HOME). - Download from
https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/{domain}-attack/{domain}-attack-{version}.jsonunless--offline.
Refresh is explicit via mitre update. The pinned default version is v19.0;
override with --attack-version v15.1 or MITRE_ATTACK_VERSION=v15.1. The
version is the reproducibility contract — same CLI version + same --attack-version
returns the same answers.
Only the domain you request is downloaded. --domain mobile will fetch
mobile-attack lazily; enterprise and ics aren't touched.
Performance
Coding agents fire many short-lived mitre ... invocations. Loading the full
ATT&CK STIX bundle through stix2 every time would cost ~2.4 s per call. To
avoid that, the CLI maintains a compiled snapshot cache next to each STIX
file:
~/.cache/mitre-attack-cli/v19.0/
├── enterprise-attack.json # raw STIX (downloaded on demand)
└── enterprise-attack.cache.msgpack # compiled snapshot — used by every warm run
| Run | Wall clock | What happens |
|---|---|---|
| First (cold) | ~25–30 s | mitreattack-python loads the STIX bundle once, builds a msgpack snapshot with every relationship pre-resolved. |
| Warm | ~150–300 ms | mitreattack-python is never imported. The hot path is typer + httpx + msgpack + pure-dict lookups. |
| Cache invalid | ~25–30 s | Rebuilt automatically when the STIX file's mtime/size changes, when the CLI version changes, or when you run mitre update --force. |
The snapshot uses msgpack — a binary, data-only format. It lives in your own
writable cache dir even when the STIX bundle itself comes from --data-path,
so a read-only data path remains read-only.
Install
uv tool install mitre-attack-cli # recommended
pipx install mitre-attack-cli # alternative
uvx mitre-attack-cli technique get T1059 # no install, one-shot
Bundled Claude Code skill
A drop-in Claude Code skill lives at
skill/ that teaches Claude to invoke this CLI whenever the user
asks anything ATT&CK-shaped — technique/group/mitigation IDs, threat-actor
names, TTPs, log-to-framework questions — instead of recalling stale ATT&CK
content from training data.
In a quick-smoke evaluation across three realistic prompts the skill
version cited only verified IDs (100% accuracy) versus 69% for the
baseline that relied on recall. See skill/SKILL.md
for what it teaches.
To activate it locally, symlink the folder into your ~/.claude/skills/:
ln -s "$(pwd)/skill" ~/.claude/skills/mitre-expert
Claude Code will pick it up on the next session.
Development
git clone https://github.com/nitzpo/mitre-attack-cli
cd mitre-attack-cli
uv sync --all-groups
uv run python tests/fixtures/build_tiny_bundle.py # build test fixture
uv run pytest # 114 tests, ~1s
uv run ruff check . && uv run ruff format --check .
The project uses uv for dependency management,
ruff for lint+format, ty
for type checking, and pytest for tests. CI runs on Python 3.11, 3.12, and 3.13 across
Ubuntu and macOS.
Architecture
Four layers, each independently testable:
cli/ # Typer commands, global flags, CliContext
└─ output/ # JSON/JSONL/markdown formatters, field projection, error envelope
└─ domain/ # ranked search, per-kind list/get/filter logic
└─ repo/ # AttackRepository wrapping mitreattack-python's MitreAttackData
└─ data/ # path resolution, httpx download with atomic-rename
The data layer is intentionally agnostic about ATT&CK schema specifics so future loaders (D3FEND, CAPEC, Atomic Red Team) can plug in without disturbing the CLI surface.
Differences vs the existing MCPs
- No daemon, no MCP server, no transport. Just a binary on
$PATH. - JSON-by-default for agents;
--prettyfor humans. - Lazy per-domain download — only fetches what you ask for, not all three.
- Pre-downloaded path interop — points at any existing STIX bundle including
versioned
{version}/{domain}-attack.jsonlayouts. - Stable error envelope with documented codes (NOT_FOUND, MISSING_DATA, …) and useful hints in every error.
License
MIT. See LICENSE.
Metadata
Release files for mitre-attack-cli 0.3.0
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 | |
|---|---|---|---|---|
| mitre_attack_cli-0.3.0.tar.gz | 32.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mitre_attack_cli-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 80.1 kB
Release files / mitre_attack_cli-0.3.0.tar.gz
| Download URL | mitre_attack_cli-0.3.0.tar.gz |
|---|---|
| Size | 32.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
022f8cb542df312961c5d75ee543e7cde77c039c6fc3e6395ea1485cfec52025
|
|
BLAKE2b-256 checksum How to use checksums |
d2c48141cee345a26e426098947b7b2fda9b1226d21516bd1e84ea29224304ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 1, 2026.
Transparency logRelease files / mitre_attack_cli-0.3.0-py3-none-any.whl
| Download URL | mitre_attack_cli-0.3.0-py3-none-any.whl |
|---|---|
| Size | 47.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
71e0945555788b79dbc8ecfe846026093b832bacb56d2bbfe92818fd4c9fd8e8
|
|
BLAKE2b-256 checksum How to use checksums |
a31595f3182ee66058137513acd5083b779e06df63a38d0f1f6db2e173c709f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 1, 2026.
Transparency logSecurity for mitre-attack-cli 0.3.0
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 mitre_attack_cli-0.3.0.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 Jun 1, 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.