fhir-pkg-cli 2026.901.1609

dotnet tool install --global fhir-pkg-cli --version 2026.901.1609
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local fhir-pkg-cli --version 2026.901.1609
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=fhir-pkg-cli&version=2026.901.1609
                    
nuke :add-package fhir-pkg-cli --version 2026.901.1609
                    

FhirPkg

A C# SDK and CLI tool for discovering, resolving, downloading, caching, and managing FHIR packages from multiple registries.

License: MIT

Packages

Package Description Status
fhir-pkg-lib SDK library - add to your .NET projects NuGet fhir-pkg-lib / Synchronized release workflow
fhir-pkg-cli CLI tool - installs the fhir-pkg command NuGet fhir-pkg-cli / Synchronized release workflow

Features

  • Multi-registry resolution - queries the primary FHIR registry (packages.fhir.org), secondary registry, CI builds (build.fhir.org), HL7 website, NPM registries, and custom/private registries with automatic fallback.
  • Local disk cache - stores packages in the standard ~/.fhir/packages layout with validated reads, transactional replacement, crash recovery, and same-identity coordination across SDK processes.
  • Hardened package sources - safely installs expected-identity or manifest-discovered packages from caller-owned streams and absolute HTTP/HTTPS URIs under finite compressed/archive limits.
  • Dependency resolution - resolves full transitive dependency closures, retains every required exact package version, and uses conflict strategies only to select the preferred name-keyed projection.
  • Always-live restore - resolves each project restore from the current manifest plus registry/cache state and installs coexisting exact versions.
  • FHIR-aware versioning - understands pre-release hierarchies, wildcards, ranges, CI builds, and branch-specific builds.
  • Resource indexing - indexes FHIR resources inside packages with fast lookup by resource type, canonical URL, or StructureDefinition flavor.
  • Publish - publish package tarballs to a registry.
  • Async & DI-ready - fully async with CancellationToken support and first-class IServiceCollection integration.

Quick Start

CLI

# Install the tool
dotnet tool install --global fhir-pkg-cli

# Install a FHIR package
fhir-pkg install hl7.fhir.r4.core#4.0.1

# Install with transitive dependencies
fhir-pkg install hl7.fhir.us.core#6.1.0 --with-dependencies

# Restore project dependencies from package.json
fhir-pkg restore ./my-ig-project

# Search registries
fhir-pkg search --name hl7.fhir.us --fhir-version R4

# List cached packages
fhir-pkg list

# Get package info
fhir-pkg info hl7.fhir.us.core --versions

SDK

dotnet add package fhir-pkg-lib
using System.Text.Json.Nodes;
using FhirPkg;
using FhirPkg.Indexing;
using FhirPkg.Models;

// Create a manager with default options
using var manager = new FhirPackageManager();

// Use your own cancellation token where you have one
CancellationToken cancellationToken = default;

// Install a package
var record = await manager.InstallAsync("hl7.fhir.r4.core#4.0.1");
Console.WriteLine($"Installed to {record?.ContentPath}");

// Install caller-owned content from its current stream position.
// The manager leaves the stream open.
await using FileStream packageStream = File.OpenRead("./package.tgz");
PackageRecord direct = await manager.InstallAsync(
    new PackageReference("example.package", "1.0.0"),
    packageStream,
    new PackageSourceInstallOptions
    {
        ExpectedSha256 = "..."
    },
    cancellationToken);

// Or discover the validated identity from a URI package manifest.
PackageRecord imported = await manager.ImportAsync(
    new Uri("https://packages.example.test/package.tgz"),
    options: null,
    cancellationToken);

// Search registries
var results = await manager.SearchAsync(
    new PackageSearchCriteria { Name = "hl7.fhir.us", FhirVersion = "R4" });

// Resolve without downloading
var resolved = await manager.ResolveAsync("hl7.fhir.us.core#latest");

// Search cached package resources. Missing indexes are generated and persisted
// lazily; newly installed packages are indexed eagerly.
ResourceInfo? profile = await manager.FindByCanonicalUrlAsync(
    "http://hl7.org/fhir/StructureDefinition/Patient",
    "hl7.fhir.r4.core#4.0.1");
JsonNode? resource = profile is null
    ? null
    : await manager.ReadResourceAsync(profile);
Dependency Injection
services.AddFhirPackageManagement(options =>
{
    options.CachePath = "/my/cache";
    options.IncludeCiBuilds = false;
    options.Registries.Add(new RegistryEndpoint
    {
        Url = "https://my-registry.example.com",
        Type = RegistryType.FhirNpm,
        AuthHeaderValue = "Bearer my-token",
    });
});

// IFhirPackageManager exposes resource operations through additive extension
// methods. IFhirPackageResourceManager can also be injected directly; both
// resolve to the same singleton.

FhirPackageManager implements IHardenedFhirPackageManager, and the default DiskPackageCache implements IHardenedPackageCache. Custom cache implementations must advertise the hardened capability before any manager install source is read. URI requests use the configured HttpClient, ResponseHeadersRead, redirect policy, and a timeout covering the response body copy. Network allow-list, proxy, and credential policy remain application responsibilities.

Package acquisition and extraction are finite by default and can be tightened with FhirPackageManagerOptions.InstallLimits, per-call InstallLimits, or the FHIRPKG_MAX_* environment variables. Cache coordination applies to SDK users of the same cache root; external tools that ignore .fhirpkg/locks are outside that coordination boundary.

