A tool for inspecting .NET libraries and NuGet packages. It is for .NET what
docker inspect and kubectl describe are for containers: view package
metadata, API surfaces, dependencies, and source.
The .NET ecosystem uses a standardized binary format for managed assemblies
(ECMA-335
.dll files). That's why NuGet packages primarily distribute binaries instead
of source. That's where dotnet-inspect fits. It does for .NET binaries what
LSP-based tools do for source. dotnet-inspect reads .NET binaries to answer
basic questions about types and members and unlocks deeper insights, like call
graphs and seeing what really changed across two binary versions
dotnet tool install -g dotnet-inspect
dotnet-inspect <command>Run without installing:
dnx dotnet-inspect -y -- <command>dotnet-inspect can load direct local libraries, packages from configured Package Sources, and Platform libraries. Platform requests prefer locally installed packs when dotnet-inspect has a usable .NET root and the requested version is installed. Otherwise, they use the package-backed Platform source.
A framework-dependent invocation may derive the root containing its current
CoreCLR runtime; a NativeAOT invocation cannot. For a .NET installation outside
that runtime-derived location, learn the root from machine provisioning or its
tool manager, verify that it contains packs, and set process-scoped
DOTNET_ROOT:
dotnet_root=/absolute/path/to/dotnet-root
test -d "$dotnet_root/packs" &&
DOTNET_ROOT="$dotnet_root" dnx dotnet-inspect -y -- find JsonSerializer$dotnetRoot = "C:\absolute\path\to\dotnet-root"
if (-not (Test-Path -Path (Join-Path $dotnetRoot "packs") -PathType Container)) {
throw "The selected .NET root does not contain packs."
}
$env:DOTNET_ROOT = $dotnetRoot
dnx dotnet-inspect -y -- find JsonSerializerDOTNET_ROOT is the installed-root override; dotnet-inspect does not infer it
from PATH. Without a usable explicit or runtime-derived root, Platform
requests use the package-backed source.
Published tool users can install or run dotnet-inspect with the commands
above. Contributors building this repository should use .NET 11 RC1 SDK
11.0.100-rc.1.26425.128.
Check the selected SDK first:
command -v dotnet
dotnet --versionBuild from source:
dotnet build dotnet-inspect.slnx -c ReleaseSee AGENTS.md for launch guidance, Repository workflow for contributor rules, and Local development for targeted test commands.
| Source | Examples | Notes |
|---|---|---|
| NuGet packages | package System.Text.Json, type --package Markout |
Supports versions, custom sources, nuget.config, TFMs, package layout, dependencies, and vulnerabilities. |
| Restored projects | type Command --project ./src/DotnetInspect.Cli, project ./src/DotnetInspect.Cli -S Skills --print, project ./src/DotnetInspect.Cli -S README |
Uses an existing project.assets.json as restored-assets context for API lookup, relationship search, dependency package skills, and root package README files; restore/build first if dependencies changed. dotnet-inspect does not restore, build, or acquire missing packages. |
| Platform libraries | library System.Private.CoreLib, library System.Text.Json --version 10.0.0, diff --platform System.Runtime@9.0.0..10.0.0 |
Prefers installed packs when the requested version is available; otherwise uses package-backed Platform packs. |
| Local assets | library ./artifacts/obj/ILInspector.Metadata/release/ILInspector.Metadata.dll, package ./artifacts/MyLib.nupkg |
Useful for auditing local builds before publishing. |
Platform packs have distinct package, Platform, and direct-library views. For
example, package Microsoft.NETCore.App.Ref@10.0.0 inspects the targeting-pack
container as an exact NuGet package, while
library ./packs/Microsoft.NETCore.App.Ref/10.0.0/ref/net10.0/System.Runtime.dll
inspects one manually downloaded or extracted DLL directly. A Platform
selection unwraps authorized pack DLLs without publishing its source pack as a
Package participant. These entry paths preserve different provenance and do
not infer Platform identity from a package or file name.
Windows Metadata (.winmd) is not a supported input format, and rejection is
only partially enforced. Directory and package scans select *.dll, so a
.winmd beside them is skipped without comment. A native *.dll in a
directory scan is also skipped; a directory with only native images is
reported as a failed source. A .winmd named explicitly —
library ./Foo.winmd, find --library ./Foo.winmd — is rejected rather than
inspected, though not every surface names the reason: find reports
"Windows Metadata is not a supported metadata format", while library reports
only "Could not read library". Owners that have not yet adopted the admission
contract do not classify at all. Treat any Windows Metadata result as
unsupported output regardless of how confident it looks. Tracked by
#5559.
Bare names are routed automatically: platform-looking names (System.*,
Microsoft.AspNetCore.*) resolve to installed platform libraries; other names
resolve as NuGet packages. In API commands, common CoreLib aliases and simple
type names such as string, int, DateTime, and Guid resolve to
System.Private.CoreLib. Use explicit commands and --package, --platform,
or --library when you need a specific source.
After exact Type and Member lookup misses, a dotted Platform name may resolve as an exact namespace in its longest namesake Library. For example:
dotnet-inspect System.Text.Json.Nodesis equivalent to:
dotnet-inspect library System.Text.Json \
--namespace System.Text.Json.NodesThe Router confirms exact ordinal namespace membership before selecting this
route. It does not use suffix or descendant matching, and broad inputs such as
System.Text retain their existing Type-prefix browsing behavior.
find uses the same exact namespace meaning after direct Type lookup misses:
dotnet-inspect find System.Text.Json.NodesIt returns the public Types declared directly in
System.Text.Json.Nodes, such as JsonArray, JsonNode, and JsonObject.
It does not include Types from System.Text.Json or descendant namespaces.
The rows use the Namespace match classification. The default unscoped search
uses the same House-realized Runtime and ASP.NET Core populations as other
Type patterns. Explicit source options remain authoritative; for example,
--platform System.Text.Json searches only that platform Library.
Add a terminal .* to include the named namespace and its descendants:
dotnet-inspect find 'System.Text.Json.Serialization.*'This is namespace-aware rather than an ordinary Type glob. It includes Types
from System.Text.Json.Serialization and
System.Text.Json.Serialization.Metadata, classifies them as Namespace, and
uses the same package and Platform source policy as exact namespace discovery.
The literal dot is significant: System.Text.Json.Nodes.* excludes
System.Text.Json.NodesExtra, while System.Text.Json.Nodes* remains the
broader lexical Type glob with Glob classification.
find classifies each Type independently without requiring wildcard syntax:
dotnet-inspect find JsonSer # Prefix and similar Types in discovery order
dotnet-inspect find Serializer # Substring: XmlSerializer, JsonSerializer, ...
dotnet-inspect find AppendFormat # Members: StringBuilder.AppendFormat overloadsEach candidate receives one Exact, Direct, Glob, Namespace, Prefix,
Substring, or Partial classification. Exact and broader classes can mix;
the rows retain source and declaration discovery order rather than sorting by
name or similarity score. An undotted identifier without an Exact, Direct,
Glob, Namespace, or Prefix Type may also search member names; Markdown shows
those rows in a separate Members section. Plain --json and table formats
keep Type rows only and note omitted member matches; --count rejects an
answer that includes them. Use find .AppendFormat for member rows in every
format.
-n N is also Find's maximum hit budget across its Type or Member patterns.
For Type search, duplicate identity and per-candidate classification occur
before the budget. Find keeps the Nth accepted candidate, then stops before
the next Type, query participant, pattern group, source, or implicit broadened
Member fallback. Use a leading dot or --members when Member rows are the
requested bounded answer. If Type rows do not fill the budget, implicit Member
fallback may still contribute and its rows precede weak Type rows in the
presented answer. The current reverse-locator package route applies Head after
its complete resident census; other compatibility and Platform routes stop
metadata traversal directly.
A sole finite --rows A..B or --rows ..B similarly stops after accepted row
B for explicit Member Find and for Type patterns that cannot enter implicit
Member fallback, such as wildcard or dotted patterns. The strict window still
fails when row B does not exist. Ordinary undotted Type patterns remain
exhaustive because fallback Member rows can precede Type rows and suppress weak
Type matches. --tail, open-ended windows, and multi-stage row selection also
remain exhaustive.
A bare library command that resolves one Library renders its public-surface
Type declarations as a Tree: the Library, its namespaces with declaration
counts, and each declaration by name. Forwarded declarations are marked
(forwarded). The Tree shows no Member counts; use type <Type> for a Type's
Members.
dotnet-inspect library System.Text.JsonSystem.Text.Json 11.0.0.0
├─ System.Runtime.CompilerServices (3 types)
│ ├─ IsExternalInit (forwarded)
│ └─ …
├─ System.Text.Json (20 types)
│ ├─ enum JsonCommentHandling
│ ├─ class JsonDocument
│ └─ …
└─ …
--tree and -v:m select the same Tree, and --mermaid renders the same
nodes as a Mermaid graph. Platform, package, and file sources are accepted,
together with --framework, --version, --preview, one --tfm,
--namesake-library, NuGet source options, and --verbose. A package that
contributes more than one Library keeps the multi-Library view; explicit
--tree or --mermaid on such a package fails and asks for the assembly
within the package. Any other option, including -S, -v:n, -v:d, and
every format option, keeps the sectioned Library view; combined with such an
option, --tree and --mermaid keep their -S "Reference Hierarchy"
requirement. A DOTNET_INSPECT_FORMAT default also keeps the sectioned view
unless --tree, --mermaid, or -v:m is given explicitly. Library facts
remain available as -S "Library Info".
A Library with no public Types renders its identity line marked
(no public types). A Library whose Type population cannot be read completely
fails with the reason instead of rendering a partial Tree.
An exact Library can list its public Type declarations from one exact namespace:
dotnet-inspect library System.Text.Json \
--namespace System.Text.Json.NodesAdd --children to include the named namespace and all namespaces beneath its
dot-segment boundary:
dotnet-inspect library System.Text.Json \
--namespace System.Text.Json \
--childrenThis includes Types from System.Text.Json and
System.Text.Json.Serialization, but not System.Text.Jsonish.
A leading dot selects an exhaustive namespace suffix within that same exact Library:
dotnet-inspect library ./MyLibrary.dll --namespace .Nodes.Nodes matches Types declared in namespaces such as World.Blue.Nodes and
World.Green.Nodes. It does not prepend the Library name, and it does not
match Nodes, World.Blue.MyNodes, or World.Blue.Nodes.More. Markdown
renders the matching declarations in Type tables without a separate count
summary. --envelope exposes the same population's typed exact,
exact-or-descendant, or suffix binding and continuation identity. Namesake
source discovery belongs to Router, Spotlight, and find, not this
exact-Library operation.
Use -D --schema to inspect the syntax-selected structural view without
acquiring or loading the target. Package --library and --all-libraries
queries expose their route-specific schemas before package resolution, while
ambiguous commandless or dotted-member targets return separately labeled
alternatives rather than a lookup-chosen union. A commandless
<target> --all-libraries gesture always selects the package aggregate view.
Discover the stable IDs accepted by body queries:
dnx dotnet-inspect -y -- explain vocabularies/csharp.body-kinds --depth 1The depth-1 listing shows every value's exact Identity, such as
ObjectCreationExpression or BreakStatement, which is the spelling queries
accept; Name is a display label.
Then use one as a typed predicate. Kind=... auto-selects Body Shapes, while
ordinary section query options still control columns and rows:
dnx dotnet-inspect -y -- library System.Text.Json \
--where "Kind=ObjectCreationExpression" \
--columns "Member;Token;Match" -n 3# System.Text.Json.dll
## Body Shapes
| Member | Token | Match |
| ------ | ----- | ----- |
| `System.Text.Json.JsonDocument.RootElement~2810741072:1` | `0x06000260` | `new JsonElement(this, 0)` |
| `System.Text.Json.JsonDocumentOptions.CommentHandling~4fc3b6f99d:2` | `0x060002DC` | `new ArgumentOutOfRangeException("value", SR.JsonDocumentDoesNotSupportComments)` |
| `System.Text.Json.JsonElement.GetProperty~b07c7787dc` | `0x060002EA` | `new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, propertyName))` |
For an overview, explicitly select Body Shape Summary to group identical
rendered matches with an occurrence count:
dnx dotnet-inspect -y -- type StringBuilder --platform System.Private.CoreLib \
--where "Kind=ObjectCreationExpression" -S "Body Shape Summary" \
--columns "Match;Count"Body Shapes retains individual occurrences. Keep Member, Token, and the
start/end line and column fields to locate each match in the method's rendered
C# body; these coordinates are not IL offsets or original source locations.
Hiding columns never groups rows. Summary row limits select groups without
reducing their occurrence counts; --count counts the selected view's rows.
Both views are available on library, type, and member.
Use --jsonl for one machine-readable row per match or --count for the row
count. Bodies that cannot be reconstructed at full fidelity make the search
incomplete: the observed rows and count still print, stderr reports how many
bodies were not searched (--verbose lists them), and the command exits 1.
| Capability | Commands | Highlights |
|---|---|---|
| Package inventory | package |
Metadata, versions, TFMs, file layout, direct dependencies, recognized ecosystem dependencies, rooted dependency hierarchy, vulnerability data, custom feeds, and NuGet config support. |
| Project package skills and docs | project |
Section-driven direct-dependency rows from valid skills/**/SKILL.md files and root README.md files in the restored package cache. Use --print --row N to emit one selected document. Skill inventory values and complete documents that require containment become [Text omitted: required containment]; selected documents also report bounded code-point locations on stderr. |
| Query vocabulary | explain vocabularies |
Product-owned stable values, accepted query inputs, maps, and defaults for rich queries. |
| Ecosystem catalog | ecosystem |
Product-configured ecosystem packs, namespace hints, core/tool packages, demos, and known Integration bindings without package acquisition. |
| Library audit | library |
Assembly identity, public key token, trim/AOT metadata, unsafe/interoperability signals, SourceLink, PDBs, references, resources, async methods, and body-shape search. |
| API discovery | type, member, find |
Type search, exact namespace discovery, member tables, docs, overload selection, generics, direct calls/callers, source, decompiled C#, and IL. Unscoped find searches installed Platform populations and adds exact prune-authorized package observations for namespace hits; add other package APIs through explicit --package, restored --project, or patterned --package-prefix scope. |
| Package discovery | package query |
Discover exact package IDs or terminal-star package-ID prefixes before inspecting a known package with package. |
| API compatibility | diff |
Package, platform, and library diffs with breaking/additive classification plus opt-in C#/IL, selected-member authored-source, complexity, and structural-cohort context. |
| Timeline correlation | timeline |
Correlate API or member-body Findings across a package version range, with evaluation and transition views. |
| Implementation matching | match |
Identity-agnostic structural equivalence for two unambiguously named methods, plus --similar seeded discovery that ranks structural candidates for one seed. |
| Structural clone discovery | library/type/member -S "Clone Candidates" |
Workspace-scoped structural candidate ranking for an exact Library, Type, or logical Member seed, with independent Breadth and Discovery facets. |
| Library vocabulary | library -S "Name Families" |
Ranked one- and two-word Type-name suffix families, exact supporting Type evidence, and optional source-provenance populations. |
| Library dependency structure | library -S "Dependency Structure" |
Internal namespace dependency graph with relationship counts, topological levels, and cycle membership. |
| Relationships | graph, depends, extensions, type -S Implementers, type -S "Derived Types" |
Integration graphs, type hierarchies, explicit package/nuspec/library/restored-project dependency graphs, reference graphs, extension methods/properties, implementors, and subclasses. |
| Direct dependency evidence | depends -S Dependencies |
depends combines explicit roots, traversal, and normalized declaration/restored evidence in one sectioned document. |
| Package pruning policy | depends -S Pruning |
Explicitly compares source-authorized direct dependency candidates with an exact installed runtime or ASP.NET Core platform inventory, without changing graph traversal. |
| Source | type/member -S Source / @Source, library/package -S "SourceLink: Files", type -S "Source Files", member -S "Source Locations" |
Source is authored-first and retains provider and fallback context. @Source adds forced PDB Source and Decompiled Source views plus Source Diff; SourceLink inventories remain separate. |
| Performance analysis (experimental) | library -S "Library Metrics", library -S @Performance, library -S "Performance: Strings", type/member -S "Performance Triage", "Top Leverage", "Resource Triage", "Call Graph" |
Whole-library structural metrics, whole-assembly leverage ranking, exact string-materialization operations, actionable rewrite-shape detection, and exception-path resource-lifecycle candidates. |
| Decompiler (experimental) | member -S @Decompiler, member -S "Fidelity Causes", member/type/library --where "Kind=<ID>" |
Decompiled C#, annotated source, IL, body-shape queries, and typed DEC#### fidelity causes. |
| Raw metadata | library -S @Metadata, library address "#Strings:0x1a4" |
Decoded ECMA-335 metadata tables and heap addressing. |
| Workspace definition, inventory, and navigation | workspace --package X --tfm TFM --share packet |
Author a durable format-3 Workspace definition without acquisition, or omit --share to realize and render typed top-level inventory. Repeat --package to compose Package Scope; add --register-library, --register-package-prefix, or --register-ecosystem for registration intent. --packet accepts a canonical Base64URL packet string. Add --active-ecosystem ID for a resource-free Ecosystem subject or --active-package N for structural Library, Type, Member, and lens descriptors. |
| Package Queries | package query ID --where "library-literal=TEXT" --tfm TFM, workspace --root-request TOKEN |
AND-compose ordinary Package Query terms with an ordinal decoded-ldstr substring over each prequalified package's selected implementation libraries. Results remain package-grain and carry typed producing-Library context, complete occurrences, and exact Root reopening tokens. |
| Workspace sharing and editing | workspace packet encode / decode, workspace component list, workspace package add / update / remove |
Convert canonical browser/CLI packets, discover stable component paths, and immutably derive edited Workspace packets. |
| Agent-friendly output | global flags | Markdown by default, compact --table, normalized --tsv, --jsonl, --json, Mermaid diagrams, section/field projection, --count, and row limiting. |
| Command | Purpose |
|---|---|
package X |
Inspect NuGet metadata, versions, dependencies, TFMs, layout, and vulnerabilities. |
package query X |
Discover exact package IDs or terminal-star package-ID prefixes, with optional metadata, dependency, ecosystem, and selected-Library qualification. |
package activity --ecosystem NAME |
Report bounded recent package activity for an ecosystem-selected package population, with source coverage and security evidence. |
project [path] |
Inspect restored project package skills and package docs. |
library X |
Inspect assembly metadata, symbols, SourceLink, references, resources, async methods, and rendered body shapes. |
library query DIR |
Query a directory or --platform reference pack as a bounded Library population; references=NAME qualifies direct assembly references. |
type X |
Discover types or render a single type shape. |
member X |
Inspect members, docs, overloads, decompiled/lowered C#, rendered body shapes, checksum-verified PDB source, and IL. |
find [X] |
Search for API types in installed .NET Runtime, ASP.NET Core, and .NET Standard populations by default. Add --members (or lead the query with ., such as .Serialize) to search member names; add package APIs through explicit --package, restored --project, or patterned --package-prefix scope. Use package query to discover package IDs. |
diff X |
Compare API surfaces by default; opt into analysis or implementation evidence. |
timeline X |
Correlate API or member-body Findings across a package version range. |
graph integrations |
Induce extension, observed Integration, and Integration-opportunity relationships over an explicit package set; -n, --tail, and --rows select complete logical edges after graph construction. |
graph calls TYPE MEMBER |
Explain one package member's supply-chain exits across its dependency graph, retaining highlighted boundaries and their shortest baseline connectors. |
graph libraries |
Discover deterministic direct-use clusters and exact cross-library relationships between two local Libraries. |
graph packages |
Discover deterministic direct-use clusters across the complete implementation-Library matrix of two exact Packages. |
graph cluster N |
Inspect exact calls for one local-Library-pair or Package-pair Direct-Use Cluster ordinal; the local route also supports public-entrypoint paths. |
depends [Type] |
With a positional type, walk its hierarchy inside --package, --library, --project, or platform search scopes. Without a positional type, combine repeatable explicit --package, --nuspec, --library, and --project roots, or exclusive --package-prefix, into one dependency graph and evidence document. |
extensions X |
Find extension methods and C# extension properties for a type. |
type X -S Implementers |
Find concrete implementors of an exact interface focus. |
type X -S "Derived Types" |
Find subclasses of an exact base-type focus. |
match A B |
Compare two unambiguous Type.Member names by identity-agnostic structural equivalence; add --body for decompiled C# and IL body differences. |
match A --similar |
Rank structural candidates for one seed method, within a single assembly. Ranks candidates only; it establishes no relation. |
explain vocabularies |
Explain product-owned query vocabularies such as api.accessibility, csharp.style-choices, and csharp.body-kinds. Add /<id> for one vocabulary, --depth 1 for all of its values, or /<id>/values/<value> for one value. |
ecosystem [name] |
Inspect the ecosystem knowledge configured into this product build. Omit the name to list packs; use -S Integrations for configured Integration concepts, distinct from observations in a library. |
workspace |
Render the typed top-level inventory of one ephemeral Workspace: committed ordered Package occurrences first, then inert Exact Library, Package Prefix, and Ecosystem registrations. Repeat --package ID@VERSION coordinates and supply --tfm; add --register-library PACKAGE@VERSION/ASSEMBLY@ASSEMBLY_VERSION, --register-package-prefix PREFIX, or --register-ecosystem ID; filter with repeatable --kind. Restore a current-format canonical Workspace packet with --packet PACKET, or use --root-request TOKEN to reopen the exact Package Root a package query --where "library-literal=..." result names. Add --active-ecosystem ID to activate the exact resource-free registration with Ecosystem Overview, or --active-package N to evaluate the exact Package occurrence and expose its Navigation hierarchy, Library asset IDs, Type and Member inventories, lenses, and diagnostics. |
workspace packet encode / decode |
Convert validated Workspace JSON and canonical base64url packets; pass - for stdin or use --file. |
skill |
Print the base LLM skill and route to focused built-in guidance (skill list, skill query, skill decompiler, skill relationships, and more). |
demo [id] |
List or run product-home inspection demos backed by real section output. |
cache |
Inspect or clear dotnet-inspect caches. |
Bare type ... --count follows the resolved subject: a Library subject counts
Types, while a Type subject counts Members. Add -S to count a particular
section or category instead; several explicitly selected row sets retain their
per-section count table.
Signals is an evidence report, not a safety certification. Use -S Signals
for a compact package or library overview, then opt into deeper audits only when
you need them.
Observed integration support is exposed through one Integrations section.
Use integration=<canonical-concept-id> to focus one concept, or
ecosystem=<canonical-pack-id> to enable the Integration concepts registered
to an ecosystem. The current Aspire registration enables the complete
configured Integration catalog; only concepts observed in the inspected
library produce rows. Add integration=... to narrow within that enabled set.
@Integrations also includes the separate Integration Opportunities section.
Use ecosystem to inspect which ecosystem packs and Integration bindings are
configured into this build. This is catalog knowledge, not evidence from an
acquired library:
dotnet-inspect ecosystem
dotnet-inspect ecosystem aspire
dotnet-inspect ecosystem aspire -D
dotnet-inspect ecosystem aspire -S @Ecosystem
dotnet-inspect ecosystem aspire -S Integrations
dotnet-inspect ecosystem ai -S "Core Packages"
dotnet-inspect ecosystem aspire -S "Core Packages"
dotnet-inspect ecosystem blazor -S "Core Packages"
dotnet-inspect ecosystem maui -S "Core Packages"
dotnet-inspect ecosystem microsoft-extensions -S "Namespace Hints"
dotnet-inspect ecosystem runtime -S PruningPackage Info and Library Info summarize ecosystems recognized from direct
dependencies. Select Ecosystem Dependencies to see the dependency/ecosystem
pairs, including one row per ecosystem when a dependency intentionally
overlaps multiple packs:
dotnet-inspect package Microsoft.Extensions.Http@10.0.0 \
-S "Package Info"
dotnet-inspect library --platform System.Text.Json \
-S "Library Info"
dotnet-inspect library --platform System.Text.Json \
-S "Ecosystem Dependencies" \
--columns "Ecosystem,Kind,Dependency,Declared By"Library recognition classifies the selected Library's declared assembly
references. Package declarations use product-profile associations directly.
Assembly references first match an authored exact or family association and
then require a compatible same-name AssemblyDef from one exact shipped
Package-asset evidence entry. Detail rows distinguish Profile match,
Catalog-backed, and Candidate; catalog-backed rows name the exact Package
asset. Candidates matched an ecosystem association without corroborating
AssemblyDef evidence and therefore do not enter the compact Package or Library
Info ecosystem rollup.
Recognition does not resolve or traverse assembly references. Unrecognized references do not become ecosystem rows, while JSON still reports recognition status as complete. Complete means every available direct observation was classified against the shipped profile; it does not claim runtime binding or high-confidence provenance.
Core Packages are inert registered package roots. Catalog inspection performs
no source work; a later bounded operation that selects the ecosystem may resolve
those concrete packages and follow their ordinary dependencies. Package-prefix
matches remain discovery scope and are not substituted for those roots.
Use package activity --ecosystem to report package activity under one named
ecosystem's recorded package prefixes (for example Aspire. for aspire). The ecosystem option selects where
to look; ecosystem itself remains the acquisition-free catalog command.
This network-backed query defaults to the interval
(reference time - 42 days, reference time], reports the exact UTC bounds and
source horizon, and overlays current GitHub-reviewed advisory context and
evidenced security releases:
dotnet-inspect package activity --ecosystem aspire
dotnet-inspect package activity --ecosystem aspnetcore --security-only
dotnet-inspect package activity --ecosystem microsoft-extensions -n 25 --json
dotnet-inspect package activity --ecosystem aspire \
--from 2026-02-01T00:00:00Z \
--through 2026-03-01T00:00:00Z--from is exclusive and --through is inclusive; specify both with explicit
UTC offsets, and keep the interval at 42 days or less. --security-only keeps
activity with positive current-advisory or exact security-release evidence.
Unavailable evidence is not treated as a negative. Human output uses the shared
report view; --json emits the lossless schema-versioned report, while
--envelope emits the same report as Content with Share and diagnostics.
--compact minifies either JSON boundary. Use --verbose for bounded
acquisition progress on stderr. Single-table formats and catalog-only section
projections are not available with package activity.
ecosystem runtime -S Pruning is the exception to "catalog knowledge": it reads
the reference pack installed on this machine to list the package identities the
platform target supplies, so a reference to one resolves to the platform rather
than to the package. Kind separates a version that moves with the framework
(live) from one pinned to a release the framework has passed (frozen).
All integrations are enabled by default. Discover the supported ecosystem
predicate with library -Q Integrations, then narrow the ordinary result:
dotnet-inspect library -Q Integrations
dotnet-inspect library Aspire.Hosting.Redis@13.5.3 --tfm net8.0 \
-S Integrations --where "ecosystem=ecosystem.aspire"
dotnet-inspect library ./MyLibrary.dll -S Integrations \
--where "integration=integration.aspire" --jsonlThese facets filter Integration evidence and opportunities, not assembly-wide presence or Census. When both are supplied, they intersect. Other query families cannot be combined with either Integration facet.
For deeper how-to guidance, use the embedded skills instead of relying on a very long README:
dotnet-inspect skill list
dotnet-inspect skill query
dotnet-inspect skill signals
dotnet-inspect skill decompiler
dotnet-inspect skill performance
dotnet-inspect skill relationshipsThese features are under active development. Their output shapes, section names, and signal sets may change between releases.
Use library -S @Performance for a whole-assembly triage pass, Top Leverage
for ranking, Resource Triage for exception-path pool-churn candidates, and
Call Graph to drill one selected member. The performance skill covers the full
workflow in more depth. Performance: Sync Calls in Async finds synchronous
calls made by async methods when the declaring type offers a callable async
sibling, including Dispose/DisposeAsync pairs.
dotnet-inspect library System.Text.Json -S @Performance
dotnet-inspect library System.Text.Json -S "Library Metrics"
dotnet-inspect library System.Text.Json -S @Performance --count
dotnet-inspect library System.Text.Json -S "Performance: Boxing" --json
dotnet-inspect library System.Text.Json -S "Performance: Strings" --json
dotnet-inspect library System.Text.Json -S "Performance: Sync Calls in Async"
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 -S "Call Graph"Use member -S @Source for the authored-first source view, forced PDB and
decompiled provider views, and their source diff. Use member -S @Decompiler
for decompiled and annotated C#, IL, and related analysis evidence. Use
Fidelity Causes when a body cannot be raised faithfully.
In Inspect Web, All also reveals exact direct-call relationships at their
source locations; these remain outside the default Finding set. Explore
starts with one Relationships row per exact physical call, with explicit
call-site inspection and Member or Source target actions. An opt-in
Diagram groups repeated physical calls by their stable logical edge while
keeping every exact call site available through the table. Selecting a
recursive relationship shows its exact direct or mutual cycle witness and
whether the bounded focus-graph census was complete. Selecting a framework
Task.Wait, Task<T>.Result, or task-awaiter GetResult relationship also
shows the exact synchronous-completion structure without claiming that runtime
blocking was measured. Selecting a proven classic await explains its inline
and suspension/resume paths, while selecting an exception-related allocation
distinguishes a thrown value from an allocation inside a catch, filter, or
fault handler. A relationship can also show a bounded direct-call path to a
method containing an Analysis-proven local throw new, including its exception
type and physical construction and throw offsets. These are compiled-structure
claims only: they do not prove that a path ran, that a throw escapes, or that an
exception propagates to the selected method.
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 -S @Source
dotnet-inspect type JsonSerializer --package System.Text.Json -S Source
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 -S Source
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 -S "Fidelity Causes"
dotnet-inspect library address 0x060002EA+0x0 \
--package System.Text.Json --library System.Text.Json.dll
dotnet-inspect library address --file coordinates.txt \
--library ./MyLibrary.dllCoordinate files accept up to 1,024 significant records. Blank and comment lines are ignored; valid and malformed records remain interleaved in source-file order so row windows select the same records the producer supplied.
ReadyToRun and metadata sections are opt-in only. Use @ReadyToRun for the
validated image header and section directory. Use @Metadata to discover or
render decoded ECMA-335 table rows, --metadata-root r2r-manifest to inspect
the ReadyToRun manifest metadata instead of the default CLI root, and
library address for one exact heap address in the selected root.
dotnet-inspect library System.Private.CoreLib -S @ReadyToRun
dotnet-inspect library ./artifacts/obj/ILInspector.Metadata/release/ILInspector.Metadata.dll -D @Metadata
dotnet-inspect library ./artifacts/obj/ILInspector.Metadata/release/ILInspector.Metadata.dll -S @Metadata --count
dotnet-inspect library ./artifacts/obj/ILInspector.Metadata/release/ILInspector.Metadata.dll -S "Metadata: TypeRef" --rows 20
dotnet-inspect library address "#Strings:0x1a4" \
--library ./artifacts/obj/ILInspector.Metadata/release/ILInspector.Metadata.dll
dotnet-inspect library System.Private.CoreLib --metadata-root r2r-manifest -S "Metadata: Image"Default output is Markdown. For compact human scanning use --table; for
machine-friendly rows use --tsv or --jsonl; for structured graphs use
--json; for plain text use --plaintext; and for diagrams use --mermaid.
Tips are off by default. Member uses one dotted explanation-projection
namespace at two placements: --explain replaces ordinary output with a
primary result on stdout, while short-only -E preserves ordinary output and
writes a companion to stderr. Bare selects the complete explanation;
.tips, as a separate dotted token, selects up to three contextual
suggestions:
dotnet-inspect member --explain
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize \
--explain
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 \
--explain
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize \
--explain .tips
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize -E
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize \
-E .tipsCommand-level member --explain is acquisition-free. Subject-bearing
--explain resolves exactly one semantic subject and writes its explanation as
the terminal stdout document instead of ordinary inspection output. A bare
ordinary method name is one MemberGroup subject regardless of overload count;
an ordinal or digest selector is one exact Member subject. Singleton groups
remain MemberGroups, and an overloaded group is not rejected as several
subjects or reduced to its first overload. Resolved-subject
--explain .tips writes only the headless plain-text suggestions to stdout; it
does not produce ordinary Member Content. Command-level .tips requires a
MemberGroup or exact Member because the command resource has no applicable
gesture context. Resolved-subject bare -E preserves ordinary stdout
byte-for-byte, flushes it, then writes the same explanation Content to
stderr. --explain -E and
--explain .tips -E .tips are duplicate projections and are rejected;
different primary and companion projections compose. Bare -E remains
reserved on other commands. Both .references placements remain reserved
until reusable inspection references are available.
Legacy -T and --tips, lowercase -e, undotted -E tips /
-E references / --explain tips / --explain references, attached or
inline -E.tips / -E=.tips / -E:.tips / --explain=.tips, unknown dotted
children, and repeated placement options are invalid. An unrelated undotted
token after either option remains positional. Option-like filenames and other
required option values retain that option's ownership; for example,
--out --tips names an output path rather than invoking the retired option. E
suggests explain and can also remind users that the companion is written to
the error stream; the latter is a mnemonic, not an error classification.
Positional depends <type>, ordinary single-Library API diff, package activity, Package Query, online package range-version population, and exact
package-backed Type or Library API inspection support the presence-only
--envelope service-output selector. It
implies JSON. For depends, API Diff, Package Activity, Package Query, and
exact Type or Library API inspection, unprojected --json emits the same
Content without the service frame. Package version --json remains an explicit
row projection;
--envelope instead exposes the complete directed population Document, Share,
and diagnostics. Asset-mode depends, other Diff modes, Discover, Count outside
package population, projected output, other Type modes, and other commands have
not adopted this transport.
| Goal | Flags |
|---|---|
| Discover available sections and fields | -D, -D --schema |
| Add structural format, shape, and cardinality details | -D --details, -D <exact-name> --details (library, package, type, member) |
| Discover query facets and operators | -Q on library/type/member/package/find; e.g. library -Q @Performance or type -Q "Body Shapes" |
| Select sections or categories | -S, wildcards such as -S "Async*", authored categories such as -S @Source or -S @Audit |
| Project columns/fields | --columns, --fields |
| Limit semantic rows or rendered lines | --rows, -n, --head, --tail, --lines, --tail-lines |
| Count results | --count |
| Materialize one payload | --print, --row, --value, --raw, --paths, package-file --roots, --urls, --json-array |
| Prefer browser views over fetchable URLs | --prefer-rendered-urls (keeps the original URL when no mapping is available) |
| Control document verbosity | -v:q, -v:m, -v:n, -v:d |
| Explain the Member command, one MemberGroup, or one exact Member | member --explain, subject-bearing member ... --explain, or member ... -E |
| Show contextual tips | Subject-bearing member ... --explain .tips on stdout or -E .tips on stderr |
| Control package sources | --offline, --source, --add-source, --nugetconfig, --http-timeout |
--offline is the only way to guarantee no network dependence. Without it,
commands other than plain -D discovery may acquire packages and PDBs to
answer the request. The
network policy owns this
rule and its adoption status.
--table, --tsv, and --jsonl render one section at a time, so pair them
with a concrete -S when querying sectioned output. Markdown and JSON can
represent multi-section documents.
--raw is itself a formatter. On package and project, do not combine it
with --json, --jsonl, --tsv, --table, --markdown, --plaintext, or
--mermaid; the command rejects those combinations before acquisition.
Explicit --raw outranks DOTNET_INSPECT_FORMAT. The retired --bare
spelling receives the ordinary unrecognized-input result.
Source URLs are fetchable by default. --prefer-rendered-urls prefers a browser
view when supported; it changes neither --print acquisition nor undecorated
--raw rendering. The former SourceLink URL-shape meaning of --raw is
retired, and --blob is removed and unrecognized. Use no URL-shape flag for
the default fetchable form.
-n N selects the command's items. It selects semantic rows when the active
command or lens declares them; otherwise it selects the first N rendered lines.
Add --tail for the last N items. --lines explicitly selects rendered lines
on a semantic-row command, and --tail-lines selects rendered lines from the
end. Rendered-line clipping is not available with JSON document output.
Useful discovery and projection patterns:
dotnet-inspect library System.Text.Json -D
dotnet-inspect library System.Text.Json -D --details
dotnet-inspect library System.Text.Json -D @Dependencies --details
dotnet-inspect library System.Text.Json -D "Reference Hierarchy" --details
dotnet-inspect library -Q
dotnet-inspect type -Q "Body Shapes"
dotnet-inspect library -Q "Performance: Arrays" --json
dotnet-inspect member JsonSerializer --package System.Text.Json -D --schema
dotnet-inspect explain vocabularies
dotnet-inspect explain vocabularies/csharp.body-kinds
dotnet-inspect explain vocabularies/csharp.body-kinds --depth 1
dotnet-inspect explain vocabularies/csharp.style-tiers/values/spelling
dotnet-inspect library System.Text.Json -S Signals
dotnet-inspect library System.Text.Json -S @Audit
dotnet-inspect library System.Text.Json -S References
dotnet-inspect library System.Text.Json -S "Reference Hierarchy" --tree
dotnet-inspect library Microsoft.Extensions.Logging.Abstractions -S Integrations
dotnet-inspect library Microsoft.Extensions.Logging.Abstractions \
-S Integrations --where "integration=integration.logging"
dotnet-inspect library System.Diagnostics.DiagnosticSource \
-S Integrations --where "integration=integration.opentelemetry"
dotnet-inspect package System.Text.Json --path @readme --content --frontmatter
dotnet-inspect package Newtonsoft.Json -S "Package Info" --fields Version --value
dotnet-inspect project ./src/DotnetInspect.Cli -S Skills --jsonlLibrary, Package, Type, and Member -D --details are structural and do not
acquire the target. They add the owner-issued section properties to the
top-level catalog, or report one exact category or section in detail:
Formats, and, where the owner declares them, Shape (table, hierarchy,
or text, per Section shapes), Cardinality
(scalar or inventory), and Terminals. Every owner declares all of them;
Call Graph and Library Dependency Structure are graphs and declare no
shape. A category reports the formats supported by its
complete expansion plus the formats of each member; it never selects or drops
members to satisfy a format. Use the result to choose an exact section before
requesting a single-result projection such as --tree or --mermaid.
explain <catalog>/sections/<section> reports the same shape and cardinality
for one section, beside its formats and members. The catalogs are library,
package, type (the type listing), member (one type's members),
member-overload, and member-detail (one exact member).
For one library, its field-set records — Library Info,
SourceLink: Availability, SourceLink: Integrity, Symbols, and
Metadata: Image — are scalar: they have no rows to count or window. --count or --rows on one of
them, on a selection of only them, or on the default overview fails before
acquisition. An explicit selection that mixes them with inventories counts and
windows the inventories alone, so library MyLib.dll -S @Metadata --count lists
each metadata table without an image field count. Context: Source Location,
Member, Instruction, Callsite, and Return Address count their one
located row; Context: Exception, Allocation, Safety, and Cost count
the regions or facts at the coordinate. library address ... -D --details
reports these declarations for the coordinate sections.
The library command renders a lone explicitly selected section in its declared
shape's native format when no format is named, per
Section shapes: a Table streams its TSV rows
(library MyLib.dll -S References, the Library Info record as field/value
TSV, each metadata table, and each Context: section on library address)
and Reference Hierarchy renders its tree; --markdown or --mermaid names
another of its formats. Dependency Structure is a graph and keeps its
current rendering. An explicit format, an environment default, --print,
--row, --value, --urls, --paths, --tree, --count, a projection,
an envelope, or discovery keeps its existing behavior, and selecting several
sections composes Markdown as before, including a mixed selection whose
scalar records leave a --rows window.
dotnet-inspect package System.Text.Json -D --details
dotnet-inspect package System.Text.Json -D Files --details --json
dotnet-inspect type System.String -D --details
dotnet-inspect member System.String.Trim:1 -D --details
dotnet-inspect explain package/sections/files
dotnet-inspect explain member-detail/sections/sourcedotnet-inspect package System.Text.Json
dotnet-inspect package System.Text.Json --version 10.0.0
dotnet-inspect package System.Text.Json --versions -n 1
dotnet-inspect package System.Text.Json@latest --versions
dotnet-inspect package System.Text.Json --versions -n 6
dotnet-inspect package System.Text.Json@8.0.0..8.0.5 --versions
dotnet-inspect package System.Text.Json@8.0.0..8.0.5 --versions --envelope
dotnet-inspect package System.Text.Json@8.0.0..8.0.5 --count
dotnet-inspect package System.Text.Json@8.0.0..8.0.5 --count --envelope
dotnet-inspect package Newtonsoft.Json@13.0.4 \
--tfms -n 1 --tail --json
dotnet-inspect package System.Text.Json -S Signals
dotnet-inspect package System.Text.Json -S "Signals,Audit: Artifact Text"
dotnet-inspect package System.Text.Json -S "Signals,Audit: Findings"
dotnet-inspect package Newtonsoft.Json@13.0.4 \
--files --tfm net6.0 -n 1 --tail --json
dotnet-inspect package Markout@0.35.2 \
--path "skills/*/SKILL.md" -n 1 --tail --paths
dotnet-inspect package Markout@0.35.2 \
--path skills/markout/SKILL.md --content --raw
dotnet-inspect package System.Text.Json --version 10.0.0 \
--path README.md --content --raw
dotnet-inspect package Microsoft.Data.SqlClient@6.1.0 \
--tfm net8.0 -S Files --paths
dotnet-inspect package Microsoft.Data.SqlClient@6.1.0 \
--tfm net8.0 -S Files --roots
dotnet-inspect package Newtonsoft.Json@13.0.3 \
-S "SourceLink: Files" -t JsonReader -n 1 --tail --urls
packet=$(dotnet-inspect workspace \
--package System.Text.Json@10.0.0 \
--tfm net10.0 \
--share packet)
dotnet-inspect package System.Text.Json --workspace "$packet"
dotnet-inspect package System.Text.Json \
--workspace "$packet" --share packet
dotnet-inspect package System.Text.Json@10.0.0 \
--tfm netstandard2.0 -S "Dependency Hierarchy" --share url
dotnet-inspect package query 'Azure.AI*' --take 100 --tsvBare package ID[@VERSION] output and bare --tree render the Package's
native children Tree. Ordinary packages list every Library in the selected
compile population by identity without opening the Library binary or
summarizing its Type population. --tfm selects an explicit target; otherwise
the Package selection default chooses the target. Tool pointer packages list
their RID packages, managed tool payloads list the entry-point Library before
their dependencies, and native tool payloads state that they contain no managed
Libraries. Minimal implicit Tree output may collapse a managed tool's
dependency Libraries into one counted branch that names -v:n as the
full-inventory gesture. Normal, Detailed, and explicit output formats list
every Library.
Unselected Markdown, plain text, JSON, envelope, table, TSV, and JSONL output
all consume that same Package children document. The tree title prints the
subject identity followed by the owner-issued properties of the displayed
children — source, selected target, and asset root, as in
System.Text.Json 10.0.12 (NuGet; net10.0; lib) — and nothing else. JSON
carries subject, completion, total and selected Counts, and typed child rows.
Row formats expose the exact asset ID, asset path, target, and child role;
they carry no replay command, because host navigation is not package content
(see Section shapes). Package children
output does not run the unrelated all-binary Signals scan or inspect selected
Libraries. --count
counts the owner-issued child population without producing rows; --rows
windows the same ordered identities, and --fields or --columns projects
child-row columns. Windows retain the
complete population Count and original child ordinals; a window selecting no
rows from a non-empty Package does not claim that the Package has no Libraries.
Select Package Info explicitly for Package facts. A bare Package Tree is
distinct from the dependency graph: select Dependency Hierarchy together
with --tree for rooted transitive dependencies.
package ID[@VERSION] --workspace PACKET inspects the matching direct Package
in the packet's selected context, independently of its focused tab, and reuses
the exact Package Root and target admitted during Workspace restoration.
Appending --share preserves ordinary stdout and writes a derived Package
packet or URL as the final stderr line. An exact selector can inspect a
currently resolved floating Package member, but Share refuses rather than
silently pinning that preserved definition.
For a direct NuGet.org Package query with one Dependency Hierarchy section,
append --share url to keep the hierarchy on stdout and print its Inspect Web
URL on stderr. The URL preserves the resolved exact Package version and target
framework; the Browser reacquires that Package and runs the rooted dependency
traversal. --share packet emits the packet instead. Local archives, other
source selections, and hierarchy row or depth selections cannot currently be
reproduced in the Browser and fail visibly.
For one package with exactly Files selected, -n, --tail, and
--rows A..B select complete path/size rows after archive extraction, file
enumeration, optional exact directory-segment --tfm filtering, and optional
--path filtering. Count, table, TSV, JSONL, JSON, --value, and --paths
observe the same selected rows; --roots instead emits their ordered distinct
top-level package roots. Add --lines only to clip rendered text.
The package command renders a lone explicitly selected section in its declared
shape's native format when no format is named, per
Section shapes: a Table streams its TSV rows, a
Hierarchy renders its tree, and a Text prints its payload. Files and
Dependency Hierarchy are Hierarchies, the nuspec and README sections are
Text, and every other section is a Table. The Files tree titles the
subject with its issued properties (source, and the target when --tfm
filters), groups files under their directories, and collapses single-entry
directory chains into one node; directory nodes are context, so -n, --rows,
and --count observe files only, and --tree is an accepted explicit format
for it. Selecting several sections composes Markdown as before, with a Text
section contributing its Path/Size fact row and its body only when it is the
whole selection. An explicit format, an environment default, --print,
--raw, --tree, --count, a projection, a shape flag, discovery, or a lens
keeps its existing behavior.
The package file family — the nuspec, README, license, and skill sections —
shares one Path/Size row schema, so -S @Files --table, --tsv, or --jsonl
streams one listing with each member's rows in family order. Scalar sections
(Package Info, Summary, Statistics, Signature, the SourceLink
availability and integrity sections, and the nuspec and README Text sections)
have no rows: selecting one of them alone with --count or --rows fails
before acquisition and names an inventory section as the alternative. A bare
-n on such a section is the rendered-line window it is for Library Info,
not a row terminal. Count maps over several sections, and multi-package counts,
keep their existing per-section meaning.
dotnet-inspect package System.Text.Json -S "Target Frameworks"
dotnet-inspect package System.Text.Json -S README
dotnet-inspect package System.Text.Json -S Files -n 5
dotnet-inspect package System.Text.Json -S @Files --tsvFor an exact online package version, -S README and one literal root
README.md or skills/**/SKILL.md path with --content acquire directly
through the PackageHouse semantic Files route rather than the legacy
extraction route. The README section uses one host-neutral selection:
README.md when present, otherwise PACKAGE.md. PackageHouse selects cache,
size-first HTTP Range access, or complete fallback, while the operation
publishes only the selected entry. That entry is detached through the shared
package document-content inspection, then the CLI applies its existing
separator, --raw, JSONL, or --out projection. Skill documents retain their
containment and link-normalization behavior. Detached content projections
accept documents up to 16 MiB; an exact README written to --out remains a
bounded byte stream and is not subject to that detached-content limit. Local
packages, floating or range version selection, target-framework filters, path
globs and roles, scoped documents, .NET tool-wrapper redirection, and other
package files retain their existing behavior.
The --files flag selects exactly the same section as -S Files.
File predicates compose before row windows and Count:
dotnet-inspect package System.Text.Json@10.0.12 --files \
--where "Root=lib" --where "Target=net8.0"
dotnet-inspect package System.Text.Json@10.0.12 -S Files \
--lib --tfm net8.0
dotnet-inspect package System.Text.Json@10.0.12 --files \
--where "Name=*.xml" --pathsFiles admits Path (complete package-relative path), Name (filename),
Directory (exact parent directory), Root (top-level folder), and
Target (a complete directory segment). Text fields support
case-insensitive = and != with * and ? wildcards; Target
matches an exact segment case-insensitively. Repeated predicates combine
with AND. --lib and --tools wrap Root equality and require exactly
Files for one package; --tfm wraps Target equality for Files.
All formats preserve package-relative paths. A filter with no matching
files succeeds with zero rows. The old --layout spelling is removed.
A package flag may select a section, filter its rows, select an inspection subject, or project a result. Only the first two have section/predicate equivalents. The following map distinguishes those contracts:
| Flag | Meaning | Section or predicate equivalent |
|---|---|---|
--files |
Select the Files section | -S Files; it can compose with other package sections |
--lib |
Filter Files to the lib/ root |
--where "Root=lib", with exactly Files selected |
--tools |
Filter Files to the tools/ root |
--where "Root=tools", with exactly Files selected |
--tfm TFM with Files |
Match a complete directory segment on file rows | --where "Target=TFM"; --tfm all adds no predicate |
--path SELECTOR |
Select Files and apply package path/role selection | One literal file can use --where "Path=FILE"; repeated selectors, directory expansion, glob rules, @readme, and @agents retain their selector semantics |
--library [DLL] |
Inspect selected compile libraries, optionally one exact DLL | Changes the inspection subject; it is not a Files filter or section shortcut |
--namesake-library |
Select the Library whose assembly name matches the package ID | Selects a Library subject; it is not Root=lib or a filename filter |
--tfm TFM with library inspection |
Select the package target before Library scope | Uses package asset selection; it is not Files Target=TFM |
--roots |
Project distinct top-level folders from selected Files | A result projection, not a predicate or another section |
--tfms |
Select the Target Frameworks section | -S "Target Frameworks"; native output, formats, row selection, and Count are identical |
--versions, --versions-with-feed |
Enumerate available package versions, optionally with feed provenance | A separate version population; these do not select a section of one package version |
--content |
Read documents selected by --path |
A content operation; selecting Files inventories entries without reading their contents |
--lib and --tools have the same Files-only meaning throughout the package
command. They require one package and exactly Files, are mutually exclusive,
and do not select managed libraries. --tools does not request Library
inspection. Package acquisition retains its existing .NET tool-wrapper
redirection, so Files can inventory a wrapper's redirected payload package.
For example, System.Text.Json@10.0.12 --files --lib --tfm net8.0 inventories
its DLL and XML entries under lib/net8.0. --library System.Text.Json.dll --tfm net8.0 instead inspects the selected managed Library. The latter applies
package asset-role selection before inspecting metadata; a file path predicate
cannot replace that subject selection. Files Target=net8.0 can also match
entries under buildTransitive/net8.0 unless a Root predicate narrows them.
The separate version-listing and content modes reject explicit
-S selection because they render their own populations. Giving one of these
a section entrance would require preserving its row identity, ordering,
acquisition, and output contract; it would not follow from replacing its flag
with a Files predicate.
For one package with only --tfms or -S "Target Frameworks", -n,
--tail, and --rows A..B select complete target-framework rows after
framework folder enumeration, de-duplication, and TFM-priority ordering.
--tfms can compose with other sections. Its former standalone JSON array
is replaced by the section's established JSON contracts: plain --json
preserves the typed package object; field or column projections follow
Projected JSON. Bare output uses native TSV. Count, table, TSV, JSONL, and JSON
observe the same selected rows; add --lines only to clip rendered text.
For one package with exactly SourceLink: Files selected, -n, --tail, and
--rows A..B select complete library/type/URL rows after SourceLink collection
and --type filtering. Count, table, TSV, JSONL, JSON, --urls, and --raw
observe the same selected rows; add --lines only to clip rendered text.
Online range-version population is metadata-only: it enumerates versions
without acquiring a package payload. --count projects the version Count as a
scalar, including with --json; --count --envelope makes that same integer
the Content of InspectionEnvelope<int>. Without Count, --envelope retains
the complete directed version Document. --preview, --include-unlisted,
configured source options, and --versions-with-feed remain semantic
population inputs.
package query --explain returns installed query facets and CLI bindings as
HAL JSON without contacting NuGet. --json is optional. This command-only
terminal rejects package arguments, query/execution options, other output
formats, and dotted projections. Process-wide controls such as --offline
and --http-timeout remain available. Select needed embedded facets locally with
jq, or use explain package-query/query/facets/depends .hal --json for a
focused dependency-facet response. See
Installed capability explanation
for the worked workflow.
package query ID selects one exact package ID. A single terminal * selects
a literal package-ID prefix. Explicit --take bounds candidate work before
-n selects final package rows. Without explicit --take, a simple -n N
also bounds direct package-row acquisition to N, up to the 1,000-candidate
execution ceiling. Larger semantic heads remain valid and use that ceiling.
package query --ecosystem <id>, or --where "ecosystem=<id>", replaces the
package argument with one Ecosystem's population: its core packages in
authored order, each resolved exactly, then every package under each recorded
prefix, admitting each package once under the shared candidate bound. The
identity may be short (aspire) or canonical (ecosystem.aspire). It cannot
be combined with a package ID or prefix argument, and ecosystem= is the only
population term --where admits:
dotnet-inspect package query --ecosystem aspire -n 5
dotnet-inspect package query --where "ecosystem=ai" --where "license=MIT"find PATTERN --package-prefix PREFIX remains API search across
packages matching the prefix:
dotnet-inspect find Serialize --members --type System.Text.Json.JsonSerializer \
--package-prefix System.TextUse depends=<package-id> to require a direct dependency. Package Query
considers all package manifest groups by default; add
dependency-target=<TFM> to select one applicable dependency group instead.
dependency-target=all spells the default explicitly and remains distinct
from a manifest's real any group. Repeat depends to require every named
dependency under the same scope. Use
depends starts-with <literal-package-id-prefix> to require a direct
dependency whose package ID begins with that prefix. The match is literal and
case-insensitive; include a trailing . to express a dot-delimited family.
Use
depends-ecosystem=<canonical-ecosystem-id> to match a direct dependency
against the ecosystem's core packages (matched exactly) and its package
prefixes:
dotnet-inspect package query 'Microsoft.Extensions.*' \
--where "depends=Microsoft.Extensions.DependencyInjection"
dotnet-inspect package query 'Polly.*' \
--where "depends=System.Threading.Tasks.Extensions" \
--where "dependency-target=netstandard2.0"
dotnet-inspect package query 'Microsoft.Extensions.*' \
--where "depends=Microsoft.Extensions.DependencyInjection" \
--where "depends=Microsoft.Extensions.Configuration" --count
dotnet-inspect package query Microsoft.Extensions.Http \
--where "depends starts-with Microsoft.Extensions." \
--where "dependency-target=net10.0"
dotnet-inspect package query Aspire.Hosting.PostgreSQL \
--where "depends-ecosystem=ecosystem.aspire"Add dependency-depth=2|3|4 to an exact depends=<package-id> term for
source-authorized declared-range reachability. The match is inclusive: direct
dependencies and transitive paths within the selected maximum depth qualify.
It requires one exact dependency-target=<TFM>; the expensive query is
limited to five package candidates:
dotnet-inspect package query Microsoft.Extensions.Http \
--where "depends=Microsoft.Extensions.Primitives" \
--where "dependency-target=net10.0" \
--where "dependency-depth=2" --take 1The result is not a NuGet restore claim. Evidence counts matching declaration
edges and previews deterministic shortest paths built from declared ranges and
resolved exact package coordinates. The shared 160-character display budget
may shorten a preview, so it is not a complete path record or package
coordinate. The legacy depends-transitive spelling remains available when a
depth-2-or-greater-only match is required. Incomplete traversal remains a
visible failure.
Use dependencies=cross-prefix to find packages with a direct dependency from a
different first dot-delimited package-ID segment. It uses the same
dependency-target scope and remains nuspec-only:
dotnet-inspect package query 'Azure.*' \
--where "dependencies=cross-prefix"Use references=<simple-assembly-name> to find packages whose managed ref/
or lib/ assemblies declare that AssemblyRef across any target-framework
group:
dotnet-inspect package query 'Microsoft.Extensions.*' \
--where "references=Microsoft.Extensions.DependencyInjection.Abstractions" \
--take 20 -n 5This package-content term matches simple names case-insensitively and reports the matching framework and archive path. It does not resolve or traverse the reference.
Use the same key at Library grain to query top-level *.dll files in one
directory, or one installed or explicitly acquired platform reference pack:
dotnet-inspect library query ./artifacts/bin \
--where "references=System.Text.Json"
dotnet-inspect library query --platform runtime \
--where "references=System.Text.Json" --take 256 -n 10Library Query tests each candidate Library's direct AssemblyRef table;
repeated references terms are ANDed. --take bounds candidates scanned,
while -n, --head, --tail, and --rows select matching Library rows
afterward. Use library query -Q Libraries to discover the current vocabulary.
Native images beside managed Libraries in the directory are skipped; a
directory with no managed Library is a failed source. Missing or malformed
Metadata remains visible rather than silently becoming a nonmatch: rows and
--count print what was observed, with the failure warning and exit 1.
License selection also stays at the manifest boundary. license=any matches
any nuspec license declaration. Closed semantic values match nuspec metadata
without reading a license document: SPDX expressions match their exact
expression, and license=OSMF recognizes a declared OSMFEULA.* file:
dotnet-inspect package query wix \
--where "license=OSMF" --nuspec-only
dotnet-inspect package query Newtonsoft.Json \
--where "license=MIT" --nuspec-onlyNeither query opens the package archive. To inspect the license documents that the package actually ships, use the separate package-file section:
dotnet-inspect package wix@7.0.0 -S Licenses
dotnet-inspect package wix@7.0.0 -S Licenses --count
dotnet-inspect package wix@7.0.0 -S Licenses --print --rawPackage Query places the semantic result in Answer: MIT for the
Newtonsoft.Json query, OSMF for the WiX query, and true for
license=any. Supporting nuspec
declaration kind and value remain separate evidence. --count already emits
only the scalar count; --raw is useful with --print when only the selected
document body is wanted without package or section framing.
The exact nuspec <license type="file"> target is always included. The same
section also finds conventional text or Markdown license names and license
directories; notices remain a separate legal-document concern. Reading that
content is an explicit package projection and never informs license identity.
Add --where "key=value" to select product-owned Package Query terms, with one
matched package per row and semantic answers. Structured evidence remains
available in unprojected JSON and the inspection envelope. The initial CLI
vocabulary covers package metadata, direct and bounded transitive dependencies,
cross-prefix and ecosystem dependency classification, downloads, README presence, .NET tools
and their CLI v1/v2 format, assembly references, skill packages, and nuspec
license identity. Discover the admitted keys and values before constructing a
query. Discovery also reports the product-owned execution class independently
from the acquisition tier:
dotnet-inspect package query -Q Packages
dotnet-inspect package query Azure.Mcp \
--where "tool=true"
dotnet-inspect package query 'Azure.Mcp*' \
--where "tool-format=v2" --take 20 -n 5 --jsonlRepeat --where to combine terms; the engine rejects incompatible selections.
The broad tool=true term identifies the .NET tool package type from manifest
evidence. Use tool-format=v1 or tool-format=v2 for settings-based format
classification; the two specific formats are compatible filtering
alternatives. Selecting a package-content term authorizes the required archive
acquisition and defaults to at most 20 candidates. Use --nuspec-only to
reject a query that would require package content. Without explicit --take, a
simple -n N query pushes that semantic head into execution; explicit
--take instead fixes the candidate population before row selection. Reached
candidate limits and partial failures are reported explicitly. --count
counts the selected matching package rows that the same query would render,
with the same completion warnings and exit status. A reached candidate bound or
partial failure therefore yields an observed count, not the scope's total.
Incompleteness alone never withholds the count: only a search that fails before
evaluating any candidate prints none, and an unsatisfied strict --rows window
fails as it does for rows.
Package Query output adapts after execution. The default renders Packages
when at least one package matched and Query Summary otherwise. The summary
reports independent Candidates, Matches, and Evaluation Failures integer
columns, so a missing package (Candidates=0) remains distinct from an
existing package rejected by --where (Candidates=1, Matches=0). Select a
stable shape explicitly with -S Packages or -S "Query Summary"; explicit
Packages retains its empty table or array when no package matched. Bare -S
is invalid without a selector. Select @Query to compose
Packages and Query Summary in Markdown or JSON; table, TSV, and JSONL remain
one-section formats.
Breaking change: package search and patternless
find --package-prefix PREFIX have been removed. Use package query with an
exact package ID or an explicit terminal-star prefix.
An exact-version Package or explicit Platform Library search with --tfm
uses one short-lived Workspace internally and preserves each declaration's
exact coordinate and observation context without changing Find's established
result presentation:
dotnet-inspect find System.Text.Json.JsonSerializer \
--package System.Text.Json@10.0.0 \
--platform System.Text.Json \
--tfm net10.0Find defaults to TSV, with one stable header and unified Type and Member rows:
Coordinate, Kind, Source, Library, Pattern, Declaration, Signature,
Match, and Ecosystem. Kind is type or member; Declaration describes
the class, method, property, or other declaration category. Coordinates are
display addresses, not substitutes for the internally retained declaration
identity. Implicit Member matches are included in TSV. --columns selects
columns and --no-header suppresses the header.
Settled Member and wildcard Type rows print progressively during source
search. Ordinary Type patterns wait when implicit Member fallback could
supersede a weak match. Ecosystem searches publish each settled layer before
searching the next. Semantic row-selection requests (-n, --rows, --tail)
retain the existing buffered selection behavior; Count emits its final scalar.
Diagnostics stay on stderr, and already printed rows remain available if a
later source fails.
Explicit --markdown, table, JSONL, and plain type-search JSON retain their
existing shapes; plain JSON remains a root result array. When a selected
Package row feeds Type or Member inspection internally, the handoff preserves
the selected package-relative implementation asset and compatible TFM rather
than reopening a same-named reference assembly. Platform implementation-pack
observations decline exact internal reopening because public Platform syntax
resolves the reference view.
--ecosystem selects a named Ecosystem and its ancestors, searching each
layer's named platform and core-package populations nearest first. Canonical
IDs (ecosystem.aspire) and short names (aspire) are case-insensitive;
separate multiple selections with commas (for example, ai,blazor) or repeat
the option. --ecosystem all selects every shipped ecosystem. An explicit
Ecosystem cannot be combined with another Find source selector yet.
--tfm still applies to core packages. Each result includes an Ecosystem
column (or ecosystem JSON field) naming the layer that produced it;
ordinary Find output is unchanged. A finite -n stops at a layer boundary
and reports unsearched ancestors on stderr:
dotnet-inspect find '.Add*' --ecosystem aspire -n 20This searches Aspire's core packages first and, when they fill the window, does not realize ASP.NET Core or Runtime. Only named populations are searched: registered package prefixes do not trigger package-prefix discovery. If the entire selection has no named populations, Find fails with a prefix hint. Explicit Markdown output retains Find's existing Members-before-Results sections; rows remain nearest-first within each kind. Unbounded default TSV instead publishes each layer's settled unified rows before the next layer. Selection-bearing requests keep the existing selection order until the separately owned row-selection work adopts the unified stream.
package query ... --where "library-literal=TEXT" --tfm TFM adds decoded
string-literal qualification to the ordinary Package Query term plan. An exact
package ID selects its latest eligible listed version. A terminal-star
package-ID prefix evaluates at most five candidates; use --take 1..5 to
choose the candidate bound. Ordinary terms AND-compose and prequalify before
the query evaluates each survivor's selected implementation libraries for the
exact target framework.
dotnet-inspect package query Newtonsoft.Json \
--where "library-literal=Unexpected end when reading JSON" --tfm net6.0
dotnet-inspect package query 'Azure.Identity*' \
--where "downloads=1m" \
--where "library-literal=DefaultAzureCredential" \
--tfm net8.0 --take 5TEXT is a raw ordinal substring, not a type pattern: it is case-sensitive,
matches no wildcards, and preserves 1 through 1,024 decoded UTF-16 code units,
including leading/trailing whitespace and newlines. The Product planner records
CLI --tfm as non-user-selectable library-target=<canonical-tfm> intent. The
query covers selected primary implementation assemblies only, not every
assembly in a package. One output row is one final matching package; typed
selected-library context, the complete occurrence array, and bounded
method-token/IL-offset previews remain evidence on that package Result.
-n and --rows select final package rows, while --take bounds package
candidates. Candidate failures remain visible and prevent an unqualified
Count. Candidate packages are disposable: they are never added to the package
cache.
Select -S "Literal Strings" to itemize every physical matching ldstr as a
row with Package, Library, Method Token, IL Offset, and the complete decoded
Literal. Prefix and interior substring matches remain whole strings. Repeated
matches within one literal remain one physical row, while separate instructions
retain separate coordinates. This evidence projection does not change
package-grain row selection or Count.
Unprojected Package Query --json emits the complete owner-issued
PackageQueryDocument. --envelope emits that same Content with Share and
diagnostics using result kind package-query. Query controls such as
--where, --take, and required semantic --tfm remain admitted; row
selection, Count, projection, discovery, section selection, and competing
formats are rejected. Typed incomplete or failed Content is still emitted
before a nonzero exit.
Each evaluated candidate carries a Root reopening token. Hand that token back
to reopen exactly the Root the result came from:
dotnet-inspect workspace --root-request TOKENThe token is opaque, credential-free, and exact. workspace --root-request
rejects a token this tool did not issue, and reports an unauthorized producer
or unavailable content instead of opening a different Root that happens to
share the package id and version.
Append --share packet or --share url to author the complete durable
Workspace definition. Ordinary authoring performs no Package acquisition or
live Workspace construction. The selected scalar is the workspace command's
result on stdout, rather than the additive stderr side output used by noun
commands:
dotnet-inspect workspace \
--package System.Text.Json@10.0.0 \
--tfm net10.0 \
--register-package-prefix Microsoft.Extensions. \
--share packetDirect Package and registration inputs become one schema-version-3 definition and canonical format-3 packet. Registration-only authoring also remains resource-free. Normalized-equivalent Package coordinates are emitted once, while registration options retain their authored cross-kind order. A scanner-bearing Ecosystem fails visibly as non-projectable; the command never drops its scanner to manufacture a packet.
Declare an authentication-required package source to author a credential-free format-5 Inspect Web URL for a private-feed Workspace:
dotnet-inspect workspace \
--package Private.Package@1.2.3 \
--tfm net10.0 \
--nuget-source-auth-required \
https://nuget.pkg.github.com/example/index.json \
--share urlInspect Web prompts once per exact authentication-required endpoint for a username and personal access token. Credentials remain in page-session memory only: activation-local copies are cleared after settlement, while the active realization or incumbent-recovery binding may retain them until replacement or disposal. They are not placed in the packet or URL, retained definition, browser storage, logs, diagnostics, or telemetry. Reloading prompts again. Cancellation or failure before publication leaves the prior visible Workspace unchanged; if recovery after cutover also fails, Inspect Web enters a blocking retry state rather than exposing the failed tentative Workspace. Source declarations that do not require authentication activate without a prompt.
Add --make-package-dependencies-explicit to acquire the bounded manifest for
every direct Package member, resolve its exact direct dependencies for the
member's effective target, and append those dependencies to the same context
before emitting the derived packet. PackageHouse uses a source-supplied
manifest when available and otherwise acquires only the root nuspec from the
package archive:
dotnet-inspect workspace \
--package Microsoft.Extensions.Logging.Abstractions@10.0.0 \
--tfm net10.0 \
--make-package-dependencies-explicit \
--share packetThe transformation also accepts a canonical Base64URL packet string through
--packet. Existing members retain their order; new members use owner-issued
dependency order and are deduplicated only within each context. The command
emits no packet unless every selected Package manifest settles and the complete
derived definition remains projectable. Unlike ordinary resource-free
--share, this explicit transformation admits --preview and NuGet source
policy because acquisition is part of the requested operation.
--packet accepts canonical Base64URL packet text. With --share, it validates
the input and emits the canonical packet or selected URL without complete
restoration. The --share selection governs this output scalar; inventory
output formats apply only when --share is absent.
Durable definition output cannot be combined with --kind, inventory row
controls, --root-request, or Package Navigation selectors. Explicit NuGet
source policy is accepted only for dependency enrichment or coordinate
replacement; --preview is accepted only for dependency enrichment.
To edit one direct Package coordinate in an existing scenario, first list the packet's typed components and copy the canonical Package path:
dotnet-inspect workspace component list --packet "$w"
dotnet-inspect workspace package update \
packages/avalonia@11.3.14/net8.0/~ \
--packet "$w" --version 12.1.2
dotnet-inspect workspace package update \
packages/avalonia@11.3.14/net8.0/~ \
--packet "$w" --tfm net9.0 --share url
dotnet-inspect workspace package update \
packages/avalonia@11.3.14/net8.0/~ \
--packet "$w" --version 12.1.2 --json --envelopeUse --version, --tfm, or both, and select either scalar --share
output or --json --envelope. The envelope includes the derived Share,
actual Scope outcome, retention/fallback decision and diagnostics. Scalar
output contains only the complete resulting packet/URL; fallback diagnostics
go to stderr. No input packet is emitted as a successful failure fallback.
Source options are allowed for this acquisition-backed route.
Replacement preserves unrelated contexts, registrations, row order, focus,
and committed views. Format 4 can retain an active Library, Type or Member
and its exact inspector. For example, changing Avalonia@11.3.14 to 12.1.2
on net8.0 follows Avalonia.Data.MultiBinding from Avalonia.Markup
to its defining Avalonia.Base Library; its constructor can follow separately.
An explicitly active Library stays paired with that Library instead.
Both Versions must be exact pins. Changed TFMs require an unsubscribed
single-member context; shared-context TFM changes, floating selected sources,
ambiguous source positions and query-bearing scenarios are visibly refused.
Do not combine Package update with dependency enrichment, direct construction,
inventory controls, or
--active-package/Library/Type/Member/inspector selectors: the packet owns that
intent. Browser coordinate-control and capture adoption remain separate.
Use the same canonical paths for resource-free immutable Package edits:
dotnet-inspect workspace package add Markout@0.35.2 --packet "$w"
dotnet-inspect workspace package remove \
packages/markout@0.35.2/net10.0/~ --packet "$w"The default workspace output is the typed top-level inventory. Package
occurrences appear in committed Scope order, followed by inert registrations
in declaration order. Overlap is preserved because committed content and
registration intent are different facts:
dotnet-inspect workspace \
--package System.Text.Json@10.0.0 \
--package Markout@0.35.2 \
--tfm net10.0 \
--register-library System.Text.Json@10.0.0/System.Text.Json@10.0.0.0 \
--register-package-prefix Microsoft.Extensions. \
--register-ecosystem aspireUse repeatable --kind package|exact-library|package-prefix|ecosystem to
select inventory kinds without changing Workspace construction. -n N,
--tail, and --rows A..B select complete typed entries after that filter;
--count observes the selected entries, while --lines explicitly selects
rendered lines. JSON and JSONL retain the typed entry arms and their portable
details. --verbose adds each Package producer,
requested/selected/effective target, runtime identifier, and asset-selection
status to human output.
Restore one current-format canonical Base64URL Workspace packet string for inventory instead of supplying direct construction options:
dotnet-inspect workspace --packet PACKETPacket input is mutually exclusive with direct Package and registration
construction. Workspace Definitions performs complete restoration, including
group and non-Package context intent and retained Navigation state, before the
CLI enters the inventory operation. CLI refinement of that restored Navigation
state is intentionally deferred. Top-level workspace --packet combines only
with inventory controls when --share is absent; nested component and Package
commands own packet editing.
workspace never selects an occurrence implicitly, even when the Workspace
contains exactly one Package.
Add --active-ecosystem ID to select one exact Ecosystem registration from
the current top-level inventory receipt. Short IDs such as aspire normalize
to the canonical ecosystem.aspire registration. The result activates the
Ecosystem subject and its ecosystem.overview lens without acquiring Packages,
Libraries, platform assets, or population:
dotnet-inspect workspace \
--register-ecosystem aspire \
--active-ecosystem aspireThis acquisition-absence claim is unverified by a dedicated composition gate; the Release tests verify the visible structural result.
Add --active-package N to evaluate one exact occurrence by its one-based
Workspace order. The detailed result includes the active subject, complete
Workspace-to-Member hierarchy slots, Library asset IDs, bounded Type and Member
inventories, target-aware lens availability, and retained diagnostics.
For this CLI consumer, the current active catalog entries are available once
Navigation admits the exact subject because those entries execute on demand;
query and result non-success remains inside the selected entry. This does not
prevent another producer from supplying explicit unavailable or failed
availability evidence to the Navigation evaluator:
dotnet-inspect workspace \
--package System.Text.Json@10.0.0 \
--tfm net10.0 \
--active-package 1Library asset IDs, Type full names, and Member stable selectors in that output
can drive an exact stateless descendant plus lens request. Copy those selector
fields verbatim: line separators, tabs, rendering hazards, and literal
backslashes, plus characters reserved by Markdown tables, use a reversible
backslash transport spelling that workspace decodes before exact selection:
dotnet-inspect workspace \
--package System.Text.Json@10.0.0 \
--tfm net10.0 \
--active-package 1 \
--library compile:lib/net10.0/System.Text.Json.dll \
--type System.Text.Json.JsonSerializer \
--lens .compareAdd --member <stable-selector> and use a member.* lens for a Type-to-Member
destination. The contextual .<name> spelling above lowers through the View
Facet Registry to the exact canonical ID for the destination kind; full IDs
such as type.compare remain the durable spelling in output, packets, and
cross-host handoffs. --all-libraries uses the aggregate Library as the source
while --library still names the destination Type's exact defining Library.
A source-only --all-libraries request omits --library; supplying both
without a Type destination is rejected. Root-only and explicit-empty Packages
have no All-libraries subject and return a typed non-success snapshot instead
of throwing.
Selector misses retain the evaluated snapshot and diagnostics. The command claims that a Type or Member is not present only when its scoped inventory is complete; otherwise it reports incomplete evidence. Unavailable, failed, inapplicable, and unknown destination lenses leave both requested halves uninstalled and return nonzero with typed diagnostic data. JSON and JSONL Type and Member rows carry the defining Library asset ID, and Member rows carry both containing and declaring Type names. Process-local Workspace, occurrence, generation, action, and authority identities are omitted.
dotnet-inspect project ./src/DotnetInspect.Cli -S Skills
dotnet-inspect project ./src/DotnetInspect.Cli -S @Project
dotnet-inspect project ./src/DotnetInspect.Cli -S Skills -n 1 --tail
dotnet-inspect project ./src/DotnetInspect.Cli -S Skills --print --row 1
dotnet-inspect project ./src/DotnetInspect.Cli -S README
dotnet-inspect project ./src/DotnetInspect.Cli -S README --print --row 1
dotnet-inspect type Command --project ./src/DotnetInspect.Cli
dotnet-inspect member Command --project ./src/DotnetInspect.Cli -S "Member Index"
dotnet-inspect library ./artifacts/obj/ILInspector.Metadata/release/ILInspector.Metadata.dll -S SignalsFor API and relationship commands, --project means an existing
project.assets.json restored-assets context. Passing a .csproj or project
directory only locates that file; dotnet-inspect does not restore or build.
The project command reads only valid package Skills and root README.md
documents listed by the existing restore output. It does not interpret package
AGENTS.md or PROJECT.md files. Select @Project to compose both document
inventories, or select Skills for that focused view. With exactly one
document section selected, -n, --tail, and --rows A..B select complete
document rows before Count, structured output, projection, or print/bare
lowering. Add --lines only to clip rendered text. Multi-section @Project
output retains its independent section row sets and rendered-line -n
fallback.
An exact type target with no competing operation or projection defaults to
the compact public Type hierarchy; --tree explicitly selects the same Tree
profile. A short name that platform find resolves to one exact Type, such as
type JsonSerializer, renders the same Tree. The Tree lists one row per Member
group under its category, and a category counts its Member groups. It shows no
overload Counts; use member <Type> <Name> for a Member group's overloads.
static class System.Text.Json.JsonSerializer
├─ Properties (1)
│ └─ IsReflectionEnabledByDefault
└─ Methods (10)
├─ Deserialize
└─ …
--all includes non-public and hidden Member groups. --mermaid selects a
standalone graph TD over that same Type, category, and Member-group
hierarchy. It requires one exact Type and cannot be combined with discovery, match,
listing/glob/namespace-prefix targets, member filters, row or line windows,
verbosity-driven output, another format, or a selected section. It fails with
no stdout when compact inspection is unavailable (including managed
netmodules or bounded inventory), even if an XML documentation sidecar is
present. Tree retains the legacy Type rendering fallback when compact
inspection is unavailable. Count, sections, Markdown, tables, JSON, filters,
and windows keep their existing independent routes.
An explicit verbosity keeps the verbosity-driven Type rendering rather than the
compact Tree. -v:m adds the base Type and Member signatures, with an overload
Count in place of the signatures for each overloaded constructor, method,
operator, explicit interface implementation, or extension group; properties
(including indexers) and events list each signature, and fields list each name. -v:n and -v:d list every overload signature.
That rendering rejects -v:q; add --markdown for compact sections.
dotnet-inspect type System.Math --platform System.Private.CoreLib --tree
dotnet-inspect type System.Math --platform System.Private.CoreLib --mermaidThe type and member commands render a lone explicitly selected section in its
declared shape's native format when no format is named, per
Section shapes: a Table streams its TSV rows
(type System.String -S Methods, member System.String.Trim -S Methods, the
Type Info record as field/value TSV, Signature as its one row) and a Text
prints its undecorated payload (Source, Decompiled Source,
IL, API Declarations, PDB Source, Source Diff, Annotated Source, the
overlays, and Finding Census). The shape decides, not a list of section
names. Annotated Source Document and Call Graph keep their composed
rendering: the first is a document with no bare payload, the second a graph.
An explicit format, an environment default, --print, --row, --tree,
--count, a projection, a shape flag, discovery, an envelope, or an analysis
query keeps its existing behavior, and selecting several sections composes
Markdown as before. Scalar sections (Type Info, API Info, and every Text
payload other than Source) have no rows: selecting one alone with --count
or --rows fails before acquisition and names an inventory section as the
alternative; a bare -n on it is the rendered-line window. Signature is a
one-row inventory whose row is the resolved member, so --count answers 1.
Count maps over several sections keep their per-section meaning.
Implementers and Derived Types are explicit, expensive Type sections in
@Relations. They preserve the exact Type occurrence selected for ordinary
Type output while scanning the selected source population. Platform Type
relations scan the runtime, ASP.NET Core, and .NET Standard populations by
default; an explicit --framework deliberately narrows the scan to that one
family. An implementation-only Platform focus such as
System.Private.CoreLib remains the selected Type occurrence while hierarchy
binding uses its exact corresponding reference definition. Missing or
ambiguous correspondence fails visibly. Count and Rows are independent
producer terminals: Count-only requests no rows, and a finite head or
closed-range --rows window reaches the producer as a finite prefix bound. An
unbounded request uses a 10,000-row safety bound and reports continuation as
incomplete output. Tail selection is rejected because the forward-only
producer cannot satisfy it without privately materializing the complete
population. Package relation rows include the package-relative asset in
Source, so distinct ref, lib, or runtime occurrences remain
distinguishable.
Every other type or member Text with a bare payload (API Declarations on the
type command, Decompiled Source, Annotated Source, PDB Source, IL,
and the overlays) has a fact row: --table, --tsv, and --jsonl emit its
section, line count, and character count. Source Diff keeps its own row
form, the comparison metadata and summary. --json on any of them except
API Declarations emits the facts plus the complete payload as content;
API Declarations keeps its inspection envelope, whose content carries the
complete text. A fact row is not
an inventory, so --count and --rows stay rejected. Composed Markdown
still shows each Text's body, so -S "Decompiled Source,IL" reads side by
side.
Source is the Text whose rows are its exact lines, per
Source document cardinality:
--count reports the line count, which includes the empty final line after a
trailing line terminator; --rows selects lines, which native output,
--markdown, and --plaintext print as text; and --table, --tsv, and
--jsonl emit one row per line with its number, UTF-16 start offset, content,
and terminator, which --columns and --fields can project. --jsonl
carries each line's content exactly; --tsv and --table normalize a tab
inside a line to a space, as every TSV in this CLI does. --json stays
the complete Source document, so it rejects --rows. Default output is
unchanged, and -n remains a rendered-line window.
dotnet-inspect type string --tree
dotnet-inspect member System.String.Trim:1 -S Source --count
dotnet-inspect member System.String.Trim:1 -S Source --rows 2..3
dotnet-inspect type --platform System.Text.Json -n 1 --tail --json
dotnet-inspect find JsonSerializer --platform System.Text.Json
dotnet-inspect member JsonSerializer --package System.Text.Json -m Serialize
dotnet-inspect member --explain
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize --explain
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 --explain
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize --explain .tips
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize -E
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 -S @Source
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 -S "Finding Census" --json
dotnet-inspect member JsonElement --package System.Text.Json DeepEquals:1 -S Facts --json
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 -S Calls
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 -S Calls -n 1 --tail --json
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 -S Callers
dotnet-inspect member System.ThrowHelper --platform System.Private.CoreLib --all \
-m ThrowArgumentNullException:1 -S Callers -n 1 --tail --json
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 --source-parts --json
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 --print --part xml-docs
dotnet-inspect member JsonSerializer --package System.Text.Json Serialize:1 \
--print --part body --markdown
dotnet-inspect type JsonSerializer --platform System.Text.Json -S "Source Files" --urls --json-array
dotnet-inspect library address 0x060002EA+0x0 \
--package System.Text.Json --library System.Text.Json.dllA bare ordinary method name selects its MemberGroup. Its default output is a
native Tree rooted at one compact identity line and containing every public,
non-hidden exact overload; explicit --tree renders the same population.
This remains a MemberGroup when the selected version has one overload.
Use --columns "Signature;Description" to request compiled documentation for
each returned exact overload and render the bounded population as a table.
Select an exact Member with an ordinal or digest when the intended subject is
one declaration rather than its overload family. Its native default is one
singular Signature view containing the display signature, digest, and canonical
signature, followed by its independently settled compiled-documentation
outcome, with no sibling Rows or Count. Missing or failed documentation remains
visible without invalidating the resolved Member document. The one-based
ordinal selects from the current MemberGroup's stable baseline order; after
resolution, the owner-issued exact identity and population binding replace that
ordinal as the durable subject.
--all is an API visibility option. API-level commands use their ordinary
public-facing declaration population by default; add --all when the
question includes non-public, hidden, or obsolete declarations. It is not a
general "analyze every implementation" option.
Implementation-oriented sections define their own population. For example,
Library Metrics summarizes the selected Library's admitted implementation
bodies, including private and compiler-generated bodies when they are part of
that population, without requiring --all. If an aggregate result identifies
a non-public body and you follow it into an API-level command, that separate
command may require --all to resolve the declaration.
Some body-oriented commands also begin with an API lookup. In those commands,
--all can be necessary to resolve a non-public, hidden, or obsolete Type or
Member root. Once resolved, the implementation operation uses its complete
admitted body population by default; --all does not widen traversal, select
more relationships, or request every analysis.
-k/--kind filters the logical C# declaration kind. Explicit interface
properties and events compose their accessors into one property or event
row, so select them with -k property or -k event.
-k explicit-interface-implementation selects explicit method
implementations that are not composed into a property or event declaration.
Exact library ... -S "Library Metrics" --json emits the complete Research
LibraryStructuralReportDocument: the Analysis receipt and coverage,
numeric distributions and maximum-body identities, async disposition, typed
type summaries, cross-type relationships, Analysis diagnostics, and the
methodology-v2 Type-leverage document. Type leverage preserves exact metadata
type identities, the separately ordered sea-level and mountain-peak rankings,
raw directional degrees, one nullable dominant pole per Type, role and evidence
qualifications, Metadata signature-use and Analysis body-use receipts, and
Graph work receipts. A Type that qualifies at both directional maxima receives
the larger-degree pole; an exact degree tie receives no pole while remaining
in both rankings.
--envelope emits identical content plus Share and operation diagnostics:
dotnet-inspect library Markout.dll --package Markout@0.35.2 \
--tfm net10.0 -S "Library Metrics" --json
dotnet-inspect library Markout.dll --package Markout@0.35.2 \
--tfm net10.0 -S "Library Metrics" --envelopeThis complete transport is separate from Markout lowering. Markdown, table,
TSV, and JSONL retain their existing Library Metrics row contracts and add
separately named Sea-Level Types and Mountain-Peak Types row groups. Those
groups present the Research-issued order, named degree, role, exact type key,
and qualification summary without blending the rankings into one score.
Complete
JSON requires one exact Library, one target framework, and the exact singleton
section; it rejects row, field, column, Count, discovery, payload, and
competing presentation projections rather than truncating Content. Type
summaries carry exact metadata keys separately from display labels, and every
relationship endpoint names a retained summary, so a Copilot App can render an
SVG without recovering identity from display text. Library Metrics Share is
currently nonProjectable.
Exact library ... -S "Dependency Structure" reports internal namespace
dependencies derived from whole-library method evidence. Namespace edges are
the section's QuerySpace rows. Nodes show Type count and topological level;
cycle members are emphasized and carry their exact cycle index. Isolated
namespaces remain visible in an unwindowed graph:
dotnet-inspect library FluentValidation.dll \
--package FluentValidation@12.1.1 --tfm net8.0 \
-S "Dependency Structure"
dotnet-inspect library FluentValidation.dll \
--package FluentValidation@12.1.1 --tfm net8.0 \
-S "Dependency Structure" --mermaid
dotnet-inspect library FluentValidation.dll \
--package FluentValidation@12.1.1 --tfm net8.0 \
-S "Dependency Structure" -n 10 --head-n, --head, --tail, and --rows select namespace edges before graph
rendering; a selected graph retains only edge endpoints. --count executes the
namespace-edge QuerySpace Count terminal. The section is explicit-only and is
not added by verbosity or category selection. Markdown and tabular formats
lower the Markout graph as an edge table; --mermaid lowers the same graph as
a diagram.
Exact -S "Dependency Structure" --json emits the complete Research document:
Analysis and population receipts, Type and namespace nodes, internal and
external edges, cycles, explanations, completeness, and diagnostics.
--envelope emits the same Content plus a currently nonProjectable Share.
Complete JSON requires one exact Library and one target framework, and rejects
row, field, column, Count, discovery, print, shape, and competing presentation
projections rather than truncating Content.
Exact library ... -S "Name Families" reports the most prevalent one- and
two-word Type-name suffix families in one Library. The default all
population covers every Type definition. --name-family-population selects
ordinary, generated, mixed, or unknown when exactly bound source
provenance is available:
dotnet-inspect library FluentValidation.dll \
--package FluentValidation@12.1.1 --tfm net8.0 \
-S "Name Families" -n 10 --head
dotnet-inspect library FluentValidation.dll \
--package FluentValidation@12.1.1 --tfm net8.0 \
-S "Name Families" --name-family-population ordinary --count-n, --head, --tail, and --rows are semantic QuerySpace selection over
family rows; --count executes the corresponding QuerySpace Count terminal.
The section is explicit-only and is not added by verbosity or category
selection.
Exact -S "Name Families" --json emits complete Content: every Type word and
residual row, every population and family member address, methodology and
oracle identity, provenance qualification, and partition receipts.
--envelope emits the same Content plus a currently nonProjectable Share.
These complete transports accept the population selector but reject row,
field, column, Count, discovery, print, and shape projection. Markdown, table,
TSV, and JSONL lower only the already selected family rows and show at most
five labeled Type examples per family.
Exact -S "Architectural Families" composes those suffix families with the
Library's exhaustive signature-only structural evidence. Each family row
reports foundation, hub, orchestrator, unclassified-role, sea-level, and
mountain-peak Type counts together with its population, source provenance, and
structural-evidence disposition:
dotnet-inspect library FluentValidation.dll \
--package FluentValidation@12.1.1 --tfm net8.0 \
-S "Architectural Families" -n 10 --head
dotnet-inspect library FluentValidation.dll \
--package FluentValidation@12.1.1 --tfm net8.0 \
-S "Architectural Families" --name-family-population ordinary --countExact -S "Architectural Family Types" exposes the supporting Type rows from
the same managed operation. Each row retains its artifact-scoped Type
identity, one- and two-word families, source disposition, signature degrees,
issued structural role and pole, and structural-evidence disposition:
dotnet-inspect library FluentValidation.dll \
--package FluentValidation@12.1.1 --tfm net8.0 \
-S "Architectural Family Types" -n 20 --headBoth sections are explicit-only. -n, --head, --tail, and --rows
select the chosen family or Type rows before Markout lowering; --count
counts that row set. --name-family-population applies to either exact
section. The operation reuses the complete name-family population and one
exhaustive signature-only structural acquisition; it does not request method
bodies or Library Metrics implementation profiles.
Exact --json from either section emits the same complete architectural-family
composition document rather than only the selected presentation rows. It
contains every exact Type row, every population and family support address,
both owners' methodology and work receipts, structural qualifications, and
composition accounting. --envelope emits identical Content plus a currently
nonProjectable Share. Complete transports require one exact Library and
target framework and reject row, field, column, Count, discovery, print,
shape, and competing presentation projections.
See API and implementation population scope for the distinction between API visibility, implementation completeness, and package-library selection.
For a Type catalog with an explicit package, library, platform, or project
source, including positional or -t Type globs, -n, --tail, and
--rows A..B select complete types after type, kind, and unsafe filtering.
Markdown, table, TSV, JSONL, and JSON observe the same selected types;
assembly-level companion evidence such as Type forwarders remains visible. Add
--lines only to clip rendered text. Exact-type, selected-section, discovery,
shape, match, and ambiguous commandless modes retain rendered-line fallback.
Numeric -t is a literal Type filter, not a row-count spelling.
With exact member -S Calls, -n, --tail, and strict --rows A..B
select complete direct call-site rows after analysis of the selected overload
and its generated evidence methods. Repeated calls to the same target remain
distinct. Markdown, table, TSV, JSONL, structured JSON, and Count observe the
same selected call sites in their existing IL-offset order. Add --lines only
to clip rendered text. Callers, Call Graph, @Calls, mixed sections,
discovery, and Calls included only by verbosity retain their existing row
contracts or rendered-line fallback.
With exact member -S Callers, -n, --tail, and strict --rows A..B
select complete deduplicated caller-site rows after the selected target
overload and all authorized caller scopes have been scanned. Markdown, table,
TSV, JSONL, structured JSON, and Count observe the same selected call sites,
including Source when the completed caller rows came from multiple assemblies.
Add --lines only to clip rendered text. Calls, Call Graph, @Calls,
mixed sections, discovery, and scope-implied Callers without the exact selector
retain their existing row contracts or rendered-line fallback.
Exact member ... -S "Call Graph" --json emits the complete semantic
InspectionGraphDocument: typed member subjects, directed call edges,
physical call-site occurrences, characteristics, seeds, completeness limits,
and failures. --envelope emits the identical document under content plus
Share and diagnostics:
dotnet-inspect member System.Text.Json.JsonSerializer Serialize:1 \
--platform System.Text.Json -S "Call Graph" --json
dotnet-inspect member System.Text.Json.JsonSerializer Serialize:1 \
--platform System.Text.Json -S "Call Graph" --envelopeThis complete transport is separate from Markout lowering. Markdown,
Mermaid, tree, table, TSV, and JSONL keep their existing presentation and row
contracts. Complete Call Graph JSON requires the exact singleton section and
rejects row or line windows, fields, columns, Count, payload projections, and
competing presentation formats rather than truncating the semantic document.
Call Graph Share is currently nonProjectable; a Copilot App may render the
typed content as SVG without recovering graph semantics from Mermaid or
display labels.
Focused member -S "Source Locations" --json reports member, document, and
pdb_span without fetching source text or adding generic section/row wrappers.
PDB spans describe executable source, not the entire declaration.
Opt in with --source-parts to acquire checksum-verified source and discover
lexical ranges. --print --part member|xml-docs|attributes|signature|body
prints the selected part; both gestures imply Source Locations when -S is
omitted. The full member includes attached XML documentation and attributes;
the body includes its delimiters. Missing parts fail visibly, and unqualified
--print still prints the whole source document. These are lexical source
parts, not parsed documentation or stronger physical-authorship evidence.
Human-readable part output restores the original first-line indentation;
structured JSON content remains the exact token-selected text.
Use a Workspace packet as reusable aggregate context when the Type may be defined by any Library in its selected context:
packet=$(dotnet-inspect workspace \
--package System.Text.Json@10.0.0 \
--tfm net10.0 \
--share packet)
dotnet-inspect type System.Text.Json.JsonSerializer \
--workspace "$packet"
# Given a schema-4 packet from a Type-capable producer:
dotnet-inspect type System.Text.Json.JsonSerializer \
--workspace "$schema4_packet" \
--share packettype --workspace requires one exact Type and one canonical Base64URL
Workspace packet string; URL input is rejected. It uses the packet's selected
context independently of its focused tab. The packet is the sole location
source, while the receiving command still applies its own NuGet source,
credential, cache, and offline policy. Optional --share keeps ordinary Type
output on stdout and writes the derived schema-4 packet or URL as the final
stderr line when the input is schema 4. A workspace --share producer without
source declarations emits schema 3; one with source declarations emits schema
5. Schema 3 remains a valid inspection input but cannot encode the derived Type
scenario; requesting Share from that input fails visibly without discarding
the Type output.
dotnet-inspect diff --package Markout@0.33.0..0.35.2
dotnet-inspect diff --platform System.Runtime@9.0.0..10.0.0 --breaking
dotnet-inspect type System.Text.Json.Schema.JsonSchemaExporter --package System.Text.Json@9.0.0..8.0.6 --match
dotnet-inspect member System.Text.Json.JsonSerializer Deserialize:1 --package System.Text.Json@9.0.0..10.0.0 --match
dotnet-inspect timeline --package Markout@0.33.0..0.35.2 --type Markout.MarkoutWriterOptions --members --at all -S Transitions -n 10 --tail
dotnet-inspect timeline --package System.Text.Json@8.0.0..9.0.0 --type System.Text.Json.JsonSerializer --members --at all -S Evaluations --rows 2..type/member --match follows one source API coordinate across exactly two
literal package versions, preserving the written direction. Member matching
resolves its selector only at the source; the destination selector comes from
API correspondence, so a moved overload ordinal is not independently replayed.
Matching is declaration-only: an ordinal selecting a singleton Property/Event
accessor is refused; omit the accessor ordinal to match that declaration.
Ordinals selecting among overloaded indexer declarations remain supported.
Use --tfm to select one API surface and optional --library to narrow the
source Library. --all widens source selection to the existing IncludeAll API
scope; destination declaration matching remains strict and does not apply a
second accessibility filter. Plain text and Markdown render the typed result;
--json emits complete Content, and --envelope adds Share and diagnostics.
This is separate from root match, which compares implementation structure.
Ordinary API diffs with one Library at each endpoint consume the shared
Library API Diff contract
intended for website Compare. This includes single-Library packages, platform
libraries, and local DLL pairs. --type narrows the complete comparison;
--all widens its API scope. The endpoints must be versions of the same
logical Library (assembly name, culture, and public-key token).
On this route, unprojected --json serializes the complete
LibraryApiDiffOutcome, replacing the former {changes: ...} presentation
view. Use --envelope for that same Content plus Share and diagnostics;
--compact controls whitespace for either complete JSON boundary, not projected
or other Diff operations. For example:
dotnet-inspect diff --package System.Text.Json@9.0.0..10.0.0 --tfm net8.0 --envelope --compactEnvelope output accepts --all, but rejects Type/classification filters,
section selection, explicit verbosity, row/line windows, and non-API modes.
Explicitly projected JSON, such as -S Changes --json, retains its existing
presentation schema. Share is explicitly non-projectable for comparison
endpoints; it is not a replay URL.
The exact local-Library Implementation Diff route also exposes complete typed
Content. Exact section selection chooses the operation rather than projecting
its result; --type and --member remain semantic request inputs recorded in
the Content:
before=old/Foo.dll
after=new/Foo.dll
dotnet-inspect diff \
--library "$before..$after" \
-S "Implementation Diff" --type Foo.Widget --envelopeUnprojected --json emits the same ImplementationDiffDocument found at
--envelope.content; --compact controls whitespace. The document retains
Before/After assembly identity, MVID and provenance, structured C# and IL
evidence, complexity changes, and per-mechanism coverage. Share is currently
non-projectable for the ordered endpoint pair. Package/platform ranges, PDB
Source enrichment, row or field projection, alternate formats, and additional
sections remain on the existing rendered paths or are rejected for complete
transport.
Changes without a compatibility classification remain visible under
Other API Changes, or as unclassified rows in detailed output. They are
not classified as breaking or additive. An incomplete or rejected comparison
returns nonzero and says not compared, rather than claiming no changes.
Multi-Library packages, member-filtered diffs, Analysis Diff, Implementation
Diff, analysis-set views, and mixed-section requests retain their existing
routes; this adoption does not add the website Compare UI.
Use -S @Diff to compose the Changes, Analysis Diff, and Implementation Diff views. Annotated Source Diff, Complexity Context, Structural Context, Summary, and Transitions remain exact-name sections because
their focused semantics do not compose with those comparison views.
--analysis selects which keyed Finding comparisons a pairwise diff runs.
It takes one or more analysis identities, comma-separated or repeated, and
-S then selects views of their result. diff -D, --help, and
explain analyses list the identities: api, api-attribute,
allocation, call-site, unsafety, csharp, il, and
string-literals. The request's surface comes from its filters: any
--member is Member, otherwise --type is Type, otherwise Library. The body
analyses (allocation, call-site, unsafety, csharp, il) take exactly
one --member; api-attribute takes --type; string-literals takes the
Library surface and exactly one --where predicate.
dotnet-inspect diff --package System.Text.Json@9.0.0..10.0.0 \
--type System.Text.Json.JsonSerializer --member "Serialize:1" \
--analysis api,call-site,allocation
dotnet-inspect diff --package Microsoft.Azure.SignalR@1.20.0..1.33.1 \
--analysis string-literals \
--where "Literal contains https://"
dotnet-inspect diff --library old/Foo.dll..new/Foo.dll \
--analysis string-literals --where "Literal starts-with https://" --jsonString-literal predicates use exact ordinal UTF-16 matching. The key is
case-sensitive Literal; the supported operators are contains and
starts-with. Each Transition row retains the complete decoded literal. Two
matching positions within one literal still produce one row, while separate
physical ldstr instructions remain separate occurrences. Package diffs with
several Library assemblies compare corresponding assemblies by file name and
name each assembly in the Transition target. An assembly present at only one
endpoint contributes added or removed literals. The single-Library target
remains the package name.
Omitting --analysis selects the default set, api, so diff A B output is
unchanged. One selected analysis defaults to Changes for api and to
Transitions otherwise; several default to one Summary row per analysis
with its outcome (Compared, Unavailable, or Failed) and its Added,
Removed, Changed, and Present counts, each counted over the Transition
rows its analysis emits (string-literals emits no Present rows, so its
Present count is 0). -S Transitions lists each
selected analysis's per-Finding transitions in selection order; at the Type
surface api shows its api.type rows and then its api.member rows.
Changes requires api. Transitions requires a selected analysis that
declares it at the request surface: Type and Member analyses do so at their
surfaces, while string-literals declares Library Transitions.
--breaking, --additive, --changed, and --name-only refine Changes
only. Unknown, duplicate, empty, surface-unsupported, and wrong-cardinality
entries are all reported before acquisition.
Pairwise --finding and -S "Finding Transitions" are retired: they fail
with guidance naming the --analysis identity and -S Transitions.
--history keeps --finding and does not accept --analysis yet.
--analysis does not combine with Analysis Diff, Implementation Diff,
Annotated Source Diff, Complexity Context, or Structural Context.
--json emits the shared DiffAnalysisDocument; --envelope emits that same
Content plus Share and diagnostics. Both retain the exact string-literal
predicate in the comparison context.
Select Annotated Source Diff with exactly one package Type and Member to
emit the complete portable AnnotatedSourceDiffDocument. C# comparison is
included by default; --il includes the corresponding IL instruction
comparison. The document retains exact physical endpoints, type-forwarder
hops, per-medium line maps into its contained source documents, and
product-issued text comparisons. A Member present on only one endpoint has a
typed absent side and no manufactured two-sided comparison. This route
requires --json; --compact controls whitespace.
dotnet-inspect diff \
--package System.Text.Json@11.0.0-preview.6.26359.118..11.0.0-preview.7.26381.103 \
--tfm net10.0 \
--type System.Text.Json.JsonSerializerOptions \
--member .ctor:1 \
-S "Annotated Source Diff" --json --ilSelect Implementation Diff directly to inspect body-level C#, IL, and
normal-flow complexity evidence. Select Complexity Context directly for a
focused view with nullable Old, New, Delta, Population Size, and
Percentile Rank fields. The rank is the inclusive percentage of
delta-bearing methods in this diff whose absolute complexity delta is no
greater than the row's. It is positional context, not an unusualness or
quality judgment; an all-equal population gives every row 100. Use column
projection with JSON Lines to emit dedicated cells instead of parsing
Evidence:
--implementation is the conventional shortcut for exact
-S "Implementation Diff" selection. It contributes that canonical section
before ordinary section resolution, so explicit peer sections compose
normally and all validation, output formats, and complete transport behavior
remain identical.
dotnet-inspect diff --package Markout@0.33.0..0.35.2 \
--type Markout.MarkoutWriter \
-S "Complexity Context" \
--columns Member,State,Delta,PopulationSize,PercentileRank,Kind \
--jsonlSelect Structural Context directly to inspect signed instruction, complexity,
loop, exception-region, direct-call, allocation, and async deltas with their
direction signature and exact local cohort frequency. It includes complete,
unambiguous pairs, including all-Unchanged pairs; added, removed, incomplete,
and ambiguous pairs do not appear. Cohort Size is a local frequency, not an
outlier or quality judgment. Use the stable Kind value
research.complexity.structural-cohort and dedicated fields for structured
automation:
dotnet-inspect diff --package Markout@0.33.0..0.35.2 \
--type Markout.MarkoutWriter \
-S "Structural Context" \
--columns Member,InstructionDelta,ComplexityDelta,InstructionDirection,CohortSize,PopulationSize,Kind \
--jsonlUse the Clone Candidates section for a globally ranked search from an exact
Library, Type, or logical Member seed. Breadth and candidate admission are
independent; the default is Everything plus SimilarNames.
dotnet-inspect type Cases.Widget --library ./app.dll -S "Clone Candidates"
dotnet-inspect member Cases.Widget --library ./app.dll -m Value \
-S "Clone Candidates" \
--where "Breadth=Self" \
--where "Discovery=All"
dotnet-inspect type Cases.Widget --library ./app.dll \
-S "Clone Candidates" -n 2
dotnet-inspect package ./app.nupkg --library app.dll \
-S "Clone Candidates" -n 2
dotnet-inspect type Cases.Widget --library ./app.dll \
-S "Clone Candidates" -n 1 --tail --count
dotnet-inspect type -Q "Clone Candidates"Breadth accepts Self, SelfAndRegisteredEcosystems, or Everything;
Discovery accepts SimilarNames or All. The current CLI supplies the
selected exact library as its finite Workspace participant snapshot and
discloses that scope in tabular diagnostics and structured coverage. It does
not infer registered-ecosystem membership or silently narrow the requested
breadth. -n, --tail, and strict --rows windows select complete ranked
candidate pairs consistently across Markdown, tables, TSV, JSONL, projected
JSON, complete JSON, and --count. Coverage and the work receipt remain
complete evidence, so structured receipt.returned_pairs can exceed the
selected rows length.
Rows are retrieval candidates, not checked clone relations. They retain rank,
both exact method endpoints, the 0-10,000 total and component scores, and the
optional type/member name-similarity evidence. Plain --json also retains the
portable seed, participant identity and provenance, coverage, failures, limits,
and work receipt. --rows, --columns, --fields, --count, --table,
--tsv, and --jsonl operate at the declared candidate-row output seam.
Pairwise match remains the checked comparison path:
dotnet-inspect match Left.Compute Right.Compute --library ./app.dll
dotnet-inspect match Left.Compute Right.Compute --library ./app.dll --body
dotnet-inspect match Sample.Encode --similar --library ./app.dll
dotnet-inspect match Sample.Encode --similar --library ./app.dll --assembly-wide --top 10--body adds decompiled C# and IL body differences alongside the independent
structural-match result. Both methods must resolve to the same physical
assembly. A bodyless or unavailable endpoint stays visible rather than implying
equal bodies. Use Markdown (the default) or --json; body evidence is not
supported with --table, --tsv, --jsonl, or --similar.
--body --json returns a match/body envelope: the body document retains
per-producer native verdicts, physical endpoint addresses and availability,
structured C#/IL differences, diagnostics, and cleanup outcomes. Plain
match --json keeps its existing flat structural document. --body returns
nonzero on query cancellation or failed body comparison while preserving the available output;
a valid bodyless endpoint is reported as NoApplicableInput, not a body match.
The publication and CLI gates
cover these distinctions.
--similar ranks structural candidates for one seed method. It is a discovery
step, not a verdict: a rank establishes no relation, no semantic equivalence,
and no authorship or copying claim. Within one image, confirm a candidate by
re-running the pairwise form on the selected pair.
The default candidate population is the seed's declaring type. --assembly-wide
opts into whole-assembly retrieval, which costs materially more. -n,
--tail, strict --rows windows, and --top select complete ranked candidate
rows after retrieval; --top uses the structural-similarity ranking already
issued by Analysis. Markdown, table, TSV, JSONL, JSON, and --count consume the
same selected candidate sequence. JSON retains the complete per-method
outcomes, blockers, and query receipt, with row_selection counts that
distinguish returned candidates from selected rows. --max-results and
--max-methods move the product retrieval limits themselves. In --table,
--tsv, and --jsonl, the ranked candidates are the only row shape; the seed,
scope, disposition, receipt, blockers, and disclosure are written to stderr so
stdout stays single-shaped and parseable.
Every ranked row prints a Token column holding the candidate's metadata token,
which the pairwise form accepts directly as the second operand. That keeps every
row addressable even when a name is ambiguous across overloads or property
accessors:
dotnet-inspect match 'Sample.Encode' 0x06000CF8 --library ./app.dllA metadata token is a table row index, not a portable identity, so it addresses
a member only in the assembly that defines it. match resolves a token against
the image named by --library and fails when that image does not define the
row, rather than binding it to an unrelated member.
That distinction is visible when --library names a facade. If the seed's type
is forwarded, the ranked rows come from the assembly that actually defines them,
so the run names that assembly and the exact --library value to pass when
confirming a candidate:
dotnet-inspect match System.String.IsNullOrEmpty --similar --library ./System.Runtime.dllComparing candidates drawn from two different assemblies is not supported; inspect each side on its own.
dotnet-inspect package Microsoft.Extensions.Logging@10.0.0 \
-S Dependencies
dotnet-inspect package Microsoft.Extensions.Http@10.0.0 \
-S "Package Info"
dotnet-inspect package Microsoft.Extensions.Http@10.0.0 \
-S "Ecosystem Dependencies" \
--columns "Ecosystem,Kind,Dependency,Declared By"
dotnet-inspect package Microsoft.Extensions.Logging@10.0.0 \
-S "Dependency Hierarchy" --depth 2 --tree
dotnet-inspect depends Stream --markdown --mermaid
dotnet-inspect depends Int128 --table --rows 1..10
dotnet-inspect depends Int128 \
--where "Kind=Interface" \
--order-by "Target desc" \
--top 5 --table
dotnet-inspect depends NpgsqlOptionsExtension \
--package Npgsql.EntityFrameworkCore.PostgreSQL@8.0.4 \
--tfm net8.0 \
--envelope
dotnet-inspect depends NpgsqlOptionsExtension \
--package Npgsql.EntityFrameworkCore.PostgreSQL@8.0.4 \
--tfm net8.0 \
--json
dotnet-inspect depends \
--project ./src/App/App.csproj \
--depth 2 \
-S "Dependency Hierarchy,Dependencies"
dotnet-inspect depends \
--package Microsoft.Extensions.Hosting@10.0.0 \
--nuspec ./artifacts/local.nuspec \
-v:n
dotnet-inspect depends \
--package-prefix Microsoft.Extensions \
--max-packages 100 \
-S @Dependencies
dotnet-inspect depends --nuspec ./artifacts/local.nuspec -D --effective
dotnet-inspect depends --package Newtonsoft.Json --tfm net8.0 \
-S Dependencies
dotnet-inspect depends --package System.Text.Json@9.0.0 --tfm net11.0 \
-S Pruning
dotnet-inspect depends --package Microsoft.AspNetCore.Authentication.JwtBearer@10.0.0 \
--tfm net11.0 --platform-family aspnetcore -S Pruning
dotnet-inspect depends \
--project ./src/DotnetInspect.Cli \
--nuspec ./artifacts/package.nuspec \
-S "Dependencies,Failures" \
-v:n
dotnet-inspect type IEquatable --project ./src/DotnetInspect.Cli \
-S Implementers -v:q
dotnet-inspect extensions string --project ./src/DotnetInspect.Cli -v:q
dotnet-inspect graph integrations \
--package Microsoft.Extensions.DependencyInjection.Abstractions@10.0.0 \
--package Microsoft.Extensions.Logging.Abstractions@10.0.0 \
--package Microsoft.Extensions.Logging@10.0.0 \
--package Microsoft.Extensions.Http@10.0.0 \
--tfm net10.0 \
--relationship integration.observed \
-n 10 --tail --table
dotnet-inspect graph calls \
Microsoft.Extensions.DependencyInjection.ProviderBuilderServiceCollectionExtensions \
AddOpenTelemetrySharedProviderBuilderServices~4d95928639 \
--root-package OpenTelemetry@1.18.0 \
--root-tfm net10.0 \
--tfm net10.0 \
--all
dotnet-inspect graph libraries \
--library ./Consumer.dll \
--library ./Provider.dll
dotnet-inspect graph packages \
--package Microsoft.Extensions.Http.Polly@11.0.0-rc.1.26425.128 \
--package Polly.Extensions.Http@3.0.0 \
--tfm netstandard2.0
dotnet-inspect graph packages \
--package Microsoft.Extensions.Http.Polly@11.0.0-rc.1.26425.128 \
--package Polly.Extensions.Http@3.0.0 \
--tfm netstandard2.0 \
-S "Library Pairs,Call Sites" \
--json
dotnet-inspect graph cluster 1 \
--package Microsoft.Extensions.Http.Polly@11.0.0-rc.1.26425.128 \
--package Polly.Extensions.Http@3.0.0 \
--tfm netstandard2.0 \
--table
dotnet-inspect graph cluster 3 \
--library ./Consumer.dll \
--library ./Provider.dll
dotnet-inspect graph libraries \
--library ./Consumer.dll \
--library ./Provider.dll \
-S
dotnet-inspect graph libraries \
--library ./Consumer.dll \
--library ./Provider.dll \
-S "Provider API Types" \
--tableFor asset roots, Dependency Hierarchy is the rooted explanatory result:
shared targets reached through different parents remain separate occurrences,
and tables, JSON, JSONL, row windows, and Count use that same occurrence
currency. On package, selecting this section invokes the same host-neutral
Depends operation; --tree only chooses its projection. Dependencies
remains the direct declaration evidence section and does not acquire transitive
packages. The removed package --dependencies spelling reports replacement
guidance rather than acting as a second hierarchy selector.
Positional depends <type> retains its existing Dependency Graph section
until Type relationships move to the general Graph operation. That route now
projects its existing Source, Target, and Kind predicates plus field and
Traversal ordering through -Q "Dependency Graph". --top requires a Source,
Target, or Kind field order; Traversal is a sequence order. Asset-mode
Dependency Hierarchy and Package Dependency Hierarchy inherit the same
--depth capability from the Dependency operation.
For recursive package traversal, --tfm selects the root package dependency
group and configures the stable traversal target. When --tfm is omitted, the
root keeps its package-local selection while newly reached packages use the
product traversal default, currently net11.0; a compatible destination
selection does not replace that target on later edges.
For graph integrations and graph calls, one semantic row is one logical
graph edge in the completed typed document. Head/Tail and strict Window select
those edges before Markdown, table, TSV, JSONL, JSON, Mermaid, plaintext graph,
or Count lowering; selection does not reduce package acquisition or hide
retained graph failures. Add --lines only to clip rendered text explicitly.
graph libraries, graph packages, and graph cluster retain independent
section row sets; their adopted Direct Use Clusters and Call Sites cohorts are
described below.
graph packages requires exactly two Package coordinates and one explicit
--tfm. It acquires only those Package subjects, enumerates the complete
cross-Package implementation-Library matrix, and evaluates both call
directions for each Library pair. The explicit --tfm is one shared
acquisition request; each Package may independently select a different
compatible implementation asset framework. The default Direct Use Clusters
rows use a canonical Package-pair-wide cluster ordinal. Library Pairs
exposes every admitted matrix cell, including complete empty pairs, while
Call Sites exposes the physical calls supporting each cluster. --columns
and --fields both project the selected section's row vocabulary. Reversing
the two --package values does not change canonical row order or cluster
assignment. The operation does not traverse Package dependencies; use
graph calls for the dependency-aware member workflow. graph cluster N
accepts the same Package pair and defaults to the selected cluster's
Call Sites. Package-backed Public Root Paths is not yet available; that
exact section continues to require the local-Library route.
graph calls is the integration-style complement to the general
member -S "Call Graph" view. It starts from one exact member in
--root-package, automatically follows the root's authorized dependency
graph, and shows only calls crossing the selected supply-chain baseline plus
the shortest baseline paths needed to reach them. Root asset selection stays
exact; dependency traversal independently uses --tfm or the product default.
In the OpenTelemetry example, --all is needed only because
AddOpenTelemetrySharedProviderBuilderServices is a non-public starting
declaration. It widens that API lookup; it does not mean all calls, remove the
graph bounds, or widen the body population, relationship set, dependency
traversal, or selected baseline.
Each edge is typed as connector, boundary, or unclassified-boundary, and
row-oriented output retains the physical MVID, MethodDef token, IL offset,
operand token, call kind, dispatch kind, and loop state. A dependency member
with unique ownership also retains its exact package id, version, and selected
framework. Inspect Web loads that coordinate through its ordinary package path
only when the user selects the graph node, then opens the exact member;
ambiguous ownership publishes no package coordinate.
For an unresolved ordinary AssemblyRef from a Package participant, the CLI
evaluates reachable Package suppliers first and eligible exact Platform targets
second. A selected supplier is admitted into a fresh immutable Workspace
generation, and the call graph is rebuilt against that successor. Continuation
uses finite command-owned work limits and the Workspace deadline; exhausted or
incomplete work remains visible instead of becoming a final missing binding.
The default --baseline self+registered-ecosystems excludes the exact root,
explicit --first-party-prefix values, and the product platform registrations
(.NET Runtime, ASP.NET Core, and Microsoft.Extensions) from highlighting.
--baseline self retains only the exact root and explicit first-party prefixes
as connectors. --baseline nothing highlights every known dependency Package
and rejects first-party prefixes because that baseline excludes nothing.
Traversal and acquisition remain unchanged by all three values. Platform-
delegated dependency routes do not become Package boundaries, while genuinely
unknown ownership remains an unclassified-boundary.
The OpenTelemetry example retains the explanatory connector paths but
highlights OpenTelemetry.Api rather than registered Microsoft.Extensions
Packages. Unavailable dependency participants remain visible through typed
routes and diagnostics rather than being silently dropped. Use --table,
--jsonl, or --json for exact receipts; -n, --tail, and --rows select
complete logical edges after graph construction.
For positional type dependencies, --json writes the complete
TypeDependencySectionResult Content, and --envelope writes the identical
camelCase value under content with schema_version: 1,
result_kind: "type-dependencies", share, and diagnostics. The motivating
example resolves the full matched type
Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.NpgsqlOptionsExtension.
The Content retains the complete dependency relationships and the separately
selected rowSelection.relationships; internal dependency enums remain
numeric.
Envelope framing and diagnostic member names use lower snake case. Share keeps
the owner values available and nonProjectable; diagnostic severity remains
Information, Warning, or Error, and absent correspondence is retained as
null. Baseline envelopes have no evidence member.
With --envelope, --depth remains a traversal input and --rows,
-n/--head/--tail remain semantic relationship selection. --compact is
accepted. Competing formats, --json, Discover/schema/effective modes, -S,
explicit -v, Count, fields/columns, presentation projections or decoration,
and rendered-line clipping are rejected before acquisition. --verbose and
-E .tips remain on stderr. --share retains its existing policy
and emits its optional URL or packet as the final stderr line. There is no
--evidence-envelope support yet.
Asset-mode output, Discover, Count JSON, and ordinary non-JSON output are unchanged. A service-issued empty or non-success Content value is still serialized with its existing exit behavior; an acquisition failure that produces no result emits no substitute envelope.
Pruning is explicit-only and evaluates direct declarations of the named
roots; it does not prune dependency-graph edges or run transitive traversal.
The default comparison family is runtime; use
--platform-family aspnetcore to select the ASP.NET Core inventory. In its
output, Candidate is the package version resolved from the declaration and
Platform Provides is separate platform-supply evidence. If those columns
show 4.3.2 and 4.3.1, respectively, the disposition is
PackageRetained: the command does not select or downgrade to 4.3.1.
graph libraries evaluates both directions in the pair; every row still names
its directed source and target. Omitting -S shows Direct Use Clusters.
In that default view, and with exact -S "Direct Use Clusters", -n, bare
-N, --tail, and strict --rows select complete deterministic cluster rows
before Markdown, plaintext, table, TSV, JSONL, JSON, or Count lowering. Use
--lines for explicit rendered-line clipping. Select
-S "Consumer Use Sites;Provider API Types" for the local methods containing
direct calls and the provider declaring types selected by those calls. These
are direct-use surfaces, not semantic feature clusters, public-entrypoint
reachability, or a list of configured ecosystem Integrations.
Select @Libraries to compose Call Sites, Consumer Use Sites, Direct Use Clusters, and Provider API Types in alphabetical section order. Public Root Paths remains an exact-name section because its required focused cluster does
not compose with the pair-wide category. Summary, path, wildcard, category,
and multi-section views retain rendered-line -n because their independent
row schemas do not form one semantic sequence.
The default Direct Use Clusters section partitions the exact directed calls
into connected components of source and target methods. Each explicit row retains
its call-site references and separately counts source members, provider types,
target members, extension methods, and physical sites. A one-extension-method
row exposes a small direct-use footprint; it is not yet proof that the package
is removable or that copying source is safe.
Use the pair-wide cluster ordinal to reopen one component as exact calls:
dotnet-inspect graph libraries \
--library ./Consumer.dll \
--library ./Provider.dll
dotnet-inspect graph cluster 3 \
--library ./Consumer.dll \
--library ./Provider.dll
dotnet-inspect graph cluster 3 \
--library ./Consumer.dll \
--library ./Provider.dll \
-S "Public Root Paths"graph cluster N requires the same two Libraries and defaults to exact Call Sites. Its heading and description identify the focused cluster and summarize
its source-member, provider-type, target-member, extension-method, and physical
call-site footprint. The rows name every source member, source token, target
member, target token, call kind, evidence method, evidence token, and IL offset
in that cluster. Use source and target identities for ordinary member
inspection. Use the evidence token with the IL offset for library address,
because a compiler-generated physical body can differ from the attributed
source member. The cluster remains structural evidence rather than a
source-inlining verdict.
Public Root Paths traces the selected cluster's exact consumer methods back
to exhaustive public MethodDef roots in the consumer library. Each row reports
one deterministic shortest local static path, its public root and destination
tokens, and physical IL receipts for every logical step. The section must be
named explicitly under graph cluster N; it is excluded from defaults and
wildcard section selection. Pair-wide graph libraries rejects the section
with focused-route guidance. A complete empty section means no public root has
a local static path to the selected use sites. If pair, public-root, or path
analysis is incomplete, retained positive paths are still rendered and the
command exits nonzero instead of asserting absence.
dotnet-inspect member "<SourceType>" \
--library ./Consumer.dll \
-m "<SourceMember>" \
-S @Source
dotnet-inspect member "<TargetType>" \
--library ./Provider.dll \
-m "<TargetMember>" \
-S @Source
dotnet-inspect library address "<EvidenceToken>+<ILOffset>" \
--library ./Consumer.dlldotnet-inspect workspace packet decode "$w"
dotnet-inspect workspace packet decode "$w" | jq
dotnet-inspect workspace packet encode --file workspace-state.json
dotnet-inspect workspace packet encode --file workspace-state.json --url
dotnet-inspect member JsonConvert \
--package Newtonsoft.Json@13.0.4 \
SerializeObject:1 \
--tfm net6.0 \
--share
dotnet-inspect depends \
--package Newtonsoft.Json \
--tfm net6.0 \
--share
dotnet-inspect skill list
dotnet-inspect demo list
dotnet-inspect demo list -n 3 --jsonworkspace packet encode --url emits https://dotnet-inspect.net/?w=<packet>
for the existing share-packet JSON shape. Packet-only output remains the default.
This is not an encoder for workspace --json inventory output. The packet's
existing limits and the browser's supported restoration shapes still apply.
Bare --share emits a complete Inspect Web URL; --share url spells that
default explicitly, while --share packet emits only the canonical packet.
member --share[=url|packet] projects one explicitly selected public member
overload from an exact NuGet.org package version and target framework. The URL
opens that member's API Overview in the published browser. Select an overload
with Name:N, Name~digest, or --index N. Local, project, platform,
private-feed, non-public, multi-library, and other rendering or analysis modes
fail visibly rather than producing a link the browser cannot restore.
depends --package <id>[@<version>] --tfm <tfm> --share[=url|packet]
projects the package Dependencies view without acquiring the package or
traversing the graph in the CLI. An omitted version or latest is resolved
from NuGet.org and pinned before emission; the published browser then acquires
that exact coordinate and lazily computes the dependency graph for the
selected target framework. Local archives, effective source policies that do
not authorize exactly one NuGet.org source, wildcard, range, or build-metadata
versions, omitted frameworks, the Browser-reserved Microsoft.NETCore.App
Platform id, row windows, counts, and other rendering formats fail visibly
rather than producing a non-reproducible link.
depends <type> --package <id>@<version> --tfm <tfm> --share[=url|packet]
keeps the type dependency result on stdout and appends its canonical
Dependencies URL or packet to stderr. Type sharing is limited to one exact
NuGet.org package coordinate, a valid target framework, and the requested type;
local, floating, ranged, private-feed, multi-source, platform, and
non-projectable requests fail visibly.
The service constructs Share for positional type JSON regardless of whether
stderr projection was requested. --json emits Content only; --envelope
exposes Share alongside that Content. A nonProjectable Share does not change
otherwise successful Content or its exit status. Mixed dependency sources and
any explicit --depth are non-projectable because the published Browser
cannot preserve those requests.
.NET 10.0 SDK or later.
dotnet-inspect is designed for LLM-driven development.
The embedded skill (dotnet-inspect skill) is also distributed through the
dotnet/skills marketplace.
Start with AGENTS.md, then use Repository workflow for contributor rules. Use overview.md when a change crosses subsystem ownership boundaries, and taste/skill-guidance.md when maintaining the embedded skill.
MIT
explain <resource> --json returns compact resource facts and HAL navigation.
The declared fact names are local to the resource type; ordered values remain
arrays. Non-available facts appear in fact_states, and relationship states
and truncation remain explicit. Integers and decimals are lossless decimal
strings; octets are base64 strings.
dotnet-inspect explain vocabularies/csharp.body-kinds --json
dotnet-inspect explain package-query/query/facets/library-literal --json
dotnet-inspect explain vocabularies/csharp.style-choices --depth 1 --json
dotnet-inspect explain vocabularies/csharp.body-kinds .contract --json.contract explicitly selects the complete self-contained explanation Document
with its schema declarations. It requires an exact resource and --json.
HAL links use inspect-resource:/<resource-path> addresses; pass a returned
href unchanged to explain to follow it. These addresses resolve locally,
without HTTP access. Human explanation and capability search are unchanged.
For vocabulary, query-space, and query-facet roots, .data --json selects a
self-contained reading dataset rather than a graph depth. Vocabulary data
includes referenced vocabularies, direct value properties, complete positive
boolean sets, and optional-text membership groups. Facet data includes required
context and exposing bindings; exposed_facets is the binding's intersection
with the selected facets, not its entire term population.
dotnet-inspect explain vocabularies/csharp.style-choices .data --json
dotnet-inspect explain package-query/query .data --json
dotnet-inspect explain package-query/query/facets/library-literal .hal --json.hal embeds the reading resources under _embedded. Vocabulary reading uses
_embedded.vocabularies and each vocabulary's _embedded.values; direct .data
uses keyed vocabularies/values tables plus owner-order arrays. Both preserve
native identities, map meanings and sparse property indices. scope reports the
reading profile and complete selected population. Vocabulary catalog_values
counts are bounded JSON numbers; integer map values retain their lossless decimal
text representation.
For an exact vocabulary root, add -Q / --query-help to either reading
projection to select native value identities before serialization:
dotnet-inspect explain vocabularies/csharp.body-kinds .hal --json \
-Q ObjectCreationExpression
dotnet-inspect explain vocabularies/csharp.style-choices .data --json \
-Q slot-local-names
dotnet-inspect explain vocabularies/api.accessibility .hal --json \
-Q 'public;private'Lists accept commas or semicolons, trim whitespace, deduplicate, and preserve
owner order. A bare -Q after the projection selects all values; a supplied empty
list fails. Matching is exact and case-sensitive: ObjectCreationExpression is
a native body-kind identity, while objectcreationexpression is its path segment.
No wildcard, display-label or path-segment matching is inferred. Shared selection
includes only the exact referenced term values, so one style choice includes its
tier meaning without the unrelated tier population. Optional groups and defaults
contain selected members only; they do not enumerate all catalog alternatives.
-Q narrows data while .data/.hal selects its representation. It requires the
reading projection and JSON; it is rejected for ordinary compact output,
.contract, vocabulary collections, value-resource roots, other resource kinds,
search text, --depth, and -n. Capability-search -n still caps search results;
--depth still controls ordinary graph expansion. Root explain -Q does not
replace command-local Package Query --explain -Q facet selection.
Full reading HAL has one implemented self link. A value-selected HAL response
has one full-vocabulary collection link. Links advertise
application/hal+json and use ?projection=hal; pass an emitted href unchanged
to explain --json. You can add -Q to narrow that HAL address while retaining
its projection. Reading profiles omit automatic contract/member navigation;
request .contract --json explicitly when declaration inspection is necessary.
Ordinary compact resource navigation can still expose other JSON detail links.
The reading projections require JSON and reject --depth and search operands.
Closure is bounded to 256 resources and 4,096 observed targets; excess or
incomplete selected observations fail visibly instead of producing sparse tables
with ambiguous negatives. Absence from a Boolean set establishes false only for
a selected member with complete available property coverage. Unselected values
remain unknown. Neither projection supplies validation rules or host flag
mappings that the catalog has not registered. The
worked vocabulary reads
include reusable jq exploration and a concrete agent workflow.