Valkyrian Labs logo

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 .md file below the docs root, at any depth
  • hidden files and directories (names starting with .), each reported as a warning; pass --skip-hidden to leave them out

What it leaves out, always reported as a skipped_path warning:

  • .git and node_modules directories at any depth
  • build, dist, and .next directories 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 as README.MD or notes.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 --publish when the push will use --publish (otherwise existing published records are planned as status updates)
  • pass --route-base for 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 ./docs as manifest files
  • skills from ./skills/<source> as manifest assets when that directory exists
  • ./llms.txt and ./llms-full.txt as 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> (validate and plan)

--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.