Resource indexes are derivative cache data. The manager validates existing schema-v2 .index.json files, regenerates missing or invalid indexes under the package identity lease, and atomically persists them before making them searchable. Indexing failures from explicit or lazy queries are surfaced and can be retried; eager post-install indexing failures are logged without changing installation success. Parsed resources use an identity-aware LRU cache controlled by ResourceCacheSize and ResourceCacheSafeMode. Custom IPackageCache implementations without the SDK's generation-aware read capability bypass parsed-resource caching.

Prerequisites

  • .NET 8.0 SDK or later (8, 9, and 10 are supported; .NET 10 is recommended)

Building from Source

git clone https://github.com/GinoCanessa/dotnet-fhir-packages.git
cd dotnet-fhir-packages
dotnet build FhirPkg.sln

Running Tests

# Unit tests
dotnet test test/FhirPkg.Tests

# Integration tests (offline / recorded mode)
dotnet test test/FhirPkg.IntegrationTests

Documentation

Document Description
Documentation Index Landing page for all developer docs
Changelog User-visible changes for both packages, by release.
SDK Overview Introduction, quick start, DI setup, configuration
SDK API Reference Reference for the supported public surface — interfaces, models, and enums
Package Request Process End-to-end walkthrough of resolution, download, extraction, caching, and indexing.
Version Resolution Policy Configuration snapshots, fixups, pre-release rules, and FHIR-release filtering.
Release Process and Evidence Exact-commit source CI, immutable candidate handoff, 3 x 3 qualification, publication gates, and evidence.
CLI Overview Installation, quick start, command summary
CLI Reference All commands, options, exit codes, and config
FHIR Package Reference Package naming, versioning, resolution, registry API, caching, dependencies, client implementations, security, and errors.

License

This project is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
2026.901.1609 103 9/1/2026
2026.803.800 127 8/3/2026
2026.622.1701 144 6/22/2026
2026.324.1648 156 3/24/2026

### Added
- Added the tested `FhirPkg.Release` C# tool for validating release inputs,
 package and symbol contents, synchronized candidates, publication state, and
 published package provenance.
- Restore output now lists every exact resolved package identity, including
 coexisting versions of the same package, in console and JSON formats.
- Added `ResolvedDirective.ResolutionWarnings`, an additive, null-defaulted list
 of non-fatal diagnostics describing how a package source was chosen. The CLI's
 `resolve` command prints each warning, and `--json` emits them as a
 `resolutionWarnings` array.
- Added `FhirPackageManagerOptions.GitHubToken`, the CLI's `--github-token`
 global option, and the `.fhir-pkg.json` `githubToken` key, which authenticate
 the `api.github.com` repository lookups used when choosing the canonical
 repository for a CI build. `null` — the default — keeps those lookups
 unauthenticated and sends no `Authorization` header.

### Changed
- Pack, qualify, publish, and independently verify `fhir-pkg-lib` and
 `fhir-pkg-cli` as one synchronized release candidate, with safe recovery from
 partial NuGet publication.
- Migrated release workflow validation from PowerShell scripts to the C#
 release tool.
- Updated GitHub workflows to the Node 24-compatible `actions/checkout@v6` and
 `actions/setup-dotnet@v5`.
- Relaxed the `global.json` SDK policy from `rollForward: disable` to
 `latestFeature`, so building from source no longer requires the exact
 `10.0.302` patch and any `10.0.3xx`-or-later SDK works. CI still installs and
 resolves `10.0.302` exactly.
- Audited the documentation set for currency, completeness, and correctness
 ahead of this release: the CLI and SDK overviews now mirror their reference
 documents and cover `--github-token` / `githubToken` / `GitHubToken`,
 `docs/sdk-api-reference.md` carries a public-surface coverage table, and
 `README.md`'s links resolve from the NuGet package page.

### Fixed
- Fixed the deployment regression that could publish the SDK without the CLI.
- Made transient Windows cache-replacement retries asynchronous and
 cancellation-aware.
- Restored the defined FHIR/FHIRsmith wildcard grammar, including exact
 two-part versions, part-specific numeric/label/build wildcards, and trailing
 `?` remainder matching.
- Preserved and installed every required exact package version and its transitive
 subgraph during recursive dependency resolution.
- Fixed `@current` implementation-guide resolution selecting an arbitrary fork or
 feature branch. A plain `@current` now resolves the canonical repository's
 default build — chosen by a package-id prefix table, then a GitHub non-fork
 check, then the oldest build — and takes its version and date from that
 repository's `package.manifest.json`. Previously the most recent build from any
 publisher won, which made `hl7.fhir.uv.subscriptions-backport@current` fail to
 install outright and silently mislabelled roughly 139 other packages.
- Fixed branch-qualified CI build URLs being collapsed to the default-branch
 form. The winning record's branch is no longer discarded, so
 `@current$branch` emits `.../branches/{branch}/package.tgz`.
- Fixed CI build dates being ranked by a lexical string comparison across two
 incompatible published formats. Dates are now parsed to instants before
 comparison.

### Removed
- Removed SDK and CLI project restore-lock APIs and options. Restore now always
 resolves the live manifest, registry, and cache graph.