Audit Hugo Drafts from the Command Line

hugo list drafts finds every piece of draft content before a reader does, printing a CSV of path, title and draft status for each match. It does not touch anything: no publishing, no edits, just a read-only pass over the project. The examples use Hugo 0.123.7 from the installed hugo package. Give it about ten minutes if you already know where the site lives.

You need a shell, a Hugo project, and read access to it. Because it reads the project, it can create Hugo's normal build lock, so avoid running it against a directory that another Hugo process is actively writing to unless concurrent reads are fine for your workflow.

1. Check the installed version

Run this ordinary, unprivileged check from any directory:

$ hugo version
hugo v0.123.7+extended linux/amd64 BuildDate=2026-03-17T19:51:14Z VendorInfo=ubuntu:0.123.7-1ubuntu0.3+esm2

Your build date and vendor suffix will differ. The version matters when you are comparing CSV columns or diagnostics against another machine. If hugo is not found, stop and install it through your normal package or release process rather than guessing at a replacement.

2. Run the check from the project root

Change into the directory holding the site's Hugo configuration, then run:

$ cd /path/to/my-hugo-site
$ hugo list drafts
path,slug,title,date,expiryDate,publishDate,draft,permalink
content/posts/launch-notes.md,,Launch notes,0001-01-01T00:00:00Z,0001-01-01T00:00:00Z,0001-01-01T00:00:00Z,true,https://example.test/posts/launch-notes/

Checkpoint: if the command exits successfully, capture that result before doing anything else, because the shell status belongs to whichever command ran just before it:

$ printf 'hugo list drafts exit status: %s\n' "$?"
hugo list drafts exit status: 0

3. Point at a project explicitly

When a script, editor or scheduled job does not start in the project root, use the inherited --source option:

$ hugo list drafts --source /path/to/my-hugo-site
path,slug,title,date,expiryDate,publishDate,draft,permalink
content/posts/launch-notes.md,,Launch notes,0001-01-01T00:00:00Z,0001-01-01T00:00:00Z,0001-01-01T00:00:00Z,true,https://example.test/posts/launch-notes/

Use an absolute path in automation so the result does not depend on the caller's current directory. Hugo reports an error and a non-zero status when that directory does not exist or cannot be loaded:

$ hugo list drafts --source /path/to/missing-site
Error: failed to load modules: failed to apply mounts for project: failed to open dir "/path/to/missing-site": "open /path/to/missing-site: no such file or directory"
$ printf 'hugo list drafts exit status: %s\n' "$?"
hugo list drafts exit status: 1

Warning: do not treat an error as an empty draft list. Check the path, permissions and project configuration first. sudo is not a normal requirement here; use it only when an administrator has deliberately restricted read access, and fix ownership or group access rather than making a scheduled check run as root.

4. Read an empty result correctly

A project with no draft content still prints the CSV header, just with no data rows:

$ hugo list drafts --source /path/to/my-hugo-site
path,slug,title,date,expiryDate,publishDate,draft,permalink

That is a successful, useful result: Hugo found no content it classifies as draft in this project. It does not prove every file is published, that the site builds, or that another content mount is equally clean. Confirm you pointed at the intended source directory before touching any front matter.

5. Use the output as a pre-publish gate

For a human review, save the report outside the project and inspect the rows:

$ hugo list drafts --source /path/to/my-hugo-site > /tmp/hugo-drafts.csv
$ sed -n '1,20p' /tmp/hugo-drafts.csv

Do not redirect over a report you still need: shell redirection truncates the destination before Hugo even runs. If an empty list matters, check that the file holds only its header rather than trusting a glance at a terminal window, and keep the report only as long as it contains unpublished titles or paths.

hugo list drafts is not a publication command. To change whether a page is a draft, edit that page's front matter, review the diff, and run the check again. This command has no undo because it changes nothing; clear a temporary report yourself with rm -- /tmp/hugo-drafts.csv once you are done reviewing it.

6. Check the command's available options

The installed manpage documents only -h and --help as options specific to this subcommand. Everything else, such as --source, --config, --configDir, --environment, --quiet, --logLevel, --destination and --themesDir, is inherited from the parent command. Ask for help when you need the exact syntax for your installed version:

$ hugo list drafts --help
List all of the drafts in your content directory.

Usage:
  hugo list drafts [flags] [args]

Help text can change between package releases. On Hugo 0.123.7, --verbose still works as an inherited diagnostic flag but prints a deprecation warning pointing you at --logLevel info instead. Skip diagnostic flags on a quiet machine check unless you actually want their messages in the report.

Done means