Metadata Inspector
Browse and explore .NET assembly metadata. Standalone command-line tool. The Community edition is free and fully featured for everyday inspection; the Enterprise edition adds natural-language queries, side-by-side assembly diff, an MCP server for AI-driven inspection, and structured JSON output — unlocked by your existing Demeanor Enterprise license key.
Overview
The Metadata Inspector is a standalone command-line tool for examining .NET assembly metadata. It ships as a separate global tool (WiseOwl.Inspector, command inspector) and runs without any license key for its Community feature set. Installing WiseOwl.Demeanor auto-installs Inspector on first use; you can also install it directly without ever buying Demeanor. It reads any .NET assembly (Framework, Core, .NET 5–10) and lets you explore its types, methods, fields, properties, events, custom attributes, IL code, and all 31 ECMA-335 metadata tables.
Some Inspector capabilities (--query, --diff, --mcp, --json) require a Demeanor Enterprise license key supplied via the DEMEANOR_LICENSE environment variable. The same key unlocks both Demeanor Enterprise and Inspector Enterprise — there is no separate Inspector license. See Community vs Enterprise below for the full split.
Use it to:
- Understand the structure of any .NET assembly
- Verify what an obfuscator preserved or renamed
- Compare assemblies before and after obfuscation Enterprise
- Audit assemblies for specific attributes, interfaces, or patterns
- Decode custom attribute blobs without writing code
Community vs Enterprise
Inspector ships in two editions. Community is the default state when no license key is present — free, fully featured for everyday inspection, no time limit, commercial use permitted. Enterprise unlocks at runtime when the DEMEANOR_LICENSE environment variable is set to a valid Demeanor Enterprise key. The same key unlocks Demeanor Enterprise and Inspector Enterprise; there is no separate Inspector license to buy.
| Capability | Community | Enterprise |
|---|---|---|
Interactive REPL (inspector MyApp.dll) | ✓ | ✓ |
One-shot summary (--summary) | ✓ | ✓ |
Per-table dump for all 31 ECMA-335 metadata tables (--table <name>) | ✓ | ✓ |
All metadata tables in one shot (--metadata) | ✓ | ✓ |
Unified type view (--type), composable with --method and --il | ✓ | ✓ |
Full IL disassembly (--il) | ✓ | ✓ |
Cross-table find by name pattern (find in REPL) | ✓ | ✓ |
Filter rows scoped or unscoped (--filter, --public-only) | ✓ | ✓ |
Dependencies view (--dependencies) | ✓ | ✓ |
Natural-language metadata queries (--query) — "show methods returning string", "which types implement IDisposable", "how many fields" | — | ✓ |
Side-by-side assembly diff (--diff) — added / removed / renamed types and members | — | ✓ |
MCP server (--mcp) — drive Inspector from Claude Code, Cursor, Windsurf, Continue.dev, or any MCP-capable assistant | — | ✓ |
Structured JSON output (--json) — for tooling and CI integration | — | ✓ |
To unlock Enterprise capabilities, set DEMEANOR_LICENSE to your Enterprise key on the machine where Inspector runs:
setx DEMEANOR_LICENSE "your-enterprise-key" # Windows (persistent)
export DEMEANOR_LICENSE="your-enterprise-key" # Linux / macOS Close and reopen your terminal afterward so the new variable is picked up. If the variable is unset or invalid, Inspector continues to run with Community features and will tell you so on stderr if you try an Enterprise-only flag. See pricing for Enterprise license details.
Installation
Installing Demeanor auto-installs the inspector the first time you run demeanor, so inspector is already on your PATH if you followed Getting Started. To install the inspector on its own (no Demeanor required):
dotnet tool install -g WiseOwl.Inspector Then run:
inspector MyApp.dll Two Ways to Use It
One-shot mode (CLI flags)
Pass flags to get a specific view and exit:
inspector MyApp.dll --summary
inspector MyApp.dll --table typedef
inspector MyApp.dll --type WeatherForecast
inspector MyApp.dll --query "show public methods returning string" Interactive mode (REPL)
Launch without flags to enter the interactive prompt. Type queries directly:
inspector MyApp.dll
inspector> summary
inspector> show public methods
inspector> which types implement IDisposable
inspector> describe OrderService
inspector> quit Query Language Enterprise
The inspector understands structured English queries beyond the Community-tier summary and find commands. You don't need to memorize command syntax — describe what you want to see. The inspector shows how it interpreted your query before displaying results. The natural-language query engine documented below is part of the Enterprise edition (one-shot via --query / -q, or interactively in the REPL when a valid DEMEANOR_LICENSE is set).
Showing items
| Query | What it does |
|---|---|
summary | Assembly identity, version, and row counts |
show types | List all types |
show methods | List all methods |
show fields | List all fields |
show properties | List all properties |
show events | List all events |
show resources | List embedded resources |
show assembly references | List referenced assemblies |
show custom attributes | List custom attributes |
show interfaces | List interface types |
Filtering by accessibility
| Query | What it does |
|---|---|
show public types | Only public types |
show public methods | Only public methods |
show internal types | Only internal types |
show private methods | Only private methods |
Filtering by signature
| Query | What it does |
|---|---|
show methods returning string | Methods whose return type contains "string" |
show methods returning void | Methods returning void |
show methods that take int | Methods with a parameter type containing "int" |
show static methods | Static methods only |
show virtual methods | Virtual methods only |
show abstract methods | Abstract methods only |
Filtering by owner / location
| Query | What it does |
|---|---|
show methods on Calculator | Methods declared on types matching "Calculator" |
show fields on OrderService | Fields on types matching "OrderService" |
types in namespace MyApp.Models | Types in a specific namespace |
Filtering by type hierarchy
| Query | What it does |
|---|---|
which types implement IDisposable | Types implementing a specific interface |
types that inherit from Exception | Types with a specific base class |
types with attribute Serializable | Types decorated with a specific attribute |
show generic types | Types with generic parameters |
show sealed types | Sealed types |
Counting
| Query | What it does |
|---|---|
how many types | Count of types |
how many methods | Count of methods |
how many fields | Count of fields |
how many properties | Count of properties |
count resources | Count of embedded resources |
Detail views
| Query | What it does |
|---|---|
describe OrderService | Full type detail: base type, interfaces, fields, methods, properties |
show type Calculator | Same as describe |
what is WeatherForecast | Same as describe |
Searching
| Query | What it does |
|---|---|
find Calculator | Search all types, methods, fields, and properties for "Calculator" |
find Dispose | Search across all tables for "Dispose" |
How matching works
All name matching is case-insensitive and uses substring containment by default. show methods on Order matches OrderService, OrderRepository, and ReorderQueue.
Driving the inspector from an AI assistant Enterprise
This section is optional. The inspector’s primary interface is the CLI documented above — the REPL and one-shot commands cover every capability, and the structured English query language needs no AI to work.
If you already use an MCP-capable assistant (Claude Code, Claude Desktop, Cursor, Windsurf, Continue.dev, or any other MCP client), the inspector’s built-in MCP server (--mcp) lets the assistant answer the same questions in conversation on your behalf. The inspector auto-registers with detected MCP clients the first time you install it — nothing to configure, no separate API key. Everything runs locally over stdio; no assembly data leaves your machine. The MCP surface exposes 9 tools (inspect_query, inspect_summary, inspect_types, inspect_methods, inspect_fields, inspect_properties, inspect_attributes, inspect_find, inspect_diff) the assistant can call.
The MCP server requires a valid DEMEANOR_LICENSE Enterprise key. Requires your own Claude subscription — not included with Demeanor. Any other MCP-capable assistant works the same way with its own subscription.
Ask it anything
IHostedService?See the conversational walkthrough for an end-to-end conversation where the assistant drives both the inspector and Demeanor’s audit surface in the same session.
One-Shot CLI Options
All options work from the command line for scripting and CI/CD integration.
Options marked Enterprise require a valid DEMEANOR_LICENSE environment variable. Unmarked options work in the Community edition with no key.
Display options
| Option | Description |
|---|---|
--summary | Assembly identity and statistics |
--metadata | Display all metadata tables |
--table <name> | Display specific table(s). Repeatable. |
--il | IL disassembly for all methods |
--dependencies | Assembly, type, and member references |
--type <pattern> | Unified type view: fields, methods, properties, events, attributes, MethodImpls |
--diff <other.dll> Enterprise | Compare against another assembly |
--query <text>, -q Enterprise | Natural language query (one-shot) |
Filters and formatting
| Option | Description |
|---|---|
--filter <text> | Filter rows by name substring. Supports scoped queries: type=Foo, parent=Bar, sig=string |
--public-only | Restrict output to public symbols |
--json Enterprise | Output structured JSON for tooling. Forces one-shot mode. Top-level licensedTo field carries the licensee identity. |
MCP server Enterprise
| Option | Description |
|---|---|
--mcp | Start as an MCP server on stdio so an MCP-capable AI assistant can drive the inspector. Exposes 9 tools (inspect_query, inspect_summary, inspect_types, inspect_methods, inspect_fields, inspect_properties, inspect_attributes, inspect_find, inspect_diff). See Driving the inspector from an AI assistant. |
Metadata Tables
The inspector can display any of the 31 ECMA-335 metadata tables. Use --table <name> in one-shot mode.
Core tables
| Table name | Contents |
|---|---|
typedef | Types defined in this assembly (classes, interfaces, structs, enums, delegates) |
methoddef | Methods defined in this assembly |
fielddef | Fields defined in this assembly |
paramdef | Method parameters with names and default values |
property | Properties with getter/setter references |
event | Events with add/remove/fire accessors |
Reference tables
| Table name | Contents |
|---|---|
typeref | Types referenced from other assemblies |
memberref | Methods and fields referenced from other assemblies |
assemblyref | Referenced assemblies (dependencies) |
typespec | Instantiated generic types (e.g., List<string>) |
methodspec | Instantiated generic methods |
moduleref | Referenced modules (P/Invoke DLLs) |
Relationship tables
| Table name | Contents |
|---|---|
interfaceimpl | Which types implement which interfaces |
nestedclass | Nested type relationships |
methodimpl | Explicit method overrides (.override directives) |
methodsemantics | Property/event accessor mappings |
propertymap | Type → property group mappings |
eventmap | Type → event group mappings |
customattr | Custom attributes on any metadata row |
Generic tables
| Table name | Contents |
|---|---|
genericparam | Generic type/method parameters (T, TKey, etc.) |
Interop and layout tables
| Table name | Contents |
|---|---|
implmap | P/Invoke mappings (unmanaged function imports) |
classlayout | Explicit class size and packing |
fieldlayout | Explicit field offsets |
fieldrva | Fields with data stored at fixed RVAs |
fieldmarshal | Marshalling descriptors for interop |
declsecurity | Declarative security attributes |
standsig | Stand-alone signatures (local variable types) |
Assembly-level tables
| Table name | Contents |
|---|---|
resource | Embedded and linked manifest resources |
exportedtype | Types forwarded to other assemblies |
file | Files in a multi-file assembly |
constant | Compile-time constants (field/param/property defaults) |
Examples
Quick overview of an assembly
inspector MyApp.dll --summary Compare before and after obfuscation
inspector obfuscated/MyApp.dll --diff original/MyApp.dll Find all types that implement a specific interface
inspector MyApp.dll -q "which types implement IHostedService" Audit for specific attributes
inspector MyApp.dll -q "types with attribute JsonSerializable" Check what an obfuscator preserved
inspector obfuscated/MyApp.dll -q "show public properties" Explore interactively
inspector MyApp.dll
inspector> summary
Assembly: MyApp
Types: 142
Methods: 891
...
inspector> show types implementing IDisposable
-> Show types implementing IDisposable
public class MyApp.Data.DbContext : System.Object
public class MyApp.Services.HttpClientPool : System.Object
(2 type(s))
inspector> describe DbContext
-> Show details of type DbContext
=== MyApp.Data.DbContext ===
Base: System.Object
Implements: System.IDisposable
Fields (3): ...
Methods (12): ...
inspector> show methods on DbContext
-> Show methods on DbContext
...
inspector> quit Script-friendly JSON output
inspector MyApp.dll --json --summary Drive from an AI assistant (optional)
If you already use an MCP-capable assistant, the inspector can be driven conversationally. See Driving the inspector from an AI assistant.
# Ask (if you use an MCP-capable assistant):
# "Show me all public methods that accept a CancellationToken and return Task"
# The assistant queries the inspector and answers in context. How Query Translation Works
Under the hood, every query (whether typed as English or passed via --table) is converted into a structured InspectQuery object with these fields:
| Field | Purpose | Values |
|---|---|---|
| Verb | What to do | Show, Find, Count, Detail, List |
| Target | What metadata to query | Types, Methods, Fields, Properties, Events, CustomAttributes, Interfaces, Resources, AssemblyRefs, Summary, All |
| Filters | Which items to include | Zero or more filter predicates (see below) |
| Limit | Max results | Any positive integer, or unlimited |
| Format | Output format | Table, Detail, Json, IL |
Available filter fields
Each filter has a field, an operator, and a value. Not every field applies to every target — the inspector validates compatibility and rejects mismatched combinations.
| Filter field | Applies to | Example |
|---|---|---|
Name | All targets | Methods named "Dispose" |
FullName | Types, Methods | Types with full name containing "Models" |
Namespace | Types | Types in namespace "MyApp.Data" |
ReturnType | Methods | Methods returning "string" |
ParameterType | Methods | Methods taking "CancellationToken" |
FieldType | Fields | Fields of type "Dictionary" |
PropertyType | Properties | Properties of type "string" |
BaseType | Types | Types inheriting from "Exception" |
Implements | Types | Types implementing "IDisposable" |
HasAttribute | Types, Methods | Types with [Serializable] |
Accessibility | Types, Methods | Public, private, internal, protected |
Owner | Methods, Fields | Methods on type "Calculator" |
IsStatic | Types, Methods, Fields | Static methods |
IsAbstract | Types, Methods | Abstract types or methods |
IsSealed | Types | Sealed types |
IsGeneric | Types | Generic types (with type parameters) |
IsVirtual | Methods | Virtual methods |
Text | All (search mode) | Free-text search across all names |
Filter operators
| Operator | Meaning |
|---|---|
Contains | Value appears anywhere in the field (default, case-insensitive) |
Equals | Exact match (case-insensitive) |
StartsWith | Field starts with the value |
EndsWith | Field ends with the value |
Not | Field does NOT contain the value |
GreaterThan | Numeric comparison (for count fields) |
LessThan | Numeric comparison (for count fields) |
In the CLI, the -> interpretation line shows you how your English was parsed before execution. When driving the inspector from an AI assistant, the assistant constructs queries using these same fields and operators.