cd /news/developer-tools/decompile-and-inspect-net-assemblies… · home › topics › developer-tools › article
[ARTICLE · art-168159] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

Decompile and inspect .NET assemblies from the command line — and from an AI assistant

Glass.NET 1.3.0, a free .NET decompiler, adds a headless command-line interface and a Model Context Protocol server that lets AI coding assistants open assemblies and read decompiled C#. The release introduces four batch commands — export, sbom, verify and diff — built on the same ICSharpCode.Decompiler engine as the UI, all performing static analysis without executing the inspected assembly.

by read7 min views5 publishedNov 12, 2026

Glass.NET is a free .NET decompiler built around navigation — you open an assembly and read it like your own source. But plenty of the work you do with a decompiler isn't interactive at all. You want to gate a CI job on whether a dependency changed its public surface, emit a software bill of materials for every binary you ship, or check that the NuGet package you just pulled is really what it claims to be. And increasingly you want your AI coding assistant to answer "what does this dependency actually do?" without you hand-feeding it decompiled snippets.

Glass.NET 1.3.0 covers both. It adds a headless CLI — the same ICSharpCode.Decompiler engine as the UI, no window required — and glass mcp, a Model Context Protocol server that lets an AI assistant open assemblies and read decompiled C# on your behalf. Everything below is strictly static analysis: Glass reads metadata and IL and reconstructs C#. It never runs the assembly it inspects. And all of it is free — no tiers, no license, no seats.

Four commands do the batch and scripting work, plus the server:

glass export — reconstruct a buildable C# project, or dump a single member.glass sbom — emit a software bill of materials for an assembly or package.glass verify — check a NuGet package's authenticity and strong-name identity.glass diff — compare two builds and report what changed in the public surface.glass mcp — start the MCP server for an AI assistant. Run glass --help for the full list; every command takes --json so you can pipe output into jq or a build step.

Point export at an assembly and a directory and you get a reconstructed, compilable project back:

$ glass export ./Acme.Payments.dll -o ./out/Acme.Payments
Decompiling Acme.Payments.dll (net8.0) …
  142 types, 1,206 members
Wrote ./out/Acme.Payments/Acme.Payments.csproj
Wrote 142 source files
Done in 1.9s — static analysis only, assembly was not executed.

That .csproj targets the assembly's own TFM and lists its references, so dotnet build ./out/Acme.Payments just works — useful when you need to diff against source, patch-and-recompile, or hand a reproducible tree to someone.

When you only care about one method, skip the whole project and ask for the member by its documentation-comment ID:

$ glass export ./Acme.Payments.dll --member "M:Acme.Payments.Gateway.Charge(System.Decimal)"
public ChargeResult Charge(decimal amount)
{
    if (amount <= 0m)
        throw new ArgumentOutOfRangeException(nameof(amount));
    var req = new ChargeRequest(amount, _clock.UtcNow);
    return _transport.Send(req);
}

You can pass a type ID (T:Acme.Payments.Gateway) to dump every member of a type, or --il to get the IL view instead of C#. This is the fast path for "show me exactly what this one method does" without opening a UI.

glass sbom reads an assembly's metadata and produces a dependency inventory in CycloneDX JSON — the assembly's identity, its target framework, and every AssemblyRef it binds against, with versions and public-key tokens:

$ glass sbom ./Acme.Payments.dll --format cyclonedx -o payments.sbom.json
$ jq '.components[] | {name, version}' payments.sbom.json
{ "name": "Newtonsoft.Json", "version": "13.0.3" }
{ "name": "System.Text.Json", "version": "8.0.0" }
{ "name": "Acme.Core", "version": "4.2.1" }

Because it works from the compiled binary rather than a packages.lock.json, it tells you what the shipped artifact actually references — including transitive assemblies that a project-file audit can miss. Point it at a .nupkg and Glass enumerates the assemblies inside each lib/<tfm> folder and merges their references into one document.

Before you trust a package, glass verify checks two things statically: the NuGet signature on the .nupkg, and the strong-name identity of the assemblies inside it.

$ glass verify ./Acme.Payments.4.2.1.nupkg
Package     Acme.Payments 4.2.1
Signature   author-signed, counter-signed (timestamp 2026-10-30)  ✓
Assemblies
  Acme.Payments.dll   strong-named  pkt=b77a5c561934e089   ✓
  Acme.Core.dll       NOT strong-named                     ⚠
