crucible.cli 1.1.73

dotnet tool install --global crucible.cli --version 1.1.73
                    
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 crucible.cli --version 1.1.73
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=crucible.cli&version=1.1.73
                    
nuke :add-package crucible.cli --version 1.1.73
                    

Crucible

Static documentation generator that transforms Markdown into HTML through an XML intermediate representation and XSLT 4.0 transformation.

Packages

Package Description Install
Crucible.Cli Command-line tool dotnet tool install -g Crucible.Cli
Crucible.Extensions Extension library (Mermaid diagrams, plugin API) Library — reference in your project

Quick start

# Install the CLI
dotnet tool install -g Crucible.Cli

# Create a new docs project
crucible init

# Build the site
crucible build

Features

  • Markdown in, HTML out — write docs in Markdown with YAML frontmatter
  • XSLT-powered — transforms via the PhoenixmlDb XSLT 4.0 engine
  • Client-side search — Lunr.js with pre-built index
  • Dark mode — automatic with manual toggle
  • SEO — Open Graph, canonical links, sitemap.xml
  • Extensible — plugin model for custom Markdown processing
  • LLMs.txt — auto-generated site overview for AI consumption

Documentation

Full documentation at phoenixml.dev

License

Apache 2.0

Product Compatible and additional computed target framework versions.
.NET 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
1.1.73 35 8/4/2026
1.1.63 89 7/31/2026
1.1.62 91 7/29/2026
1.1.47 152 4/29/2026
1.1.46 106 4/29/2026
1.1.45 108 4/29/2026
1.0.0 165 3/20/2026

A pass over the findings from the 2026-08-01 code review. Several of these change
what a build *reports*, and three can fail a build that previously passed — see
"Behaviour changes" below before upgrading a pipeline.

### Fixed

- **Documents that failed to parse were dropped from search and `llms.txt` with no
 warning.** Both generators caught every exception per document and skipped the
 file silently. The failure reached users as a search box that could not find
 pages visibly present on the site, with nothing in the build output to explain
 it. Both now report the file and the reason, and the bare `catch` narrows to the
 exception types actually expected, so anything else surfaces instead of being
 mistaken for a malformed file.

 Also covers the non-throwing path: a well-formed file whose root element was not
 `<document>` was dropped by a bare `continue`, producing the identical symptom
 without an exception ever being raised.

- **The 1.1.63 search-index fix was incomplete.** It decided staleness by comparing
 modification times with a strict `>`, which misses two cases that both ship an
 index short of real pages: a document injected inside the index's timestamp
 granularity *ties* rather than exceeding, and a file copied in with its
 modification time preserved is *older* than the index that predates it. The
 second is the likelier one in practice, since injecting generated pages is the
 documented extension point and copying them is the obvious way to do it.

 Staleness is now a coverage question — documents on disk against entries in the
 index — with the time comparison kept for content changes that leave the count
 unchanged, and ties counted as stale.

- **Plugins with dependencies loaded and then failed on first use.** The loader
 used a bare `AssemblyLoadContext` with no dependency resolution, so any plugin
 with a dependency threw `FileNotFoundException` at the first call into it, deep
 enough to obscure the cause. Resolution now runs through the plugin's
 `.deps.json`, which means **a plugin is a published output folder, not a loose
 `.dll`**.

- **Malformed frontmatter failed the build without naming the file.** A raw
 `YamlException` reported a line number inside the frontmatter block and nothing
 about which document it came from. Errors now carry the document path and a
 document-relative line, with the original diagnostic kept as the inner
 exception, and one bad file is a build error rather than an unattributed stack
 trace that takes the run down.

- **`--strict` did nothing.** It was parsed, stored, and read by nothing, while
 `--help` advertised "Treat warnings as errors" — so a CI pipeline passing it got
 a green build no matter what was reported.

- **`--verbose` did nothing.** Same shape. It now reports the input directory and
 the type it was detected as, the output directory, and the intermediate
 directory.

- **Library code resumed on the caller's synchronization context.**
 `Crucible.Core` used `ConfigureAwait(true)` throughout. Harmless under the CLI
 and ASP.NET Core, neither of which installs a context, but a responsiveness and
 deadlock hazard the first time the library is embedded in WPF, WinForms, or
 MAUI.

### Behaviour changes

- **`--strict` now fails builds.** This is the point of the fix, but a pipeline
 that has been passing `--strict` and going green may start failing. The warnings
 it escalates were always being printed.

- **A malformed closing delimiter is now "missing frontmatter" rather than a
 mangled page.** The terminator was previously any line *starting* with `---`, so
 a `----` rule or a typo ended the block early and leaked the remainder into the
 rendered body. It must now be a line that is exactly `---`, ignoring trailing
 whitespace. Documents relying on the old behaviour will now report an error
 instead of rendering incorrectly.

- **A skipped draft is information, not a warning.** It moved to a new `Messages`
 channel, printed as `info:` and never escalated by `--strict`, because a draft is
 the author's intent rather than a defect — escalating it would make `--strict`
 unusable on any site with work in progress. Anything parsing build output for
 `warning:` lines will no longer see drafts there.

- **`--verbose` keeps the intermediate directory.** A full build parses into a
 temporary directory and deletes it on the way out, so reporting that path and
 then removing it would not have been diagnostics. Under `--verbose` the
 directory is left in place for inspection, and is not cleaned up afterwards.

- **Plugin load contexts are no longer collectible.** They never were unloaded, so
 the flag cost indirection and reduced JIT optimization for a capability nothing
 used. No effect unless a host was relying on plugin assemblies being
 collectible, which nothing in-tree was.