Skip to content

cargo doc --output-format=markdown: generate agent-ready API docs from Cargo.lock #16720

@taradepan

Description

@taradepan

Problem

AI coding agents (GitHub Copilot, Claude, Cursor, etc.) reason from training-data
snapshots of API documentation. That data goes stale fast. An agent working in your
project may reference a serde or tokio API from a version months older than what
is pinned in your Cargo.lock, producing code that does not compile.

Vercel measured this concretely: providing agents with version-matched documentation
raised task pass rate from 53% to 100% (https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals).
The key insight is that agents perform dramatically better when given the exact API
surface of the exact versions you have pinned
, not a best-guess from training data.

Today there is no first-party way to generate that documentation. Users must either:

  • Point agents at docs.rs (wrong version, requires internet, no workspace context)
  • Run third-party tools and manually stitch output together
  • Write and maintain AGENTS.md / CLAUDE.md entries by hand

This is a gap at the ecosystem level. Every Rust project using AI agents has this
problem, and cargo doc is the natural place to solve it — it already knows the
exact crate graph, versions, and source.

Proposed Solution

Add --output-format=markdown to cargo doc (and cargo rustdoc), gated behind
-Zunstable-options initially.

Running:

cargo doc -Zunstable-options --output-format=markdown

produces target/doc/markdown/ containing:

  • One .md file per documented crate (e.g. serde.md, tokio.md)
  • An index.md listing every crate, its pinned version, and a short description

The implementation lives entirely in Cargo — no changes to rustdoc are needed.
We reuse the existing --output-format=json rustdoc output as an intermediate
and post-process it into Markdown in a new ops/cargo_markdown_doc.rs pass,
following the same pattern already established by -Zrustdoc-mergeable-info.

Key design points:

  • serde_json is already a dependency of Cargo — no new dependencies are added
  • The JSON intermediate is parsed with hand-written serde structs mirroring the
    rustdoc JSON schema, driven by format_version for compatibility checking
  • Incremental: if a crate's .json is not newer than its .md, rendering is skipped
  • UserIntent::Doc { json: bool } is replaced with output_mode: DocOutputMode
    enum (Html | Json | Markdown), cleaning up an existing boolean smell
  • --open opens target/doc/markdown/index.md
  • Workspace members are marked (workspace) in the index so agents know what
    they can modify vs. what is an external dependency

The generated index.md includes a ready-to-paste snippet for AGENTS.md /
CLAUDE.md pointing agents at the version-exact docs.

Stabilization path: land unstable, gather feedback from the agent tooling
community on output format, stabilize once settled.

This is a natural extension of what rustdoc --output-format=json already
provides — optimized for language model reading patterns rather than downstream
tooling, and integrated into the standard cargo doc workflow every Rust
developer already uses.

Notes

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`Command-docS-blocked-externalStatus: ❌ blocked on something out of the direct control of the Cargo project, e.g., upstream fixS-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions