Command-Line Interface

The Demeanor CLI is a cross-platform .NET global tool.

demeanor [options] <assembly>
demeanor <command> [options]
CommandDescription
(default)Obfuscate an assembly
deobfuscateDecode an obfuscated stack trace against an obfuscation report — see Decoding Stack Traces
inspectorSeparate tool — see Metadata Inspector
licenseDecode and display license key information

Obfuscate Command

Input / Output

OptionDescriptionDefault
<assembly>Path to the .NET assembly to obfuscate(required)
--out <dir>Output directory./Demeanor/
--dry-runRun the full pipeline (including the report) but write the obfuscated assembly to a discardable temp directory instead of --out. Preview the rename map and statistics without touching the real output. Mirrors the MCP tool's dry_run: true parameter.false

Scope

OptionDescriptionDefaultTier
--include-publicsAlso obfuscate public/protected symbols. Use for executables not referenced by other assemblies.offEnterprise
--include-depsAlso obfuscate co-located private dependency assemblies.offEnterprise

Naming

OptionDescriptionDefaultTier
--names <mode>Alpha (a, b, c) or UnicodeAlphaUnicode: Enterprise
--prefix <ns>Namespace prefix for obfuscated type names(none)Community
--rename <off|on|aggressive>How hard renaming is applied, weakest first. At aggressive, renamed members additionally share one name through privatescope and leave their type’s namespace, property and event metadata is stripped, compiler-emitted hints are removed, and default parameter values are stripped.aggressiveCommunity
--virtual-rename <off|on>Renaming of overrides of external methods — ToString, Equals, GetHashCode, interface implementations — through injected MethodImpl rows. The runtime dispatches correctly to the renamed methods; the decompiled output cannot be recompiled.onEnterprise
--enum-deletion <off|on>Deletion of enum member fields, so decompilers see an enum with no symbolic names or values. Reaches only enums that were renamed, and only those whose names the program is not observed to read. Sits inside --rename-enums: turning that off turns this off too.onEnterprise

Protection Features

All protection features are enabled by default at Enterprise tier. At Community tier, only renaming is active.

OptionDescriptionDefault
--string-encryption <off|on>Encryption of literal strings, with a decryptor injected into the assembly.on
--constant-encryption <off|on>Encryption of integer constants, replaced by inline arithmetic.on
--resource-encryption <off|on>Encryption of embedded resources. Applies to a raw resource this assembly reads by name; one whose only reader is another assembly is left in plaintext and named in a warning, because only the assembly that owns a resource holds the key. .resources files are never encrypted.on
--call-hiding <off|on>Relay methods that hide intra-assembly call targets, so a decompiler cannot resolve which method calls which.on
--proxy-threshold <N>Minimum method body size for call hiding, in bytes.16
--cfg <none|reorder|predicates|flatten>Control-flow obfuscation strength, weakest first.flatten
--hinder-reflection <off|on>Metadata constructs that make reflection-based tools less reliable, and suppression of ildasm disassembly.on
--anti-tamper <off|on>A module initializer that hashes the assembly file and terminates the application if it has been modified since the build. It verifies a file on disk, so under NativeAOT or single-file publishing there is nothing to verify and the check passes without doing anything.on
--anti-debug <off|on>Debugger detection scattered across method entry points; the application exits when a managed or native debugger attaches at runtime. NativeAOT-compatible.on
--baml <off|on>Patching of compiled XAML so it tracks renamed types and properties. Turning it off freezes everything the BAML references from renaming instead, so the unpatched XAML still resolves.on

Exclusions

OptionDescription
--exclude <name>Exclude a type or member by fully-qualified name. Repeatable.
--xr <pattern>Exclude by regex pattern. Repeatable.
--xa <assembly>Exclude an assembly (with --include-deps). Repeatable.
--add-assembly <name>Include a dynamically referenced assembly. Repeatable.

Renaming Categories

Each of these sits inside --rename: --rename off turns all of them off, whatever they are set to individually. A member-level [Obfuscation(Feature="rename", Exclude=false)] or [Obfuscation(Feature="rename-propagate", Exclude=false)] opts the marked symbol back in.

OptionDescriptionDefault
--rename-types <off|on>Type names. Enumerations sit inside this: turning it off turns off enum renaming, and with it enum member deletion.on
--rename-enums <off|on>Enumeration type names. Enum member deletion reaches only enums that were renamed, so turning this off turns that off too.on
--rename-methods <off|on>Method names.on
--rename-fields <off|on>Field names.on
--rename-properties <off|on>Property names. Data-bound and serialized properties are protected automatically whatever this is set to.on
--rename-events <off|on>Event names.on
--rename-parameters <off|on>Parameter names.on
--rename-resource-names <off|on>Managed resource names. A *.resources entry named after a type follows that type when it is renamed, which is what keeps a ResourceManager built from typeof(T) resolving. Turn it off when a lookup names the resource by a literal string instead.on
--no-serializableExclude serializable types and their serializable fields from renaming.(off)

Reporting & Incremental (Enterprise)

OptionDescription
--report [<path>]Generate a JSON report mapping original to obfuscated names. Optionally pass a filename; without one, the report is written next to the obfuscated assembly.
--prior-report <path>Prior report for incremental obfuscation
--satellite-assembliesUpdate resource names in satellite assemblies
--sa-cultures <culture>Restrict satellite processing to specific cultures

Project Rules & Decisions

OptionDescription
--project <dir>Project root holding .demeanor/ — your project rules and resolved decisions. Defaults to the nearest ancestor of the input assembly containing a .demeanor directory. The MSBuild integration always passes this explicitly.
--fail-on-pending-decisionsExit non-zero if a needs-decision rule matched a symbol nobody has resolved. Those symbols are left unrenamed and listed either way; this makes it a build failure. Off by default.

Strong Name Re-signing

OptionDescription
--keyfile <path>Strong name key file (.snk)
--keycontainer <name>Strong name key container

Output Control

OptionDescriptionDefault
--license <key>License key (also reads DEMEANOR_LICENSE env var)
--verboseVerbose obfuscation statisticsoff
--quietSuppress all non-error outputoff
--debugPreserve debug data (PDB)off
--no-logoSuppress the startup banneroff
--no-bootstrapSkip the first-run bootstrap. On its first invocation demeanor installs the companion inspector tool if it is not on PATH, writes the /obfuscate skill into ~/.claude/skills/, and registers itself as an MCP server in ~/.claude.json. The MSBuild integration passes this on every build, so compiling a project never changes anything outside it. DEMEANOR_NO_BOOTSTRAP=1 does the same.off
--versionPrint the version and exit
--help, -h, -?Print the full option list and exit. Every option is listed with the levels it accepts and its default, so this page and the tool cannot disagree about what exists. A subcommand takes it too — demeanor audit --help.

Metadata Inspector

The metadata inspector is a standalone CLI tool that installs alongside Demeanor. The Community edition (REPL, table dumps, IL disassembly, type drill-down, find, filter, dependencies) requires no license key. Enterprise capabilities (--query, --diff, --mcp, --json) unlock with a Demeanor Enterprise license key in DEMEANOR_LICENSE. See the full Inspector documentation.

inspector <assembly> [options]

audit Command

Pre-obfuscation risk analysis, and the right place to start on any codebase. It reads the compiled assembly, matches it against the built-in rules plus your project rules, and prints what obfuscates cleanly, what needs a decision from you, and what is worth knowing about — before a single byte changes.

demeanor audit MyApp.dll
demeanor audit MyApp.dll --json
OptionDescription
--jsonEmit the findings as JSON instead of a terminal table
--include-depsAlso audit co-located private dependency assemblies

Other Commands

CommandWhat it does
demeanor report <file>Read a generated JSON report in human-readable form. --section and --filter narrow the output. See Reports.
demeanor deobfuscate <file>Map an obfuscated stack trace back to original names, using --report. See Deobfuscating stack traces.
demeanor check <assembly>Report whether an assembly has already been obfuscated, and with which protections.
demeanor validate-exclusions <assembly>Show exactly which symbols your exclusion rules match, without obfuscating anything. See Exclusions.
demeanor init <assembly>Interactive setup wizard — wires MSBuild integration into the nearest project.
demeanor license <key>Decode and display license key information. Reads DEMEANOR_LICENSE when no argument is given.
demeanor --mcpStart the MCP server on stdio, so an MCP-capable assistant can drive the audit, obfuscation, reports and decisions. See Decisions & CI.