dotnet-inspect-private-feeds · v0.1.0 · 2026-09-23 · sha256 e69f44f767ebece9

dotnet-inspect-private-feeds v0.1.0A

Immutable. This exact content never changes and is served at /api/v1/blob/e69f44f767ebece9.

---
name: dotnet-inspect-private-feeds
version: 0.1.0
description: Inspect packages from private and custom NuGet feeds safely — select and map sources, use credential providers or explicit configuration, diagnose authentication failures, and reason about source-bound caches and offline operation.
---

# dotnet-inspect: private NuGet feeds

Use this skill when package evidence lives outside NuGet.org. Start with a
credential-free source configuration and a NuGet credential provider; keep
tokens out of repositories and command lines.

```bash
dnx dotnet-inspect -y -- <command>
```

## Select the feed

`--nugetconfig` uses exactly the named configuration. `--source` replaces the
configured source set and can repeat; `--add-source` augments it for one run.
Use a source-only config when a credential provider supplies authentication:

```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="private" value="https://example.com/nuget/v3/index.json" />
  </packageSources>
</configuration>
```

```bash
dnx dotnet-inspect -y -- package MyCompany.Widget --nugetconfig ./NuGet.Config
dnx dotnet-inspect -y -- package MyCompany.Widget --versions-with-feed \
  --nugetconfig ./NuGet.Config
```

`package query` currently uses NuGet.org only; it rejects private-feed source
overrides rather than silently querying the wrong authority.

Version discovery combines all eligible sources and chooses the highest
semantic version; source order is not precedence. Pin `Package@Version` when
the exact coordinate matters.

## Share a private-feed Workspace with Inspect Web

Author a credential-free format-5 URL that declares an
authentication-required source:

```bash
dnx dotnet-inspect -y -- workspace \
  --package Private.Package@1.2.3 \
  --tfm net10.0 \
  --nuget-source-auth-required \
    https://nuget.pkg.github.com/example/index.json \
  --share url
```

Inspect Web prompts once per exact 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 Workspace definition, browser
storage, logs, diagnostics, or telemetry. Reloading prompts again. Cancellation
or failure before publication preserves the prior visible Workspace; if
recovery after cutover also fails, Inspect Web enters a blocking retry state
rather than exposing the failed tentative Workspace. Declared anonymous
sources activate without a prompt.

### Query versions from a folder feed

Online version queries support NuGet V2/V3 folder feeds, specified as a
path, a `file://` URI, or a mapped source in `NuGet.Config`:

```bash
dnx dotnet-inspect -y -- package MyCompany.Widget --versions --source ./feed
dnx dotnet-inspect -y -- package MyCompany.Widget --versions -n 5 --preview \
  --source ./feed --jsonl
dnx dotnet-inspect -y -- package MyCompany.Widget --versions -n 1 --source ./feed
dnx dotnet-inspect -y -- package MyCompany.Widget@latest --versions --source ./feed
dnx dotnet-inspect -y -- package MyCompany.Widget --version 1.2.3 --source ./feed
dnx dotnet-inspect -y -- package MyCompany.Widget@1.0.0..2.0.0 --versions \
  --source ./feed --include-unlisted
dnx dotnet-inspect -y -- package MyCompany.Widget --versions-with-feed \
  --source ./feed --add-source https://api.nuget.org/v3/index.json
```

Local and HTTP versions are combined and sorted before the result limit.
Use `--versions -n 1` for one newest listed version row, or
`Package@latest --versions` to force a fresh latest-version check.
Missing folders or invalid archives are source failures, not package absence;
usable peer results carry an explicit partial warning on stderr. Local reads
use bounded enumeration rather than treating filenames as version evidence.
Latest, single-version discovery, and range selection require complete
evidence: an unreadable peer makes them fail instead of choosing from a
healthy subset. A pinned verification may report a coordinate observed on a
readable feed, with peer failures disclosed. `--include-unlisted` and
`--versions-with-feed` retain their listing and feed columns; local versions
use the non-Gallery `listed` convention.