Verdict     signature valid; 1 assembly unsigned — review before trusting.

It reports whether the package is author- or repository-signed, whether the signature is intact, and which assemblies carry a strong name and which don't. It does not vouch for intent — a validly signed package can still do something you dislike — which is why verify pairs naturally with export to actually read the code. And, as with every command, verification reads bytes; it never runs the package.

Hand diff two versions of the same assembly and it reports the delta in the public API surface:

$ glass diff ./Acme.Payments-4.2.0.dll ./Acme.Payments-4.2.1.dll
+ public ChargeResult Gateway.Charge(decimal, Idempotency)   added overload
- internal void Gateway.ResetCounters()                       removed
~ public sealed class ChargeResult                            field layout changed
3 changes (1 added, 1 removed, 1 modified)

With --json this becomes a gate: fail the build when a dependency bump quietly changes a signature you depend on, or flag an internal-to-public promotion in review.

Say a new transitive dependency, Contoso.Telemetry, showed up in a lockfile and you want to know what it does before it ships. The whole audit is static — nothing here executes the package:

$ nuget install Contoso.Telemetry -Version 2.1.0 -OutputDirectory ./pkgs -DependencyVersion Ignore

$ glass verify ./pkgs/Contoso.Telemetry.2.1.0/Contoso.Telemetry.2.1.0.nupkg
Signature   author-signed  ✓
Assemblies  Contoso.Telemetry.dll  strong-named  ✓

$ glass sbom ./pkgs/Contoso.Telemetry.2.1.0/lib/net8.0/Contoso.Telemetry.dll --json \
    | jq -r '.components[].name'
System.Net.Http
System.Text.Json

$ glass export ./pkgs/Contoso.Telemetry.2.1.0/lib/net8.0/Contoso.Telemetry.dll \
    --member "M:Contoso.Telemetry.Beacon.Flush"

Four commands, no window, nothing executed — and you've gone from "an unknown dependency appeared" to reading the exact method that touches the network.

The flow that ties it together:

The same static inspection is available to an AI coding assistant through the Model Context Protocol. glass mcp starts a JSON-RPC server over stdio that exposes a small set of read-only tools:

Tool What it does
glass_open Open an assembly or .nupkg and return its identity + TFM
glass_list_types Enumerate namespaces, types and members
glass_decompile Return reconstructed C# for a type or member ID
glass_find_references List callers of a member, across the open assembly
glass_sbom Return the dependency inventory as structured JSON

Register it with any MCP-capable assistant by pointing command at glass:

{
  "mcpServers": {
    "glass": { "command": "glass", "args": ["mcp"] }
  }
}

Now, instead of you decompiling a method and pasting it into chat, the assistant does it itself. A tools/call for glass_decompile looks like this on the wire:

{ "jsonrpc": "2.0", "id": 7, "method": "tools/call",
  "params": { "name": "glass_decompile",
    "arguments": { "member": "M:Contoso.Telemetry.Beacon.Flush" } } }

and the server answers with the reconstructed C# as text content:

{ "jsonrpc": "2.0", "id": 7,
  "result": { "content": [ { "type": "text",
    "text": "private async Task Flush(CancellationToken ct)\n{\n    using var http = new HttpClient();\n    await http.PostAsync(_endpoint, Serialize(_buffer), ct);\n}" } ] } }

So you can ask your assistant, in plain language, "open Contoso.Telemetry 2.1.0 and tell me what Beacon.Flush sends and where" — and it opens the assembly, reads the decompiled method, and tells you it POSTs a serialized buffer to a configured endpoint. The assistant is reading static output: glass mcp decompiles, it does not execute, so even an assistant acting on your behalf can inspect an untrusted package without running it.

Glass.NET 1.3.0 turns decompilation from something you do by hand in a window into something you can script and delegate. Use glass export for a buildable tree or a single method, glass sbom for a bill of materials, glass verify to check a package's signature and strong names, and glass diff to gate on public-surface changes in CI. When you'd rather ask a question than run a command, glass mcp gives your AI assistant the same read-only, static view. Every one of these reads the binary and reconstructs C# — none of them ever run it — and all of it is free. Grab the latest build from the Glass.NET download page and point it at the next dependency you're unsure about.

── more in #developer-tools 4 stories · sorted by recency
── more on @glass.net 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/decompile-and-inspec…] indexed:0 read:7min 2026-11-12 · —