Repository navigation
Releases
v1.3.1 - Project metadata, a public projects API and a consumer package
Docs repositories can now describe the product they document, and other sites can list those
products without copying anything into their own CMS.
Project metadata from docs/stack.toml
Agents (or people) keep an optional docs/stack.toml next to docs/index.md. It holds a title, a
description and the technology stack, grouped into free-form categories:
[project]
title = "Vaulthalla"
description = "The Final Cloud — encrypted storage."
[[stack.languages]]
name = "C++23"
[[stack.libraries]]
name = "libpqxx"pmdocs validate,plan,manifestandpushread it and report problems by key
(stack.toml: stack.languages[0].name must not be empty.).pmdocsnow builds with toml++.- Each sync stores the stack on the docs set, a read-only Technology stack field in the admin.
Categories and items keep their order. An empty[stack]clears the stack. Without the file,
nothing changes. - The new Manually manage title/desc setting decides who owns the docs set's title and
description. New docs sets start with it off, so values fromstack.tomlapply. Existing docs
sets behave as if it were on, so upgrading never replaces a title an admin wrote. Values the
file does not set are never blanked, and SEO fields are never written by sync. - The stack and agent-owned titles survive admin edits, publishing an older draft, and restoring
a saved version. - Default preview cards in the product hero show the stack as text pills: a few on compact cards,
grouped by category on featured ones. Cards without a stack look exactly as before. - The bundled agent skills explain when and how to maintain
stack.toml. Runpmdocs skill updatein docs repositories. - A 1.3
pmdocspushing to an older server warns that the stack was not synchronized. Docs
still sync.
Public projects API (opt-in)
publicApi: { projects: true } serves GET /api/documentation/projects (with an optional
?group= filter) and GET /api/documentation/projects/:slug. They list every published docs
set as a small allowlisted object: title, description, SEO metadata with the usual fallbacks,
absolute product and docs URLs, the docs group and the stack. Repository, OIDC, workflow and sync
settings are never exposed. Responses carry schemaVersion: 1, a content-derived strong ETag
with 304 Not Modified support, and public cache headers.
payload-markdown-docs-consumer
This new package (also published as @valkyrianlabs/payload-markdown-docs-consumer), released
with the same version, reads the projects API from any number of
sites. It has no dependencies (no Payload, Next.js or React). It fetches sites concurrently,
validates schemaVersion, and segments the results by site and then by docs group, plus a flat
list. Keys are scoped to their site (valkyrianlabs/docs). A failing site is reported without
hiding the others.
Upgrading
Postgres apps need a migration for four new, nullable docs_sets columns (and their versions).
No data step is needed. See Upgrading to 1.3 in the docs.
APT signing key updates arrive through upgrades
pmdocs now recommends valkyrianlabs-archive-keyring, the package that carries the Valkyrian Labs
APT repository's signing key. Installing pmdocs from the repository installs it (APT installs
recommended packages by default), and from then on any change
to the key (such as the removal of its expiry date) reaches the machine through normal upgrades
instead of a manual re-download.
- The package owns
/usr/share/keyrings/valkyrianlabs.gpg. An unmodified copy of the key at
/etc/apt/keyrings/valkyrianlabs.gpg(the path the installation docs used) is replaced by a link to
it, so existingsigned-by=source lines keep working unchanged; a modified file is left alone. - It is a recommendation, not a hard dependency, so the standalone
.debfrom a GitHub release still
installs on a system without the repository configured. On machines that already havepmdocs,
install the keyring once withsudo apt install valkyrianlabs-archive-keyring.
v1.2.0 - payload-markdown-docs, MCP agent tools and skills that stay current
pnpm add payload-markdown-docs
The plugin is now also published under the short name payload-markdown-docs:
pnpm add payload-markdown-docs payload-markdown @payloadcms/plugin-seo@valkyrianlabs/payload-markdown-docs stays fully supported. Both names come from the same build and are released together at the same version, with identical files; the only differences are the package name and the name Payload's admin import map uses for the plugin's components, which follows whichever name you installed. Import from the name you installed (payload-markdown-docs/next, payload-markdown-docs/migrations, and so on), install only one of them, and run payload generate:importmap after switching.
payload-markdown works under either of its names too: payload-markdown (preferred) or @valkyrianlabs/payload-markdown. The docs content field uses the admin component of whichever is installed (detected from the components payloadMarkdown() registers, or from node_modules; set payloadMarkdownPackage to choose explicitly). pmdocs install routes writes route files that import the plugin under the name your app depends on.
Let AI agents manage your docs over MCP
payload-markdown-docs/mcp plugs into Payload's official @payloadcms/plugin-mcp, next to payload-markdown's own MCP tools:
mcpPlugin(withPayloadMarkdownMcp(withPayloadMarkdownDocsMcp({ /* mcpPlugin options */ })))Agents get 13 tools to manage the docs site: inspect docs sets, groups and docs (with sync drift), edit presentation fields (hero image, nav overrides, parent, publish date), publish and unpublish, list and inspect versions, roll back to a version Git produced, create and update docs sets and groups (titles, descriptions, SEO, routing, publishing security), manage sync access keys, and read the sync history. Every tool runs as the API key's user with Payload access control.
Git stays the source of truth for doc bodies and frontmatter. A guard on the plugin collections refuses any MCP write to a Git-owned field (sync_owned), whichever tool sends it, including payload-markdown's markdown write tools and plugin-mcp's generic collection tools; the sync endpoint, the admin UI and REST are unaffected. See the MCP Agent Tools docs page for setup and the full tool list.
The payload-markdown skill is always installed
pmdocs install skill now always installs the payload-markdown skill next to the payload-markdown-docs skill. Previously Homebrew installs skipped it silently and Debian installs shipped an old copy. It is taken from your project's installed payload-markdown package when there is one, so the directive guidance matches the version your site renders with, and from the copy bundled with pmdocs otherwise. If neither is available the command fails instead of installing half the guidance. The payload-markdown-docs skill links straight into it for directives, styling, layout and the MCP content workflow.
Skills that keep themselves current
Installed skills now record what they were installed from, and pmdocs notices when a newer one is available:
pmdocs skill check # current, outdated, modified or missing per skill; exits 1 unless current
pmdocs skill update # replaces outdated skills, keeping --docs-root and --package-managerpmdocs validate and pmdocs plan print a reminder when the installed skill is stale, and the skill tells agents to run pmdocs skill update on their own. Skills you edited by hand are never replaced without --force. Re-running pmdocs install skill over an unedited install no longer needs --force.
Docs routes and the docs nav follow docs set and group changes
Changing a docs set's group, slug or route mode, or a group's slug or parent (or deleting a group), now moves the generated docs and their assets to the new routes immediately, in the same save, instead of leaving them on the old paths until the next sync. Published docs and their drafts move together, the old and new paths are revalidated, and a change that would put docs onto routes another docs set already serves is rejected with nothing saved. Routes that are already stale from earlier changes are repaired by saving the published docs set, or all at once with repairDocsRoutes({ payload }) from payload-markdown-docs/migrations.
The docs nav (getPayloadMarkdownDocsNavItems, the header adapters and PayloadMarkdownDocsNavbar) is now cached under the payload-markdown-docs:nav tag (exported as PAYLOAD_MARKDOWN_DOCS_NAV_CACHE_TAG), and the plugin expires it whenever a docs set or group changes and after every sync. Statically prerendered pages that show the docs nav in their header no longer keep serving an outdated nav. Sync and admin revalidation now expire cache tags immediately ({ expire: 0 }) rather than serving the stale entry once more.
Releases
Releases are built and published with vl-release: the Debian package, the Homebrew formula (now built from a release source archive that carries both skills), both npm names and the GitHub release come from one validated build, and a failed release can simply be re-run.
v1.1.0 - Security and Correctness Stabilization
See PR #10 for details.
What's changed
Payload Markdown Docs 1.1.0
Release 1.1.0 includes changes to sync security, sync apply integrity, read visibility, the native pmdocs CLI, plugin configuration, routing and links, release tooling, packaging, docs contract, and tests.
Sync Security
Sync security defaults to admin-only access, scopes credentials to docs sets, prevents nonce replay, narrows OIDC trust, and restricts asset serving.
- Plugin collections default to admin-only;
config.admin.useroraccess.admingrants admin CRUD, with per-collection overrides replacing operations. - Sync credentials and resolved keys carry
docsSetIds;isDocsSetInScopeauthorizes sync only when scope is empty or includes the target docs set. - Nonce consumption inserts first and rejects replays when the unique
(keyId, nonce)index is missing; the 1.1 migration removes expired nonces and keeps the oldest duplicate row. - GitHub OIDC pull_request tokens are checked against their base branch; per-docs-set trust limits allowed repositories, tag refs, workflow refs, and branch.
- Asset content types are restricted to allowed docs asset types; responses add
nosniffand CSP headers; draft assets are deferred on non-publish syncs.
Sync Apply Integrity
Sync apply is transactional, releases routes on archive, archives dropped assets, protects manual edits, and updates docs-set sync bookkeeping.
- Sync apply runs in a database transaction when
beginTransactionis available; success commits, error rolls back, and failed apply marks the sync run failed. - Archived docs release their unique route during delete or replacement so renames, slug swaps, and moved guides converge.
- Empty asset manifests archive dropped assets; already-archived records are skipped by the shared planner so
pmdocs planand server agree. - Manual-edit protection detects CMS edits to synced
title,description,navTitle, ororderand returns 409manual_edit_conflictwithcurrent_fields_hash_mismatch. - Docs-set sync bookkeeping records
sync.lastSyncedAtandsync.lastStatuswithout publishing admin drafts or creating a docs-set version; only the first--publishsync of a never-published set publishes it.
Read Visibility
Shared visibility helpers govern draft and archive status across llms, sitemap, marketing blocks, and route reads.
payload/visibilityowns raw-record and resolved-record visibility:getPayloadDraftStatus,isVisibleToReader,getDocsRecordLifecycleStatus,notArchivedWhere, andpublishedWhere.llms.txt,llms-full.txt,sitemap, and the route adapter use shared visibility helpers so draft docs and draft docs sets are not served on public surfaces.- Marketing CTA and hero
afterReadhydration no longer hydrates content from unpublished docs or docs sets. - Sidebar queries select only nav and visibility fields instead of full markdown bodies; sidebar output is unchanged.
Native CLI
pmdocs CLI enforces credential safety, server contract limits, route collision reporting, package walk reporting, and protocol parity.
pushrequires https endpoints unless the host is loopback or--allow-insecure-httpis set, preventing credential leakage over plain http.keygenwrites the private key throughmkstemp/O_EXCLat 0600 and warns when the key is readable by other users.validate,manifest, andplanenforce the server'smaxBodyByteslimit before push.validate/manifest/planreport route collisions and preserve server failure details:issues,routeCollisions, andconflicts.- Docs and skills walks report every skipped path;
.gitandnode_modulesare ignored at any depth;build,dist, and.nextonly directly below the walked root; non-UTF-8 files are rejected. planandvalidateaccept--route-baseand--asset-route-base;plancan match publish state and existing assets.
Plugin Config
Plugin configuration supports apps without media collections and adds access, trust, and migration exports.
- Media upload and relationship fields are pruned when the app lacks a media collection; heroes and blocks route generated fields through
pruneUploadRelations. PayloadMarkdownDocsConfigaddsaccess,access.admin, per-collection access overrides, and endpointtrustForwardedHeaders;PayloadMarkdownDocsAccessConfigis exported.docsSetsCollectionSlugis optional for per-docs-set access scoping.package.jsonadds a./migrationsexport forprepareDocsSyncMigration.
Routing and Links
Route derivation and Markdown link resolution are centralized and shared across HTML, llms, sitemap, and admin.
routing/docsSetRoutes.tsowns docs group and docs-set route derivation with parent-chain walking, cycle detection, and slug requirements.routing/docsLinks.tsresolves relative and docs-root Markdown links for both the HTML page renderer andllms-full.txt.- The link rewriter never rewrites link syntax inside code fences or inline code spans; it handles linked images and parentheses.
- Sitemap URLs percent-encode route segments; plain ASCII slugs are unchanged and already-encoded segments are not double-encoded.
- The Next route adapter uses
DocsSetLookupto cache docs groups and visible docs sets per request.
Release Tooling
Release AI pipeline adds provider flexibility, changelog validation, and hardened workflows.
- Adds DeepSeek
ds-flashprovider support using OpenAI transport, DeepSeek base URL, and DeepSeek API key environment resolution. - AI pipeline stage config accepts per-stage
providerandbase_urlso emergency triage, triage, draft, polish, and release notes can override pipeline provider and URL. - Changelog validation rejects a stale top entry whose trailer date predates the baseline tag; explicit-tag guard refuses an empty release range.
- Release workflow pins actions to commit SHAs, scopes permissions, runs
meson test --print-errorlogs, and passes release AI profile and DeepSeek key env vars. - Build/Test CI gates on lint, dev-app typecheck, Postgres-backed tests, Playwright e2e, and a consumer smoke run.
Packaging
Packaging updates cover Homebrew, Meson, Debian, and peer dependency installation for the CLI and host app.
- Homebrew formula builds with
-Dinstall_skill_data=true -Dcompanion_skill_data=autoand testspmdocs doctorand skill install dry-run. - Meson minimum is
>=1.3.0and DebianBuild-Dependsmatch, fixing thecpp_stdcomma fallback requirement. payload-markdownandplugin-seoare peer dependencies installed in the host app; consumer smoke verifies single dependency copies, import-map resolution,next build, andpmdocs pushrendering.- The npm package remains runtime integration only; the native
pmdocsCLI is installed separately.
Docs Contract
The 1.1 upgrade guide and author-facing docs cover manifest, frontmatter, CLI, and publishing contracts.
- Upgrade guide covers peer dependencies, import-map regeneration, additive schema changes, and the
prepareDocsSyncMigrationflow for the unique nonce index. - Manifest validation rejects derived route segments with
?,#, or control characters; enforcesmaxBodyBytes; rejects route collisions; confines asset routes. - Frontmatter rules allow decimal and
0x/0o/0border values, prefer- itemlists, require alphanumeric slug starts, warn on empty title, and reject block scalars on known fields. - CLI docs cover
doctordegraded status,validateexclusion reporting, andplan --publish,--existing-assets, and--route-base. - Bundled Claude and Codex skill references align frontmatter forms, route-collision troubleshooting, skipped/hidden file reporting, and
--route-baseusage with shared contract vectors.
Tests
Shared contract vectors, characterization snapshots, and regression coverage pin sync, assets, CLI, and packaging behavior.
contracts/vectors/*.jsoncontract version 1 pins frontmatter, manifests, signing, titles, asset routes, content types, and limits for the TypeScript server and C++pmdocs.- Postgres-gated characterization snapshots pin exact
llms.txt/llms-full.txt, sitemap, nav, route resolution, skills, docs-set manager data, and sync responses. - Regression tests cover nonce migration cleanup, credential scoping, nonce replay, asset serving policy, draft visibility, manual-edit conflicts, route release, and atomic apply failures.
- CLI tests cover keygen permissions, body-size limits, route collisions, package walk reporting, OIDC options, and plan flags.
v1.0.5 - Update Deps
Updates @valkyrianlabs/payload-markdown to v1.5.0 latest release with new img.shields.io badge directives and updated codex/claude skills.
Forgot to use the semver tool for bumping version so this is just a rerelease of v1.0.4
What's changed
Payload Markdown Docs 1.0.5
This release disables skill-data by default in native CLI installs, adds safer targeting and dependency checks for bundled skill installs, updates the frontend route API to accept string or array path input with corresponding type and export changes, updates documentation and workflow guidance to use explicit source IDs in GitHub Actions examples, and updates package metadata, release tooling, and dependency metadata for 1.0.5.
Native CLI
- Skill-data installation is disabled by default in the CLI install options.
- The install flow now shows output paths and bundled skill sources, including per-agent source listing.
- Install routing adds safety checks to keep the destination under the intended target.
- Meson build dependency checks now surface explicit errors for CLI-related dependencies such as
CLI11,nlohmann_json,doctest,libcurl, andOpenSSL.
Frontend
- Route resolution accepts the route path as either a string or an array.
- The route-path input type is added and documented in the Next types.
- Updated route and type exports are available through the frontend index.
Documentation and workflow guidance
- Routing guidance documents path-based route resolution and the legacy slug option.
- GitHub Actions examples now use
PMDOCS_SOURCEfor validation, push, and dry-run steps. - Workflow documentation replaces direct
--sourcevalues with an explicit placeholder format for validation, plan, and push guidance. - Docs package guidance now describes the native installer writing
payload-markdownartifacts beside the skill.
Plugin
package.jsonversion was bumped to1.0.5.pnpm-lock.yamlupdates includews, Tailwind-related entries,@next/swc, Babel-related resolutions, and@typescript-eslintpackages.- Docs CTA button label and target option text were changed.
Release tooling
git_collect.pynow supportsEMPTY_TREE_SHA.- The release workflow writes GitHub release body content to a file and sets
body_path. - Debian packaging and testing steps now use
meson setupwith-Dinstall_skill_data=falsebefore build and test. ai.ymlwas updated with renamed OpenAI profile configuration and adjusted token limits per stage.
v1.0.4 - Update Deps
Updates @valkyrianlabs/payload-markdown to v1.5.0 latest release with new img.shields.io badge directives and updated codex/claude skills.
v1.0.3 - AI Skill OIDC Release Workflow Patch + Docs Cleanup
What's changed
pmdocs (1.0.3-1) unstable; urgency=medium
- Initial native CLI package skeleton.
-- Valkyrian Labs maintainers@valkyrianlabs.com Wed, 13 May 2026 00:00:00 -0600
v1.0.2 - release validation patch
Forgot I added the semver release tooling to this repo and knocked the VERSION out of sync so v1.0.1 release failed. This should release cleanly now.
What's changed
Payload Markdown Docs 1.0.2
This release updates native CLI skill installation defaults and path handling, GitHub release body generation, changelog history collection, documentation, and packaging for the shared payload-markdown skill layout. It also updates Debian packaging paths and docs CTA routing for docs-set targets.
CLI skill installation defaults and path safety
The native CLI now treats skill-data installation as opt-in for npm dependency skill setups, documents related source and exclusion flags, and tightens skill path planning and write validation.
- Default skill-data installation is disabled and described as opt-in when npm dependency skills are available.
- CLI help documents the skills source root flag and exclusion flags for skills and LLMS content.
- Skill install planning separates the primary skill directory from companion package directories.
- Bundled skill path handling normalizes relative paths, validates safety, and rejects writes outside the target root.
Release body generation and changelog history
Release automation now builds a release body from release notes or the changelog, passes that body into the GitHub release step, and updates changelog collection for full-history handling.
- The GitHub release workflow prepares a release body file from release notes or the changelog and passes it to the release action.
- Changelog collection defines an empty-tree SHA constant for full-history handling.
- Release workflow packaging logic prepares release artifacts from the generated body and asset list steps.
Skill artifact layout and installer guidance
Docs now consistently describe the native installer and agent install commands as creating a sibling payload-markdown skill, and quick start guidance reflects the updated install targets.
- Docs-package guidance states that the native installer writes the companion
payload-markdownskill beside the docs skill. - Claude and Codex guidance instructs that install commands create the sibling
payload-markdownskill. - Quick start instructions reflect the updated Codex and Claude install target directories.
- Installer workflow docs describe the output trees for both agent skill layouts.
Debian build and install flow
Debian packaging docs and rules now include local setup requirements, force skill-data installation for Debian builds, and install the shared skills root path.
- Debian build instructions add the local setup steps required before packaging checks.
- The Debian rules override forces skill-data installation on for the Debian build path.
- The Debian install manifest installs the shared skills root rather than the older nested skill path.
Docs CTA routing and hero fallback
Docs CTA handling now preserves docsSet through hero fallback and CTA normalization, and set-target links resolve through the docs-set docs href helper.
- DocsProductHero passes
docsSetthrough the fallback action and CTA normalization flow. - CTA normalization resolves set-target links through the docs-set docs href helper instead of the public href helper.
- The docs CTA button configuration label text was updated to distinguish the docs-route target.
v1.0.1 - Add payload-markdown companion skill install
This is a patch, the program previously assumed that node_modules would be present which is not the case with the full-featured native CLI we have now. We now package the upstream payload-markdown skill with the CLI so pmdocs install skill --agent codex installs both skills/payload-markdown-docs and now skills/payload-markdown
v1.0.0 - AI Native Documentation for the Agent Era
Payload Markdown Docs 1.0.0
Payload Markdown Docs 1.0.0 focuses on expanded documentation sync, a broader native CLI, frontend and generated docs delivery updates, and release tooling changes.
New Features and Updates
Sync
Documentation sync was expanded across lifecycle state, routing, and authentication.
- Added draft and published sync state management with content-hash tracking.
- Changed sync handling for numeric docs-set IDs and normalized routes and endpoints.
- Added signed dry-run and upsert sync phases with GitHub OIDC authentication support.
Native CLI
The native CLI adds new command workflows and signing capabilities.
- Added
validate,manifest, andplancommands. - Added command execution result handling.
- Added Ed25519 key generation and signed push support.
- Expanded skill installation behavior and updated CLI documentation and tests.
Frontend and Navigation
Rendering and navigation behavior were updated for routes, links, and page helpers.
- Normalized route-segment handling and markdown link rewriting.
- Expanded sidebar, sitemap, and navigation rendering helpers.
- Updated marketing block rendering, API behavior, and fetch behavior.
Docs Assets and Skill Delivery
Generated docs assets and skill delivery routes were expanded.
- Added
llms.txtandllms-full.txtasset endpoints and skill asset routing. - Added skill ZIP bundle generation and hardened public asset publishing.
- Updated sitemap and docs asset handling for AI discovery routes and raw artifact control.
Breaking Changes
No breaking changes are identified.
Other Release Notes
Release Tooling and Packaging
Release automation and packaging inputs were revised.
- Updated release workflow automation and contract checks.
- Adjusted Debian, Homebrew, and native build metadata and packaging inputs.
- Refined release helper scripts for dependency installation and workflow setup.
v0.18.3 - test release AI artifact generation
feat: bump version to 0.18.3 and update related files for release