cadmpeg
cadmpeg inspects native CAD containers, dumps supported model data into
CADIR, checks and compares CADIR models, and exports CADIR, STEP Part 21
(AP203, AP214, or AP242), and bounded IGES 5.1, 5.2, or 5.3 Fixed ASCII. It also writes
supported .FCStd, .f3d, .sldprt, and .3dm models.
Native codecs transfer different subsets of geometry, topology, design intent, presentation, and metadata. Check format support before relying on a conversion path.
Install
Install with Homebrew:
Or use the installer for macOS and Linux:
|
Or install from crates.io:
Convert a model
convert decodes the input, checks the resulting CADIR, then exports it:
--to FORMAT[:DIALECT]
One flag names the output format and, when you want to say so, the dialect of
it. --to is a spelling of -f/--format; the three are the same flag.
--to rhino:archive-80names both halves. The format half may use any spelling--toaccepts, so--to 3dm:archive-80is the same request.--to stepnames the format alone. It says which kind of file to write, not which dialect of it, so a same-format conversion still preserves the input's dialect.--to 5.1names a dialect of the format the output path implies. Each format's own short vocabulary works here:5.1for IGES,60for Rhino,ap242e3for STEP. A bare value is read as a format first, and no dialect spelling collides with a format name.
Omitting --to is the identity default: converting a file to its own format
keeps the dialect it already is, and converting across formats writes the
target format's default. cadmpeg dialects FORMAT lists every id, and
cadmpeg inspect FILE prints the id of the file in front of you — the same
string you would pass to --to.
The CLI inspect path calls cadmpeg_registry::resolve_and_inspect_with.
cadmpeg_registry::identify is the candidate-reporting entry point: it retains
equal-confidence candidates instead of resolving them to one source.
A dialect the writer cannot produce is refused by name, with the whole catalog of what it can produce, rather than silently rewritten. For IGES this covers Compressed ASCII and Binary sources: converting one back to IGES replays the original bytes, which the writer could not synthesize, and asking for a different target is a synthesis request that says so.
The output extension selects step, iges, fcstd, f3d, sldprt, rhino, or
cadir. Pass --to when the filename does not identify the format, or when a
text format (cadir, step) goes to standard output:
Binary formats (fcstd, f3d, sldprt, rhino) are refused on standard
output, because that spelling is nearly always --input-format (alias
--from) written as --format; pass -o FILE or, for a deliberate binary
pipe, --binary-stdout.
Conversion stops before export if the check finds errors. It also refuses
geometry output when decoding transfers no geometry. --allow-errors and
--allow-empty write the current result anyway. They leave model data
unchanged.
Inspect, dump, and check
Inspect a native container without decoding its model:
Dump a native file to canonical CADIR JSON:
Without --output, artifact-producing commands write only the artifact to
standard output. Diagnostics and loss summaries go to standard error, so
redirection remains safe.
Check either CADIR or a supported native file:
--container-only stops native decoding before geometry. It is useful for
container diagnostics and normally requires --allow-empty when followed by a
geometry export.
Read raw bytes
cadmpeg inspect also carries byte tools that work on any file, decoded or
not. Every offset and length argument accepts 0x hexadecimal or decimal, and
_ between digits.
--endian le and --endian be select the byte order for read; little-endian is the
default. read --count N walks a record array, stepping --stride bytes and
defaulting to the scalar width.
Common alternative spellings are accepted: --length for --len, --min-len
and --min-length for --min, --start for --offset, --step for
--stride, -n for --count, and --input FILE for the positional file on
single-input tools. cadmpeg inspect bytes <tool> runs the same tool as
cadmpeg inspect <tool>. find FILE NEEDLE --encoding hex|ascii|utf16le
selects the encoding of the positional pattern. Text or hex values on
read --type produce an error that names the corresponding tool. find stops at --max hits and says so,
--max 0 reports every hit, and --context N dumps N bytes around each
hit.
--layout is a comma-separated record spec with no implicit alignment:
| Field | Meaning |
|---|---|
u8, i8 |
One byte. A byte-order suffix is rejected. |
u16le, i32be, f64le, … |
A wide scalar. The le or be suffix is required. |
bytesN |
N raw bytes, printed as hexadecimal. |
padN |
N bytes skipped and not printed. Takes no name. |
Every field except padN accepts an optional :name; unnamed fields are called
f<index>. struct --count N decodes N consecutive records and reports an
error rather than a partial record when the run passes end of file.
inspect container lists ZIP or CFB members. ZIP columns are
header/data/packed/unpacked/method/crc32/name, so a hex dump of an entry
follows directly. CFB columns are id/kind/size/alloc/path; size and alloc
are empty for storages. --json prints the same listing as versioned JSON
with raw names and container_kind zip or cfb. Names in the table are
single-quoted because Fusion .f3d entry names hold [ and ], which a
shell reads as a glob. inspect extract FILE MEMBER writes one ZIP
entry's decompressed, CRC-checked bytes, or one CFB stream, to -o FILE
or standard output; the member name matches byte-exactly, brackets
included, where unzip reads it as a glob and fails. Other container
families are listed by cadmpeg inspect FILE through their codec.
inspect cmp compares byte n of one file with byte n of the other. It
reports the first differing offset, the differing byte count, and the differing
spans. --gap merges two spans separated by that many equal bytes or fewer.
It exits 1 if the files are not identical, including length-only (Unix cmp
contract). cadmpeg diff compares decoded models.
A file whose name is also a subcommand name, such as hex, is read as the
subcommand. Write ./hex for such a file.
Compare models
diff compares two decoded models structurally:
It reports unit, tolerance, arena membership, and modified entity fields.
Exit status 1 indicates a difference.
Inputs and outputs
The built-in codecs recognize .f3d, .FCStd, .ipt, .iam, .sldprt,
.3dm, .CATPart, IGES, STEP, bare ASM/ACIS .sat/.smt/.smb/.sab
streams, and the NX and Creo .prt layouts by content. Commands that load
models also accept CADIR JSON. Use --input-format (alias --from) to bypass
detection for an ambiguous or extensionless input. Every command that takes
one input file also accepts --input FILE as a spelling of the positional;
the two-file commands (diff, inspect cmp, inspect extract) take their
inputs positionally only.
Output formats are:
cadirfor canonical CADIR JSON;jsonis an alias.stepfor ISO 10303-21 Part 21;igesfor IGES fixed ASCII.fcstd,f3d,rhino, andsldprtfor the native writers' supported subsets.
cadmpeg formats lists what this build reads and writes. cadmpeg dialects [FORMAT] lists the dialects of each format: the id, how well cadmpeg reads it,
whether anything writes it, and which of them are write targets of this build's
encoders.
Native writers use retained source data where the format requires it, and reject unsupported edits. The format support page defines each reader and writer's current semantic coverage.
File output is atomic. cadmpeg refuses to replace its input or an existing
output unless --force is present. An explicit --to format takes precedence
over a conflicting output extension and emits a warning.
Losses and machine-readable reports
Native decoding prints whether geometry transferred and lists known losses.
STEP export reports omitted, reduced, or normalized content. To save a
versioned JSON record of a dump or convert operation, pass
--report:
The command report contains decode, check, and export sections when those
stages ran. inspect --json, inspect container --json, check --json,
and diff --json write versioned JSON directly to standard output.
inspect, check, and diff produce no artifact beside the report, so they
also accept -o and --output for the report path. Every command refuses to
replace an existing report or artifact unless --force is present. Check
findings live under .check_report.findings; cadmpeg check prints the
error count and exits 1 on the same error and blocking findings.
Query reports
query projects one named view from a JSON artifact without jq: it reads a
command report, a decoded CADIR document, or a <stem>.fidelity.json decode
sidecar, detects which one it was given, and prints the view. Aggregate views
print tab-separated rows with a header; item, graph, and join print
pretty-printed JSON records.
counts on a CADIR document lists arena lengths for model and every
native.<codec> namespace; on a check report it lists entity_counts.
item uses the same dotted arena names as query counts --json
(model.<arena> or native.<codec>.<arena>; a bare name means
model.<arena>). It matches the JSON-string id field exactly or as a unique
suffix, accepts several IDs in one call, and with no ID prints the first
record (--head N for the first N). --fields a,b.c projects those paths as TSV
(projection only — no --where). graph starts from the same FILE ARENA
[ID...] selection and walks identity references: a string is an edge when it
equals another record's id in this document. --hops N (default 1) is the
maximum edge length; 0 emits only the starts. --follow PATH,... keeps
those field paths only (exact match). --reverse walks incoming references.
--max-paths (default 10000) truncates with a note on standard error and
still exits 0. join matches two arenas on required --left-key and
--right-key paths (matched inner join, unmatched left anti-join, all
grouped rights). --right-file joins two documents by key value only. schema
with no file prints the IR's compile-time record type
for a model arena — every field, whether it is required, and every variant of
a tagged union — or, bare, every model arena and its element type (sidecar
prints the decode-sidecar shape). schema FILE ARENA infers native (and
other) arena fields from the records: each dotted path's presence, JSON type,
an example, and a relation column (id for the record identity, ref /
refs for fields whose values resolve to a record id in this document or
match the identity grammar). Use relation=ref|refs paths as graph
--follow fields and as join keys. An unknown arena name lists every
addressable arena and its entry count. Which arenas a document actually has
also comes from counts.
fidelity lists a decode sidecar's retained source records (the extraction
address space) and, with --stream NAME, reassembles that stream's retained
bytes byte-exactly into -o FILE — refusing gapped extents and extent-only
retention loudly rather than splicing or writing empty output.
An empty or not-run section is not an error: the header prints, a
note goes to standard error, and the exit status stays 0. A view the
artifact kind can never carry exits 2 and names the command that produces
the right artifact. --json wraps the projection in the versioned envelope,
and - reads standard input.
Exit status
Verdict commands exit 1 on a negative verdict. Other commands do not use 1. Exit 2 is operational on every command.
0: the requested operation completed; a verdict command had a positive verdict when it ran.1: negative verdict. Verdict commands areconvert(refused write),check(failed check),diff(models differ), andinspect cmp(files differ).inspect cmpexits 1 if the files are not identical, including length-only (Unix cmp contract).2: operational error, including invalid arguments, unrecognized input, decode or encode failure, and file-system errors.
Non-verdict commands are dump, query, and inspect (except inspect cmp).
Run cadmpeg help <command> for the complete options of a command.
More documentation
Requires Rust 1.88 or later. Licensed under Apache-2.0.