Skip to content

Papermill CLI

@papermill/cli renders documents and manages versions, tags and slugs from your terminal and from CI.

Install

Node 20 or newer:

shell
npm install -g @papermill/cli

Or run it without installing:

shell
npx @papermill/cli generate report.press

Sign in

shell
papermill login

The key is validated before it is saved. Create one at Settings → API keys.

Every command takes its key from --api-key, then $PAPERMILL_API_KEY, then the saved login, in that order. Set the environment variable in CI to skip login.

shell
papermill whoami       # the signed-in account
papermill logout       # remove the saved key; it is not revoked

The saved login records the host it was validated against, so a key issued for one environment is never sent to another. It is stored in ~/.papermill/config.json.

Render a document

shell
papermill generate report.press                            # writes report.pdf
papermill generate --template quarterly-report data.json   # data merged into a saved template
papermill generate report.press --draft                    # watermarked, not counted against your quota

Output follows the input name unless -o sets one. Use -o - to stream the PDF to stdout, and - in place of the input to read stdin. A .json input requires --template.

Pass the @ suffix on --template: --template quarterly-report@production, @3, or @latest.

Manage versions, tags and slugs

CommandWhat it does
papermill version publish <template> -m "<what changed>"Publishes the current content, and prints the version number
papermill version list <template>Published versions, newest first
papermill version get <template> <version>Downloads a version, checking it against its digest
papermill version verify <template> <file>Checks a file against the version it claims to be
papermill tag set <template> <tag> <version>Points a tag at a version — this is how you release
papermill tag get <template> <tag>The version a tag names
papermill tag history <template> <tag>Everywhere that tag has pointed, and who moved it
papermill tag list <template> / tag rmLists the tags a template holds, or retires one
papermill slug set <slug> <template-id>Gives a template a readable name
papermill slug get <slug>Whether a name is free, and who holds it when it is not
papermill slug list / slug rmLists the names in your workspace, or releases one

The @ suffix selects which content to render. These commands manage the template, so they take the plain id or slug. papermill slug set is the one exception: it takes the id itself.

Every tag and slug command takes --json, as do version publish and version list. version get writes the content itself and version verify writes a report, so neither does. papermill help version lists a group's subcommands; papermill version publish --help prints one command's options.

papermill slug get exits non-zero when the name is taken, so a script can branch on the exit code rather than parse the output.

Check a template against what Papermill holds

A download is checked before anything is written:

shell
papermill version get quarterly-report production -o quarterly-report.press

The content is hashed and compared against the sha256 Papermill recorded when the version was published. A file that does not match is never written. Name the version as a number, latest, or any tag you have set.

To check a file you already have — a copy in your repository, or one a colleague sent you:

shell
papermill version verify quarterly-report quarterly-report.press production

The header is removed, what remains is hashed, and the result is compared against the sha256 Papermill holds for the version you named — a number, latest, or a tag. The digest printed inside the file's own header is not what it is checked against, because anyone who edits the content can recompute it. A passing check names the version, when it was published and by whom; a failing one prints both digests.

Always name the version. Without it, the file is checked against the version its own header claims to be, so a copy pinned at version 1 keeps passing after @production has moved on. A file whose header has been stripped must name one.

Run it in CI

yaml
- run: npm install -g @papermill/cli
- run: papermill version verify quarterly-report templates/quarterly-report.press production
  env:
    PAPERMILL_API_KEY: ${{ secrets.PAPERMILL_API_KEY }}

That step fails the build once the committed copy is no longer what @production renders. For publishing, tagging and promoting, see How to release a template.

Point it somewhere else

PAPERMILL_API_URL sends every command to another environment. Log in again for that host, or set PAPERMILL_API_KEY to a key that belongs to it. The saved login is refused for a host it was not validated against.