These version queries are metadata-only and do not use `--offline`.

### Inspect a package from a folder feed

Pin one coordinate to inspect its payload through the configured folder source:

```bash
dnx dotnet-inspect -y -- package MyCompany.Widget@1.2.3 --source ./feed
dnx dotnet-inspect -y -- package MyCompany.Widget@1.2.3 --source ./feed \
  --path @readme --content --raw
dnx dotnet-inspect -y -- package MyCompany.Widget --source ./feed
dnx dotnet-inspect -y -- package 'MyCompany.Widget@1.*' --source ./feed \
  --path @readme --content --raw
```

Online single-package inspection also supports latest, `--preview`, and
wildcard payload selection. It freshly queries every eligible source and
requires complete evidence before choosing a version; a failed peer blocks
automatic selection even when another source has a warm payload cache.
Only sources that reported the selected version may supply its payload.
Wildcards use a case-insensitive version prefix and may match prereleases.

Caller-pinned acquisition tries local sources before HTTP sources.
Declaration order is not precedence within a tier. One eligible source can
supply the exact package even when an earlier peer fails; `--verbose` retains
those diagnostics. Tool-wrapper redirects independently reapply mapping.

Local payload caches are scoped to the canonical configured folder, not just
package ID/version or producer identity. HTTP payloads currently use temporary
authority-scoped materialization and do not reuse persistent payload caches.
Automatic selection does not reuse legacy candidate caches. `package --versions`
can enumerate a range, but ordinary `package` payload inspection does not
accept a range or `--at`.

### Inspect APIs and history from a folder feed

Online API commands support omitted/latest and wildcard selection, exact pins,
and explicitly addressed ranges:

```bash
dnx dotnet-inspect -y -- type MyCompany.Widget --package MyCompany.Widget \
  --source ./feed
dnx dotnet-inspect -y -- type MyCompany.Widget \
  --package 'MyCompany.Widget@1.*' --source ./feed
dnx dotnet-inspect -y -- type MyCompany.Widget --package MyCompany.Widget@1.2.3 \
  --source ./feed
dnx dotnet-inspect -y -- type MyCompany.Widget \
  --package MyCompany.Widget@1.0.0..2.0.0 --at last --source ./feed
dnx dotnet-inspect -y -- diff --history --package MyCompany.Widget@1.0.0..2.0.0 \
  --type MyCompany.Widget --type-presence --at first --at last --source ./feed
```

Omitted and `@latest` API selection chooses the highest stable listed version.
Wildcards use the package selection contract's case-insensitive prefix
semantics and may select a prerelease.

Ranges require complete fresh discovery and acquire only from sources that
reported each selected coordinate. Diff History retains one vector for all its
probes. Omit `--at` for full-population evaluation, repeat it for explicit
checkpoints, use `--max-probes` for adaptive bisection, or use
`--major-versions` for one representative per major. API findings use the
first stable version, with the latest prerelease fallback for preview-only
majors; Analysis findings use the latest admitted version per major. An
unreadable peer prevents selection.

API/history vectors exclude unlisted observations, including endpoints.
An exact pin can still inspect an unlisted coordinate. Do not copy ordinals
from a `--include-unlisted` metadata listing into a listed-only vector.
Diff History probe recommendations retain source/configuration and selection
options. `match --similar` retains the reporting configured sources in its
exact-package replay, without depending on temporary extraction paths.

Exact API pins and range probes use the same local authority caches and HTTP
temporary storage as package inspection. HTTP payloads are downloaded anew in
each invocation. Multi-package and dependency commands, and offline extraction
remain on their existing paths.

### Restrict package ids to feeds

dotnet-inspect honors `<packageSourceMapping>` from the selected NuGet
configuration:

