Regenerate Hugo CLI Markdown Documentation Safely
Someone wants the Hugo CLI's full option list in Markdown, and hugo gen doc writes one page per command from the binary you have installed. This walks through generating it into a fresh directory, matching Hugo 0.123.7, the version checked for this guide. Allow about ten minutes for the first run, plus time to review the files before copying them into a documentation project.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need the hugo command and a writable destination. This generates documentation files; it does not build your site, publish anything or need elevated privileges. Do not reach for sudo just because the output happens to be documentation. If the destination belongs to another user or sits inside a protected system directory, fix the ownership or permissions through your normal administration process instead of hiding the problem behind a blind root command.
1. Check the installed Hugo contract
Start by confirming which binary will run and which version supplies the command. Both checks are ordinary and read-only:
$ command -v hugo
/usr/bin/hugo
$ hugo version
hugo v0.123.7+extended linux/amd64 BuildDate=2026-03-17T19:51:14Z VendorInfo=ubuntu:0.123.7-1ubuntu0.3+esm2
$ hugo gen doc --help
Generate Markdown documentation for the Hugo CLI.
...
--dir string the directory to write the doc. (default "/tmp/hugodoc/")
The exact build date and vendor text will vary. What matters is that hugo resolves to the binary you intend to use, and that its help names gen doc with a --dir destination option.
Checkpoint
If command -v hugo prints nothing, stop and install or expose Hugo through your normal package or release process. Do not carry on with a different command that happens to share the name.
2. Choose an isolated output directory
hugo gen doc writes one Markdown file per command. Its default directory is /tmp/hugodoc/, but naming an explicit directory keeps the destination visible in a script and stops you losing track of where the result went. Create a new scratch directory outside your Hugo project:
$ output_dir=$(mktemp -d /tmp/hugo-cli-docs-XXXXXX)
$ printf 'output directory: %s\n' "$output_dir"
output directory: /tmp/hugo-cli-docs-a1B2c3
The suffix is generated and will differ every time. Keep the shell variable in the same session; if you close the terminal, use the full printed path in later commands instead. This directory is ordinary temporary data, not a long-term documentation location.
There is no need to set --config, --source or --destination for this job. They are inherited global Hugo options, but the command's own output control is --dir. Adding unrelated project options just makes it harder to tell whether you generated CLI documentation or accidentally started configuring a site build.
3. Generate the Markdown files
Run the generator with the scratch path:
$ hugo gen doc --dir "$output_dir"
Generating Hugo command-line documentation in /tmp/hugo-cli-docs-a1B2c3/ ...
Done.
This installed build reports success with a plain Done. Hugo creates files such as hugo.md, hugo_gen.md and hugo_gen_doc.md, plus pages for every other command the binary exposes. The set is version-dependent: a different Hugo release or build can expose different commands and flags.
Check that the directory has files, and that the command-specific page has the front matter and synopsis you expect:
$ find "$output_dir" -maxdepth 1 -type f | sort | head
/tmp/hugo-cli-docs-a1B2c3/hugo.md
/tmp/hugo-cli-docs-a1B2c3/hugo_completion.md
/tmp/hugo-cli-docs-a1B2c3/hugo_config.md
...
$ sed -n '1,45p' "$output_dir/hugo_gen_doc.md"
---
title: "hugo gen doc"
slug: hugo_gen_doc
url: /commands/hugo_gen_doc/
---
## hugo gen doc
...
hugo gen doc [flags] [args]
Trust your own sorted list and generated text as the source of truth for the installed version. Do not lift an option from an online page into local documentation without confirming it actually appears in the generated file or in hugo gen doc --help.
4. Review before replacing project documentation
Generation is separate from integration. Count and inspect the output first, without touching the Hugo project:
$ find "$output_dir" -maxdepth 1 -type f -name '*.md' | wc -l
42
$ grep -n -E '^(title|slug|url):' "$output_dir/hugo_gen_doc.md"
2:title: "hugo gen doc"
3:slug: hugo_gen_doc
4:url: /commands/hugo_gen_doc/
42 is what this Hugo 0.123.7 installation produced in a clean directory: an observation, not a promise for every release. More useful than the count is a review of the changed files and their front matter. The pages use Markdown with Hugo-style front matter, so they can be dropped into a documentation content directory that expects that format.
Safety warning
Do not point --dir at a live documentation tree until you have a diff and a backup. Existing files with the same generated names get replaced by a later run, so a mistaken destination can overwrite hand-edited documentation. Generate elsewhere, compare, then integrate through your normal version-control workflow.
5. Compare with an existing documentation tree
If your project keeps generated command pages in docs/content/en/commands, diff the scratch output before copying anything:
$ diff -ru -- "docs/content/en/commands" "$output_dir" | less
Swap the left-hand path for the real directory in your project; this is a read-only comparison. Look for expected version changes, removed commands, changed defaults and altered inherited flags. A large diff can be entirely correct after a Hugo upgrade, but it still deserves review rather than an automatic overwrite.
Keep locally maintained pages separate where you can. The generator builds command pages from the CLI; it is not a general documentation migration tool and has no idea which extra pages your project has added by hand. Use the generated output as an input to the documentation tree, and preserve any project-specific files it does not regenerate.
6. Handle failures without escalating privileges
A non-zero exit status usually means the destination or the Hugo environment needs a look. Capture the command and its status, then inspect the path:
$ hugo gen doc --dir "$output_dir"
$ status=$?
$ printf 'hugo gen doc status: %s\n' "$status"
$ test -d "$output_dir" && ls -ld "$output_dir"
hugo gen doc status: 0
Keep the real, non-zero status for a genuine failure rather than printing a misleading success message. Check that the destination is writable with test -w, that the filesystem has space, and that the Hugo binary is still the version you expect. If the path sits inside a project, check whether another process is touching it. These checks are safer than rerunning with sudo, which can leave root-owned files behind and break later ordinary runs.
If the generated set looks incomplete, go back to step 1 and check hugo version and hugo gen doc --help. Command pages only describe what the running binary registers; they cannot document a command that build does not have.
7. Clean up the scratch output
Once the review is done, remove only the temporary directory you created. This is destructive, so verify the variable before you run it:
$ printf 'will remove: %s\n' "$output_dir"
will remove: /tmp/hugo-cli-docs-a1B2c3
$ case "$output_dir" in
/tmp/hugo-cli-docs-*) rm -rf -- "$output_dir" ;;
*) printf 'refusing unexpected path: %s\n' "$output_dir" >&2; exit 1 ;;
esac
$ test ! -e "$output_dir" && echo 'scratch output removed'
scratch output removed
Keep the directory and note its path instead if you need to investigate a failed run. There is no undo for rm -rf, but scratch output can always be regenerated from the same Hugo version. Never use this cleanup pattern with a project path or a variable whose value you have not inspected.
Done means
- Identified the build.
hugo versionconfirmed the binary and version used for generation. - Wrote to an explicit directory. The output landed somewhere isolated, named with
--dir. - Confirmed success. The command completed and produced Markdown command pages with front matter.
- Reviewed before integrating. Generated files were checked before any project documentation changed.
- Protected existing work. Hand-maintained pages were not blindly replaced.
- Cleaned up deliberately. The temporary directory was kept for investigation or removed only after its path was checked.