Skip to main content

A fast Python CLI for MITRE ATT&CK. Designed for coding agents — clean JSON output over stdout, no MCP daemon required.

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mitre_attack_cli-0.3.0.tar.gz (32.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mitre_attack_cli-0.3.0-py3-none-any.whl (47.5 kB view details)

Uploaded Python 3

File details

Details for the file mitre_attack_cli-0.3.0.tar.gz.

File metadata

  • Download URL: mitre_attack_cli-0.3.0.tar.gz
  • Upload date:
  • Size: 32.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mitre_attack_cli-0.3.0.tar.gz
Algorithm Hash digest
SHA256 022f8cb542df312961c5d75ee543e7cde77c039c6fc3e6395ea1485cfec52025
MD5 3f1d88bc8b6cb412505efbab8bcc297e
BLAKE2b-256 d2c48141cee345a26e426098947b7b2fda9b1226d21516bd1e84ea29224304ec

See more details on using hashes here.

Provenance

The following attestation bundles were made for mitre_attack_cli-0.3.0.tar.gz:

Publisher: release.yml on nitzpo/mitre-attack-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mitre_attack_cli-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mitre_attack_cli-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 71e0945555788b79dbc8ecfe846026093b832bacb56d2bbfe92818fd4c9fd8e8
MD5 0334faea72f9c21711b6906106fa0a91
BLAKE2b-256 a31595f3182ee66058137513acd5083b779e06df63a38d0f1f6db2e173c709f4

See more details on using hashes here.

Provenance

The following attestation bundles were made for mitre_attack_cli-0.3.0-py3-none-any.whl:

Publisher: release.yml on nitzpo/mitre-attack-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page