CLI Reference
Commands and flags for the native pmdocs CLI.
CLI Reference
The supported operator CLI is the native system-level pmdocs binary. Install
it through Homebrew or the Valkyrian Labs Debian repository.
The npm package @valkyrianlabs/payload-markdown-docs installs the Payload
plugin and runtime helpers only. It does not provide the supported CLI surface.
Examples use main-docs as a sample docs set slug. Replace it with the Payload
docs set slug for your upstream docs package.
install
Debian/Ubuntu:
1sudo install -d -m 0755 /etc/apt/keyrings2sudo curl -fsSL https://apt.valkyrianlabs.com/pubkey.gpg \3 -o /etc/apt/keyrings/valkyrianlabs.gpg4sudo chmod 0644 /etc/apt/keyrings/valkyrianlabs.gpg5 6echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/valkyrianlabs.gpg] https://apt.valkyrianlabs.com stable main" | \7 sudo tee /etc/apt/sources.list.d/valkyrianlabs.list > /dev/null8 9sudo apt-get update10sudo apt-get install -y pmdocs11 12pmdocs --version13pmdocs --help
Homebrew:
1brew tap valkyrianlabs/tap2brew install pmdocs3 4pmdocs --version5pmdocs --help
doctor
1pmdocs doctor
Prints local native CLI diagnostics. It does not check networking, Payload server configuration, auth, OIDC, or signing.
doctor exits 0 with status: ok when the bundled skill data is present and
1 with status: degraded when it is missing, because pmdocs install skill
cannot work without it. Homebrew builds bundle the payload-markdown-docs skill
but not the npm companion payload-markdown skill; doctor notes this and
install skill installs the bundled skill only.
validate
1pmdocs validate --source main-docs2pmdocs validate ./docs --source main-docs
Validates the conventional docs package by building and validating an in-memory
manifest. By default this includes Markdown docs from ./docs, skill artifacts
from ./skills/<source> when that directory exists, and optional custom
llms.txt / llms-full.txt fallback assets when present. The default
./skills directory is optional; only an explicitly supplied missing
--skills <path> fails validation.
What the docs walk includes:
- every lowercase
.mdfile below the docs root, at any depth - hidden files and directories (names starting with
.), each reported as a warning; pass--skip-hiddento leave them out
What it leaves out, always reported as a skipped_path warning:
.gitandnode_modulesdirectories at any depthbuild,dist, and.nextdirectories directly below the docs root (the same names deeper in the tree are ordinary docs sections)- symbolic links (not followed)
- Markdown-like files that are not lowercase
.md, such asREADME.MDornotes.markdown
Files that are not valid UTF-8 fail validation with an invalid_encoding
error that names the file.
Two files that derive the same route (index.md and Index.md, or
guide.md and guide/index.md) fail validation with a route_collision error
on each file; the sync endpoint would reject them. Routes that differ only in
letter case produce a route_case_collision warning. push reports local
collisions as warnings and leaves the decision to the server, which knows the
docs set's real route base.
Size limits: --max-file-bytes (500,000) applies to each docs file and asset,
--max-total-bytes (5,000,000) to the sum of all docs and asset contents, and
--max-body-bytes (5,000,000) to the serialized JSON request body. The body
limit is the one the server enforces first (maxBodyBytes, HTTP 413), and JSON
escaping can make the body noticeably larger than the content, so validate,
manifest, and plan check the largest body push could send and push
checks the exact body. Pass --max-body-bytes when the server is configured
with a different maxBodyBytes. Skill packages follow the same walk rules and report
files other than .md, .txt, .json, .yaml, and .yml.
manifest
1pmdocs manifest --source main-docs --pretty2pmdocs manifest ./docs --source main-docs --pretty
Prints manifest JSON. Docs records remain under files; skill artifacts and
optional custom static fallback files are emitted under assets.
plan
1pmdocs plan --source main-docs2pmdocs plan ./docs --source main-docs
Plans against optional local existing-records JSON files. Without
--existing, all valid docs are planned as creates; without
--existing-assets, all assets are planned as creates.
The plan is a local approximation of the server's dry-run. To match it:
- pass
--publishwhen the push will use--publish(otherwise existing published records are planned as status updates) - pass
--route-basefor docs sets that are not served at/<source>: a grouped docs set uses/<group-route>/<source>, a product-nested one/<group-route>/<source>/docs(also pass--asset-route-base /<group-route>/<source>so skill asset routes match) - export current records with the
--existing(docs) and--existing-assets(assets) shapes: arrays of{ "sourcePath", "route", "sourceHash", "status", "archived" }and{ "sourcePath", "kind", "contentType", "route", "sourceHash", "archived" }
pmdocs push --dry-run asks the server for the authoritative plan.
validate accepts --route-base and --asset-route-base too, so route
collision checks use the same routes.
keygen
1pmdocs keygen --out .docs-sync
Generates Ed25519 PEM keys for signed sync. The private key file is created
with mode 0600 (and a newly created --out directory with 0700), whatever
the current umask, including when --force replaces an existing key. push
warns when --private-key-file is readable by group or other users. Add the
public key to an Ed25519 record in Docs Globals > Access. push also accepts unencrypted OpenSSH
Ed25519 private keys when the matching ssh-ed25519 ... public key is stored in
Access.
push
push uploads the conventional docs package by default:
- docs from
./docsas manifestfiles - skills from
./skills/<source>as manifestassetswhen that directory exists ./llms.txtand./llms-full.txtas optional custom static fallback assets when present
Projects do not need to ship native skills. A missing default ./skills
directory is skipped during push; pass --no-skills to opt out explicitly or
--skills <path> when skills live somewhere else.
Ed25519:
1pmdocs push \2 --endpoint "$DOCS_SYNC_ENDPOINT" \3 --source main-docs \4 --key-id local-docs \5 --private-key-env DOCS_SYNC_PRIVATE_KEY
Explicit dry-run:
1pmdocs push \2 --endpoint "$DOCS_SYNC_ENDPOINT" \3 --source main-docs \4 --key-id local-docs \5 --private-key-env DOCS_SYNC_PRIVATE_KEY \6 --dry-run
GitHub OIDC:
1pmdocs push \2 --endpoint "$DOCS_SYNC_ENDPOINT" \3 --source <docs-set-slug> \4 --github-oidc
push defaults to sync mode. --dry-run submits a validation-only request.
--endpoint must use https://. Plain http:// is accepted only for loopback
hosts (localhost, 127.x.x.x, ::1) so a GitHub OIDC bearer token or a
signed manifest never crosses a network in clear text; pass
--allow-insecure-http only for a trusted private network.
--publish is separate from sync mode and requests published output. Publishing
and writes remain server-owned.
When the server rejects a push, pmdocs prints the error message followed by
every detail the server returns: validation issues (with path, code, and
severity), routeCollisions, and manual-edit conflicts. With --json, the
output adds a normalized failure object with code, message, issues,
routeCollisions, and conflicts (empty arrays when an older server does not
send them).
If assets are included and public Next asset route files are missing from the
current working tree, push prints a warning. Add --strict-routes in CI to
turn that warning into a failure.
Common push flags:
--endpoint <url>--allow-insecure-http--source <id>--docs <path>--skills <path>--llms <path>--llms-full <path>--no-docs--no-skills--no-llms--no-llms-full--skip-hidden--dry-run--strict-routes--publish--delete-behavior <archive|delete|draft|ignore>
OIDC-specific flags:
--github-oidc--oidc-token-env <env-name>
Pass --source explicitly in CI. The CLI can derive it from
GITHUB_REPOSITORY only when the docs set slug matches the repository name,
but copied workflow templates should not rely on that fallback.
--repository, --branch, and --commit are optional source metadata flags.
They are not required for GitHub OIDC authentication because Payload verifies
repository, ref, and SHA from the OIDC token claims.
install skill
1pmdocs install skill --agent codex2pmdocs install skill --agent claude
Installs the bundled payload-markdown-docs AI-agent guidance plus the
companion payload-markdown authoring skill for Codex or Claude. Codex defaults
to .agents/skills/payload-markdown-docs/ and
.agents/skills/payload-markdown/; Claude defaults to
.claude/skills/payload-markdown-docs/ and
.claude/skills/payload-markdown/. pmdocs skill install remains as a Codex
compatibility alias.
Useful flags:
--out <path>--docs-root <path>--package-manager <pnpm|npm|yarn|bun>--agent <codex|claude>--codex--claude--force--dry-run
The installer writes Markdown guidance files only. It does not sync docs or run package manager commands.
install routes
1pmdocs install routes --payload-app "src/app/(payload)"
Installs public Next App Router files that delegate raw AI asset requests to the
plugin-owned asset handlers. Commit and deploy these files when a site should
serve canonical public routes outside /api:
1/llms.txt2/llms-full.txt3/plugins/<docs-set>/llms.txt4/plugins/<docs-set>/llms-full.txt5/plugins/<docs-set>/skills/<agent>6/plugins/<docs-set>/skills/<agent>/SKILL.md7/plugins/<docs-set>/skills/<agent>.zip8/plugins/<docs-set>/skills/<agent>/<path...>
Useful flags:
--payload-app <path>--force--dry-run
install routes does not publish assets. It only creates Next route files.
install skill does not publish assets either; it only installs local agent
guidance.
Common flags
--source <id>--docs <path>--skills <path>--llms <path>--llms-full <path>--no-docs--no-skills--no-llms--no-llms-full--skip-hidden--repository <repo>--branch <branch>--commit <sha>--json--pretty--max-files <number>--max-file-bytes <number>--max-total-bytes <number>--max-body-bytes <number>--route-base <path>and--asset-route-base <path>(validateandplan)
--strict-routes is a push flag only. Without --source, the docs set slug
comes from GITHUB_REPOSITORY (the repository name) when it is set, otherwise
from the docs root directory name, or local-docs when that directory is named
docs.