Scripting HotDog CMS
Everything HotDog does is a command, so anything you do by hand can be done by a script: making sites, changing them, checking them and publishing them.
hotdog-cms is built to be scripted. Every job is a command with predictable options, output you can read, and an exit code a script can test. That makes it easy to automate the jobs you do often, and to do them to many sites at once.
You'll need to be comfortable writing small shell scripts (bash on Linux and macOS, or PowerShell on Windows). The examples use bash.
What a script can rely on
Exit codes. Every command ends with 0 when it worked and 1 when it didn't, so a script can stop or carry on:
| Command | Exits with 1 when… |
|---|---|
hotdog-cms check |
the site has errors (warnings alone exit with 0) |
hotdog-cms build |
the site can't be built: a mistake in site.yaml, a template or a page |
hotdog-cms publish |
the build fails, the checks find errors, or a target fails |
hotdog-cms new |
the folder already exists |
hotdog-cms import … |
the old site or file can't be read |
Note that build alone doesn't run the checks: a site with broken links still builds. Use check (or publish, which checks) to stop on problems.
-site instead of cd. Most commands take -site DIR, so a script can work on a site without changing folder:
hotdog-cms check -site ~/sites/bakery
hotdog-cms build -site ~/sites/bakery -out /tmp/bakery-build
Secrets from the environment. Passwords and tokens are never options, so they don't end up in scripts or shell history: HOTDOG_GIT_TOKEN, HOTDOG_WP_PASSWORD and the others are read from the environment. See the command reference.
Make a site from a script
#!/usr/bin/env bash
# new-site.sh <folder> "<Name>" <https://address>
set -euo pipefail
folder=$1 name=$2 url=$3
hotdog-cms new -name "$name" "$folder"
sed -i "s#^url: .*#url: $url#" "$folder/site.yaml"
git -C "$folder" init -q -b main
git -C "$folder" add .
git -C "$folder" commit -q -m "Start $name from the HotDog template"
hotdog-cms check -site "$folder"
./new-site.sh florist "Petals on Main" https://petalsonmain.example
set -euo pipefail makes the script stop at the first command that fails, so it never carries on with a half-made site. (On macOS, sed -i needs an empty '' after it: sed -i '' "s#…#…#".)
Change a site from a script
Pages and settings are text files, so any tool that edits text can change them: sed for a simple replacement, yq for YAML settings, or a small program in any language.
# Add a news post
cat > ~/sites/bakery/content/articles/holiday-hours.md <<'POST'
---
title: Holiday hours
date: 2026-12-20
summary: We close at 2pm on the 24th and reopen on the 27th.
tags: [Opening hours]
---
We close at 2pm on December 24th, and we're back on the 27th.
POST
# Change a setting
sed -i 's#^timezone: .*#timezone: America/Chicago#' ~/sites/bakery/site.yaml
hotdog-cms check -site ~/sites/bakery
Always finish with hotdog-cms check: it catches what a script got wrong before anyone sees it.
Changes worth reviewing: use a branch
A script that changes a live site should work like the editor does: on a branch, so the change can be looked at before it's published:
git -C ~/sites/bakery switch -c news/holiday-hours
# … make the change …
hotdog-cms check -site ~/sites/bakery
git -C ~/sites/bakery add -A
git -C ~/sites/bakery commit -m "News: holiday hours"
git -C ~/sites/bakery push -u origin news/holiday-hours
Then open a pull request on your platform (most have a command-line tool for it), or open the branch in the editor and choose Submit for review. A preview shows it exactly as it'll look, and your pipeline checks it again.
Publish from a script
hotdog-cms publish -site ~/sites/bakery server
Or let your platform publish when a branch is merged: see Your platform's pipeline.
Next
Many sites at once takes these same steps across every site you look after.

