AI-Friendly CLI Mode
Starting with Babel Obfuscator 11.7.0, the command line tool can emit a structured, machine-readable output stream that is well suited to CI pipelines, build orchestrators and AI/agent integrations.
The default text output of babel.exe is unchanged and remains fully backward
compatible: existing CI scripts and customer integrations require no changes.
The AI-friendly mode is enabled by three new global flags:
--format=text|json|ndjson— selects the output channel format--quiet(alias-q) — suppresses the logo banner and fails fast on interactive prompts--strict-exit— opts into semantic exit codes
When --format=json or --format=ndjson is selected, stdout carries the
structured stream and human-readable diagnostics are routed to stderr so the
two channels never interleave.
Flags
—format <format>
Selects the output format used on stdout. Allowed values:
| Value | Description |
|---|---|
text | Default. Legacy human-readable console output. No structural changes from previous releases. |
json | Buffered single JSON envelope written when the run completes (or on --help / --version). Best when stdout is captured to a file or piped into a JSON consumer. |
ndjson | Newline-delimited JSON. One event per line, flushed as it is produced. Best for streaming consumers, log shippers and live agents that need to react before the run terminates. |
Examples:
babel myapp.exe --format=json > result.json
babel myapp.exe --format=ndjson | jq -c 'select(.level=="error")'With —format=json or —format=ndjson the logo banner
is automatically suppressed regardless of —logo, so that the very
first byte on stdout is valid JSON.
—quiet (-q)
Suppresses the copyright/logo banner and changes the behavior of interactive
password prompts: instead of blocking on Console.In, Babel fails fast with
an explicit error. This makes --quiet safe for unattended invocations from
CI runners, container build steps and AI agents.
babel myapp.exe --quiet --keyfile mykey.pfx --keypwd env:KEY_PWD--quiet is independent from --format: it can be combined with the legacy
text output to keep human-readable logs without the banner.
—strict-exit
Opts the process into semantic exit codes. Without this flag, Babel preserves
the legacy contract where 0 means success and 1 means any failure.
| Exit code | Constant | Meaning |
|---|---|---|
0 | success | Run completed without errors. |
10 | invalidArguments | Command line could not be parsed or contained an invalid value (e.g. unknown --format). |
20 | inputNotFound | The primary assembly or another required input file was not found. |
30 | obfuscationFailure | Obfuscation failed at runtime (any unclassified obfuscator exception). |
40 | licensingFailure | Licensing check failed (missing, expired or unauthorized license). |
50 | keyOrSigningFailure | Strong-name signing or cryptographic key operation failed. |
The classification is also surfaced as exitReason in the JSON/NDJSON result
record (see Result envelope), even when --strict-exit is
not active, so consumers can distinguish failure categories independently from
the numeric exit code.
babel myapp.exe --strict-exit --format=json
echo "exit=$?"Schema: babel.cli.v1
All structured payloads conform to the versioned babel.cli.v1 schema.
Within a major schema version, additive changes (new fields, new event codes,
new exit reasons) are allowed; breaking changes will bump the schema name.
Event record
Every diagnostic emitted while a run is in progress is mapped to an event:
{
"ts": "2026-05-08T14:32:11.482Z",
"level": "info",
"code": "BAB1234",
"message": "Renaming phase, elapsed time 00.082s",
"data": { "phase": "renaming", "elapsedMs": 82 }
}| Field | Type | Notes |
|---|---|---|
ts | string (ISO-8601, UTC) | Timestamp at which the event was produced. |
level | debug | info | warning | error | Severity. |
code | string | null | Babel diagnostic code (e.g. BAB1234, W00013) when applicable. |
message | string | Human-readable message. |
data | object | null | Optional structured payload attached to the event. |
Result envelope
—format=json
A single JSON object is written to stdout when the run terminates. It contains
the run-level summary and all events buffered during the run:
{
"exitCode": 0,
"exitReason": "success",
"elapsedMs": 4218,
"warnings": 1,
"errors": 0,
"events": [
{ "ts": "2026-05-08T14:32:09.500Z", "level": "info", "code": null, "message": "Babel Obfuscator 11.7.0.0", "data": null },
{ "ts": "2026-05-08T14:32:11.482Z", "level": "info", "code": "BAB1234", "message": "Renaming phase ...", "data": { "phase": "renaming" } },
{ "ts": "2026-05-08T14:32:13.012Z", "level": "warning", "code": "W00013", "message": "Could not resolve ...", "data": null }
]
}—format=ndjson
Each event is flushed as soon as it is produced, on its own line. After the
last event, a final result line is appended (without an events array, since
events have already been streamed):
{"ts":"2026-05-08T14:32:09.500Z","level":"info","code":null,"message":"Babel Obfuscator 11.7.0.0","data":null}
{"ts":"2026-05-08T14:32:11.482Z","level":"info","code":"BAB1234","message":"Renaming phase ...","data":{"phase":"renaming"}}
{"ts":"2026-05-08T14:32:13.012Z","level":"warning","code":"W00013","message":"Could not resolve ...","data":null}
{"exitCode":0,"exitReason":"success","elapsedMs":4218,"warnings":1,"errors":0}| Field | Type | Notes |
|---|---|---|
exitCode | integer | Numeric exit code actually returned by the process (legacy or strict, depending on --strict-exit). |
exitReason | string | Stable classification token. Always reflects the semantic class even without --strict-exit. |
elapsedMs | integer | Total wall-clock duration in milliseconds. |
warnings | integer | Count of warning-level events. |
errors | integer | Count of error-level events. |
events | array | null | Present in json mode; omitted in ndjson (events are streamed as separate lines). |
Machine-readable —help
babel --help --format=json emits a complete description of every public
option, suitable for tooling that needs to introspect the CLI surface (shell
completions, AI agents, doc generators):
{
"version": "11.7.0.0",
"usage": "babel.exe <primary assembly source> [<other assemblies>...] [options]",
"options": [
{
"name": "controlflow",
"aliases": ["nocontrolflow", "no-controlflow", "control-flow", "no-control-flow", "i"],
"description": "Enable ([no]disable) MSIL control flow obfuscation",
"args": null,
"argRequired": false,
"argOptional": false,
"negatable": true,
"incremental": false,
"container": "scalar",
"type": "boolean",
"group": "- Code Obfuscation -",
"details": "Use this option to alter the method control flow ..."
}
]
}A scoped form is also supported. babel --help controlflow --format=json emits
the same envelope but containing only the controlflow option (and its
details resolved from the option resource bundle).
Hidden/internal options are never returned.
Machine-readable —version
babel --version --format=json emits runtime and platform information:
{
"product": "Babel Obfuscator",
"version": "11.7.0.0",
"fileVersion": "11.7.0.0",
"runtime": ".NET 8.0.11",
"platform": "win-x64"
}The platform field uses the .NET RuntimeIdentifier (RID) when running on
.NET 5+, and a synthetic <os>-<arch> string on legacy targets (net472-x64,
unix-x64, …).
Backward compatibility
- The default value of
--formatistext; the legacy textual output, exit codes and behavior are unchanged when no new flag is specified. - Without
--strict-exit, the process keeps returning0on success and1on any failure — existing CI gates that branch on$?keep working. --quietis independent and can be opted into without enabling structured output.
The structured output is also available through the MSBuild Task and the Babel.Obfuscator NuGet Package by passing the same flags via the standard property/argument plumbing.