Skip to main content

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:

  1. --data-path PATH (or MITRE_ATTACK_DATA_PATH env). Accepts:
    • A direct file (/path/to/enterprise-attack.json)
    • A flat directory containing enterprise-attack.json
    • A {version}/{domain}-attack.json layout (e.g. ~/cache/v19.0/enterprise-attack.json). This matches common ETL cache layouts, so pre-downloaded bundles are reused without re-downloading.
  2. Local cache at ~/.cache/mitre-attack-cli/{version}/{domain}-attack.json (honors XDG_CACHE_HOME).
  3. Download from https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/{domain}-attack/{domain}-attack-{version}.json unless --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; --pretty for 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.json layouts.
  • 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)

Source distribution for mitre-attack-cli 0.3.0
File Size Uploaded Provenance
mitre_attack_cli-0.3.0.tar.gz 32.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mitre-attack-cli 0.3.0
File Interpreter ABI Platform
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 log

Release 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 log

Security 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.

Select from 2 files

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 log

A 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.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page