```xml
<packageSourceMapping>
  <packageSource key="private">
    <package pattern="MyCompany.*" />
  </packageSource>
  <packageSource key="nuget.org">
    <package pattern="*" />
  </packageSource>
</packageSourceMapping>
```

An exact package id wins over prefixes; otherwise the longest matching prefix
wins. Mapping is applied independently to top-level packages, dependencies,
RID companions, platform packs, tool redirects, searches, and routing probes.
Every package id must match an active named source. `--source` and
`--add-source` do not disable mapping; an override must match the configured
endpoint to retain its mapped source name.

## Azure Artifacts credential provider

Install Microsoft's provider as a global tool. dotnet-inspect discovers
`NUGET_NETCORE_PLUGIN_PATHS`, then `NUGET_PLUGIN_PATHS`, then
`~/.nuget/plugins/netcore/` and `nuget-plugin-*` executables on `PATH`.

```bash
dotnet tool install --global Microsoft.Artifacts.CredentialProvider.NuGet.Tool
```

Credential plugins run only after a feed answers `401`. dotnet-inspect requests
credentials noninteractively: cached and environment-supplied credentials work,
but it never opens a sign-in prompt. `az login` alone does not supply a NuGet
credential.

In Azure Pipelines, authenticate before restore or inspection:

```yaml
- task: NuGetAuthenticate@1
- script: dotnet restore
- script: dnx dotnet-inspect -y -- package MyCompany.Widget
```

Outside Azure Pipelines, provide the provider's documented unattended
credential input. Do not print the expanded value:

```bash
export ARTIFACTS_CREDENTIALPROVIDER_EXTERNAL_FEED_ENDPOINTS='{"endpointCredentials":[{"endpoint":"https://example.com/nuget/v3/index.json","username":"unused","password":"'"$TOKEN"'"}]}'
```

For an Azure Pipelines-compatible build identity, the provider also accepts
`ARTIFACTS_CREDENTIALPROVIDER_URI_PREFIXES` with
`ARTIFACTS_CREDENTIALPROVIDER_ACCESSTOKEN`. Service-principal certificate
configuration uses `ARTIFACTS_CREDENTIALPROVIDER_FEED_ENDPOINTS`.

## Explicit credentials

When no provider serves the feed, dotnet-inspect accepts both `Username` and
`ClearTextPassword` under a matching `packageSourceCredentials` key. Keep that
config outside the repository and select it with `--nugetconfig`.

Do not rely on `%VAR%` expansion, encrypted `<Password>`,
`NuGetPackageSourceCredentials_*`, or credentials embedded in a source URL;
dotnet-inspect does not use those forms.

## Diagnose failures and caches

A reported `401 Unauthorized` means the source was unreadable, not that the
package is absent. Check provider discovery, URI matching, token scope, and
expiration before changing the package id.

dotnet-inspect's package payload and candidate caches retain source provenance.
The NuGet global folder is payload-only: it can fulfill an exact resolved
coordinate only when `.nupkg.metadata.source` names an authorized producer.
Missing or mismatched provenance is a cache miss, and installed payloads do not
introduce version candidates. Use `--no-nuget-cache` to exclude that layer.
`--offline` forbids network access and does not start credential plugins, so it
succeeds only from producer-authorized caches. Online version queries bypass
these legacy caches. Online single-package extraction, exact API pins, and
API/history range probes use authority-scoped
payload storage instead: old producer-keyed entries cannot authorize it, and HTTP
global-packages entries are not reused. A local global-packages entry must
name the same canonical configured folder in `.nupkg.metadata.source`.
Other unmigrated paths still skip configured folder feeds; `--verbose`
reports the skip. Passing a local `.nupkg` file remains supported separately.

```bash
dnx dotnet-inspect -y -- package MyCompany.Widget@1.2.3 \
  --source https://example.com/nuget/v3/index.json --no-nuget-cache
dnx dotnet-inspect -y -- package MyCompany.Widget@1.2.3 \
  --nugetconfig ./NuGet.Config --offline
```