A command-line tool for constructing, interrogating, and modifying Microsoft Threat Modeling Tool (.tm7) files — designed for use by humans and AI assistants alike.
- Open & inspect — summarize models, list entities and data flows
- Create & modify — add/remove entities and flows, create new models from templates
- Import — convert Graphviz DOT diagrams into
.tm7format - Render — visualize threat model diagrams directly in the terminal with Unicode box-drawing and ANSI colors
- Round-trip fidelity — uses
DataContractSerializerwith DTO classes matching the TM7 XML format
Self-contained, single-file NativeAOT binaries are published for every release — no .NET runtime required. Download the archive for your platform from the latest release:
| Platform | Asset |
|---|---|
| Windows x64 | tm7-win-x64.zip |
| Windows arm64 | tm7-win-arm64.zip |
| Linux x64 | tm7-linux-x64.tar.gz |
| Linux arm64 | tm7-linux-arm64.tar.gz |
| macOS x64 (Intel) | tm7-osx-x64.tar.gz |
| macOS arm64 (Apple Silicon) | tm7-osx-arm64.tar.gz |
Each release also includes checksums.txt (SHA-256) and release-metadata.json
for verification.
Platform notes
- Linux binaries are built against glibc 2.39 (Ubuntu 24.04), so they require a glibc-based distro of that vintage or newer (e.g. Ubuntu 24.04+, Debian 13+, RHEL/Rocky 10+, Fedora 40+). They are not built for musl/Alpine.
- macOS binaries are not code-signed or notarized. If you download via a browser, Gatekeeper quarantines the file; clear it with
xattr -d com.apple.quarantine ./tm7(downloading withcurl, as above, avoids this).
Requires .NET 10 SDK.
# Clone and build
git clone <repo-url>
cd tm7cli
dotnet build
# Run directly
dotnet run --project src/Tm7.Cli -- <command>
# Or install as a global tool
dotnet pack
dotnet tool install --global --add-source artifacts/package/release tm7
tm7 --help# Inspect a model
tm7 open model.tm7
tm7 list entities model.tm7
tm7 list flows model.tm7
# Create a new model from the bundled Azure template (use --template to override)
tm7 new mymodel.tm7 --name "My Threat Model"
# Add entities
tm7 add entity mymodel.tm7 \
--name "Web API" \
--type-id SE.P.TMCore.AzureAppServiceWebApp \
--generic-type-id GE.P \
--left 400 --top 200
# Add a data flow (use GUIDs from 'list entities')
tm7 add flow mymodel.tm7 \
--name "HTTPS Request" \
--source <source-guid> \
--target <target-guid>
# Render the diagram in terminal
tm7 render mymodel.tm7
# Import from Graphviz DOT (uses the bundled template by default)
tm7 import dot architecture.dot --output model.tm7
# Show all usage examples
tm7 examples| Command | Description |
|---|---|
open <file> |
Show model summary (surfaces, entity/flow counts, threats) |
list entities <file> |
List all entities with type, position, surface |
list flows <file> |
List all data flows with source/target |
add entity <file> |
Add an entity (process, external interactor, data store, boundary) |
add flow <file> |
Add a data flow between two entities |
remove entity <file> |
Remove an entity and its connected flows |
remove flow <file> |
Remove a data flow |
new <file> |
Create an empty model from a template |
import dot <dotfile> |
Import a Graphviz DOT file into tm7 format |
render <file> |
Render the diagram in the terminal |
examples |
Show usage examples and entity type reference |
| GenericTypeId | Shape | Example TypeIds |
|---|---|---|
GE.P |
╭─╮ Process (ellipse) | SE.P.TMCore.AzureAppServiceWebApp, SE.P.TMCore.AzureAD, SE.P.TMCore.Host |
GE.EI |
┌─┐ External Interactor (rectangle) | SE.EI.TMCore.Browser, GE.EI |
GE.DS |
═══ Data Store (parallel lines) | SE.DS.TMCore.AzureStorage, SE.DS.TMCore.AzureSQLDB, SE.DS.TMCore.AzureKeyVault |
GE.TB.B |
┏━┓ Trust Boundary (bold border) | SE.TB.TMCore.AzureTrustBoundary, GE.TB.B |
The render command produces a Unicode diagram with ANSI color support:
- Processes: cyan rounded boxes (
╭╮╰╯) - External Interactors: yellow sharp boxes (
┌┐└┘) - Data Stores: green parallel lines (
═══) - Trust Boundaries: red bold borders (
┏┓┗┛) - Data Flows: gray lines with colored arrows (
►◄▼▲) - Annotations: dim gray text
Options: --width, --height, --plain (no ANSI codes, for piping/AI consumption).
- Serialization: Uses
DataContractSerializerwith an explicit known-types list — this is the only reliable way to produce valid.tm7files - DTOs: The
Tm7Model/directory contains DataContract DTO classes derived from the public.tm7XML format. They use explicit[DataContract(Namespace = "...")]attributes to match the XML namespaces thatDataContractSerializerexpects. - Rendering: Uses Hex1b
Surfaceas a character-cell canvas, with custom ANSI output to handle the unwritten-cell marker (\uE000)
Releases are produced by the Release workflow,
which builds self-contained NativeAOT binaries for all six supported runtime
identifiers (win-x64, win-arm64, linux-x64, linux-arm64, osx-x64,
osx-arm64) on native runners, smoke-tests each binary, and publishes a GitHub
Release with the archives plus checksums.txt and release-metadata.json.
The easiest way to cut one is the helper script — it computes the next version, shows you the plan, and pushes the tag after you confirm:
./scripts/release.ps1 # next patch (v0.3.1 -> v0.3.2)
./scripts/release.ps1 -Minor # next minor (v0.3.1 -> v0.4.0)
./scripts/release.ps1 -Major # next major (v0.3.1 -> 1.0.0)
./scripts/release.ps1 0.5.0 # an explicit version
./scripts/release.ps1 -WhatIf # preview without tagging anythingUnder the hood this just creates and pushes a version tag, so you can also do it
by hand (git tag v0.1.0 && git push origin v0.1.0) or run the workflow manually
from the Actions tab (on the main branch) and supply the version. The version
baked into the binaries comes from the tag (the leading v is stripped); pre-release
tags such as v0.1.0-rc.1 are published as GitHub pre-releases.
If a build leg fails, the tag exists but no Release is published — fix the cause and use Actions → the failed run → Re-run failed jobs. Re-running is idempotent: the release job updates the existing tag's assets and metadata in place.
