Check Hugo's Effective Configuration with hugo config
You have just discovered that the file everyone edits is not the configuration Hugo is actually using, and hugo config proves it in one line. It prints the effective settings, defaults folded together with your own overrides, without touching the build or the destination directory. Give it about ten minutes: the examples use Hugo 0.123.7, packaged as 0.123.7-1ubuntu0.3+esm2 on Ubuntu.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need a shell and a Hugo project, or a directory holding a Hugo configuration file. Every command below is an ordinary user command. You should not need sudo; if the project is unreadable, fix its ownership or permissions through your normal administration process rather than making a routine inspection run as root.
1. Confirm the installed command
Check the binary and version before comparing output with a guide written for another Hugo release:
$ 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
$ dpkg-query -W -f='${Package} ${Version}\n' hugo
hugo 0.123.7-1ubuntu0.3+esm2
The build date and vendor text will differ on another machine. What matters is that the command you invoke is the one you meant, and that its version is known.
Checkpoint
Stop here if hugo is missing, or if you are troubleshooting a different installation than /usr/bin/hugo.
2. Print the default project view
Run the command from a project directory, or pass the project with --source. With no format option, Hugo 0.123.7 prints TOML:
$ hugo --source /path/to/site config --format toml
archetypedir = 'archetypes'
assetdir = 'assets'
contentdir = 'content'
defaultcontentlanguage = 'en'
publishdir = 'public'
themesdir = 'themes'
...
The full output is longer and depends on the release and project. Hugo mixes default and custom settings together, so a value appearing here does not necessarily come from hugo.yaml. Read the report as the effective configuration Hugo assembled for this one invocation, nothing more.
Already inside the site directory? The shorter equivalent is:
$ hugo config
Do not confuse --source with --contentDir. The former picks the project root Hugo reads configuration and directories from. The latter only overrides the content directory setting for this one command.
3. Select a project and configuration file explicitly
Use an explicit source path when a script, editor or service might run from an unpredictable working directory:
$ hugo --source /path/to/site config --format toml
By default, Hugo looks for hugo.yaml, hugo.json or hugo.toml. Reach for --config when the file has another name, or when you want the input to be unambiguous:
$ hugo --source /path/to/site \
--config /path/to/site/configuration.yaml \
config --format yaml
The path above is a placeholder: swap in a readable file that belongs to the project you actually want to inspect. Treat a missing file, malformed YAML or an invalid project setting as a configuration error, not something to work around by pointing Hugo at a nearby project.
Checkpoint
Verify the project path before continuing:
$ test -d /path/to/site && echo 'project directory exists'
$ test -r /path/to/site/hugo.yaml && echo 'configuration is readable'
4. Choose an output format for the next tool
The --format option accepts toml, yaml or json. Pick whichever suits the next step rather than converting the output by hand afterwards.
$ hugo --source /path/to/site config --format yaml | sed -n '1,24p'
archetypedir: archetypes
assetdir: assets
build:
buildstats: {}
useresourcecachewhen: fallback
...
$ hugo --source /path/to/site config --format json > /tmp/hugo-effective-config.json
$ head -n 8 /tmp/hugo-effective-config.json
{
"archetypedir": "archetypes",
"assetdir": "assets",
"baseurl": "https://docs.example.test/",
"build": {
TOML is the default and reads easily. YAML is handy for comparing against a YAML project file. JSON suits a parser or a review tool. The command writes to standard output; redirecting to /tmp is optional and just keeps the captured report separate from the site.
Warning
Effective configuration can contain private URLs, filesystem paths and deployment settings. Review the output before it lands in a ticket or a log, and never paste secrets into a public issue.
5. Inspect a particular language
For a multilingual site, pass a language key with --lang:
$ hugo --source /path/to/site config --lang fr --format yaml | sed -n '1,24p'
archetypedir: archetypes
assetdir: assets
baseurl: https://docs.example.test/
...
The key has to be one the site actually configures. The local Hugo 0.123.7 manpage says that without --lang, Hugo uses the first language defined, a release-specific detail worth checking when output differs between installations. Current upstream documentation describes the default in terms of the default content language instead, so do not assume a newer Hugo release picks the same way.
If the command rejects the language, run it without --lang first and look for the configured language keys. A language report is not a translation of every setting, just a view of the effective configuration for that language.
6. Compare reports without changing the site
Save two reports outside the project and diff them when chasing an environment difference:
$ hugo --source /path/to/site --environment development \
config --format json > /tmp/hugo-development.json
$ hugo --source /path/to/site --environment production \
config --format json > /tmp/hugo-production.json
$ diff -u /tmp/hugo-development.json /tmp/hugo-production.json
--environment is an inherited global option, not something unique to hugo config. It matters when your configuration has environment-specific values. The diff may include cache paths, working directories or other ordinary differences, so review each change rather than treating every line as a fault.
Use filtering only to narrow a question you already have, for example:
$ hugo --source /path/to/site config --format toml | rg '^(baseurl|contentdir|publishdir|environment)'
baseurl = 'https://docs.example.test/'
contentdir = 'content'
environment = 'production'
publishdir = 'public'
A filtered report is a useful check, not a replacement for the full output. If a setting is nested, search for its section or read the complete report in the format you chose.
Common traps
- Report looks like bare defaults. Confirm
--sourcepoints at the intended project and that you did not accidentally select an empty directory. - Output differs between machines. Record the Hugo version, source path, explicit config path, environment and language on each side, then rerun both with
--format jsonand diff the files. - Tempted to delete the config to see the defaults. Do not. This workflow has no undo step because it never writes to the project; deleting the real configuration to "test" a fallback answers a different question and leaves you worse off.
Done means
- Verified the binary. You confirmed the installed Hugo command and version.
- Selected the right project. You used
--sourceor worked from the project root. - Understood the mix. You know the report combines defaults with custom settings.
- Picked a format. TOML, YAML or JSON, chosen for the task at hand.
- Used
--langcorrectly. Only with a language key the site actually configures. - Reviewed before sharing. Captured output was checked for private paths or deployment-sensitive values first.