feature-manifest
feature-manifest is a small Rust crate plus Cargo subcommand for documenting, validating, and rendering Cargo feature flags.
It gives crate authors a place to describe feature intent today, using Cargo.toml, while also producing outputs that are useful for README tables, docs pages, CI, and editor tooling.
As of 2026-05-02, a quick cargo search for both feature-manifest and cargo-feature-manifest returned no matches, so the crate name appears open on crates.io.
Why this exists
Cargo features are powerful, but feature intent is often trapped in a raw [features] table. feature-manifest creates a lightweight authoring layer on top of that table so maintainers can:
- keep every feature documented in one place,
- fail CI when metadata drifts out of sync,
- generate Markdown for docs and READMEs,
- emit JSON for tooling and editor integrations,
- visualize feature relationships with Mermaid.
Installation
Once published:
cargo install feature-manifest
This installs the cargo-feature-manifest binary, which you then invoke as cargo feature-manifest.
From source today:
git clone https://github.com/funwithcthulhu/feature-manifest.git
cd feature-manifest
cargo install --path .
Commands
cargo feature-manifest check
cargo feature-manifest markdown > FEATURES.md
cargo feature-manifest json
cargo feature-manifest graph
The default command is check, so cargo feature-manifest is valid shorthand.
During local development, you can run the same commands with:
cargo run -- check
cargo run -- markdown
cargo run -- json
cargo run -- graph
You can point the tool at another crate with either a crate directory or a direct manifest path:
cargo feature-manifest check --manifest-path path/to/crate
cargo feature-manifest markdown --manifest-path path/to/crate/Cargo.toml
Metadata format
Structured form:
[]
= ["serde"]
= ["dep:serde"]
= ["dep:tokio"]
= []
= []
[]
= { = "Enables Serialize/Deserialize impls." }
= { = "Enables async APIs backed by Tokio." }
= { = "Experimental APIs; semver not guaranteed.", = true }
= { = "Internal codegen support.", = false }
[[]]
= "runtime"
= "Choose one async runtime backend."
= ["tokio", "async-std"]
= true
Flat shorthand is also supported:
[]
= "Enables Serialize/Deserialize impls."
= { = "Enables async APIs backed by Tokio." }
Supported metadata fields:
| Field | Type | Meaning |
|---|---|---|
description |
string |
Human-facing explanation of the feature. Required for a clean check. |
public |
bool |
Whether the feature should appear in public-facing rendered output. Defaults to true. |
unstable |
bool |
Marks the feature as experimental. |
deprecated |
bool |
Marks the feature as deprecated. |
allow_default |
bool |
Acknowledges that a private, deprecated, or unstable feature is intentionally default-enabled. |
note |
string |
Extra freeform context appended in Markdown output. |
Group fields:
| Field | Type | Meaning |
|---|---|---|
name |
string |
Group identifier used in reports. |
description |
string |
Human-facing explanation of the group. |
members |
string[] |
Features that belong to the group. |
mutually_exclusive |
bool |
When true, flags invalid default combinations. |
What check validates
- Features declared in
[features]but missing metadata. - Metadata entries that do not correspond to a real feature.
- Empty or missing descriptions.
- Unstable, deprecated, or private features that are enabled by default without
allow_default = true. - Mutually exclusive groups that default-enable more than one member.
- Unknown or duplicate feature names inside configured groups.
Output goals
markdownproduces a docs-friendly feature table.jsonemits normalized machine-readable metadata.graphemits a Mermaid dependency graph for feature relationships.
Example JSON output shape:
Example Mermaid output:
graph TD
default_["default"]
feature_serde["serde\nstable, default"]
feature_tokio["tokio\nstable"]
ref_dep_serde["dep:serde"]
ref_dep_tokio["dep:tokio"]
default_ --> feature_serde
feature_serde --> ref_dep_serde
feature_tokio --> ref_dep_tokio
Dogfooding Fixture
A small sample crate lives at fixtures/basic/Cargo.toml. You can try the current CLI against it with:
cargo run -- check --manifest-path fixtures/basic
cargo run -- markdown --manifest-path fixtures/basic
cargo run -- graph --manifest-path fixtures/basic
Publish Checklist
- Confirm the version,
CHANGELOG.md, and README examples are ready for the release. - Run
cargo fmt,cargo test, andcargo publish --dry-run. - Install the binary locally with
cargo install --path .and smoke-test the CLI against a real crate. - Generate and review
FEATURES.mdoutput from a non-trivial fixture crate.
Why this layout
The crate is split into a reusable library and a cargo-feature-manifest binary so the validation logic stays testable and future integrations can call the library directly.
License
Licensed under either of the following, at your option:
- Apache License, Version 2.0
- MIT license