Skip to content

Documentation

Getting started: what to install and what to set up

Before your first Heddle command you need a few tools on your machine and a few accounts, and this page gives each one's install command for macOS, Windows and Linux. The minimum is Node.js 22 or later, git, the GitHub CLI and a Cloudflare account with your domain in it. Research and the agents add a Search Console property and a prepaid DataForSEO account, and email goes through Plunk. The rest is optional or off by default.

Install the tools first, then create the accounts. Each entry says what Heddle uses it for and which commands read it, so you can stop at what your install needs.

Tools

Node.js 22 or later, with npm

Heddle is a set of Node.js scripts. Every command runs on Node.js 22 or later, and npm installs Heddle's own dependencies.

System Install
macOS brew install node
Windows winget install OpenJS.NodeJS.LTS
Linux curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash (installs nvm), then nvm install 22 (in a new terminal)

Check it with node --version.

git

Heddle lives in a git repository beside your site's, and the agents work in branches and pull requests.

System Install
macOS xcode-select --install
Windows winget install Git.Git
Linux sudo apt install git (Debian, Ubuntu), or sudo dnf install git (Fedora)

Check it with git --version.

GitHub CLI (gh)

The agents open, read and merge pull requests with gh, heddle launch reads the repository's workflows and secret names with it, and you set the repository's secrets with gh secret set.

System Install
macOS brew install gh
Windows winget install GitHub.cli
Linux sudo apt install gh (Debian, Ubuntu; or the packages at cli.github.com), or sudo dnf install gh (Fedora)

Then:

gh auth login

Choose GitHub.com, HTTPS, and sign in with the browser. The account needs write access to the site's repository.

Check it with gh auth status.

Cloudflare's cf CLI (npm package cf, pinned at 1.0.0-beta.14)

Every Cloudflare step Heddle takes for you (DNS, Email Routing, KV, Worker secrets, Turnstile, tokens) goes through Cloudflare's own CLI, signed in once by a person. It is installed with Heddle. npm ci in the Heddle folder puts it in node_modules, so there is nothing to install separately and every machine runs the same version.

Install it with npm ci (in the Heddle folder).

Then:

npx cf auth login

Run it in the Heddle folder. A browser opens; sign in to the Cloudflare account the site deploys to.

Heddle always passes the account the site's wrangler.jsonc names, so one sign-in that sees several accounts never picks the wrong one. When different accounts need different sign-ins, cf keeps named profiles and binds one to a folder. npx cf auth create <name>, then npx cf auth activate <name> <path to the site>.

Run heddle from that folder so the binding applies. npx cf auth list shows the profiles and npx cf auth whoami the one in use.

Beta. cf is in beta. Heddle pins one version (1.0.0-beta.14) and maps each Cloudflare API call it makes to a cf command, so an update cannot change what a step does until Heddle moves the pin.

When cf has no command for a call, Heddle falls back to the Cloudflare API with a token if one is set, and otherwise reports the step as not readable rather than done.

Check it with npx cf auth whoami.

wrangler (Cloudflare's Workers CLI)

The site deploys to a Cloudflare Worker with wrangler, Worker secrets are set with wrangler secret put, and heddle media uploads to R2 with it. It is a dependency of the site, run with npx, so there is nothing to install globally.

Install it with npm install --save-dev wrangler (in the site's repository, once).

Then:

npx wrangler login

Check it with npx wrangler whoami.

Chromium or Google Chrome

heddle diagrams draws diagrams in a real browser with the brand's font, and the diagrams check measures their labels on the built page. Heddle looks for CHROMIUM_PATH, then Playwright's own download, then the usual install locations.

System Install
macOS brew install --cask google-chrome
Windows winget install Google.Chrome
Linux sudo apt install chromium (Debian), or npx playwright install chromium (Ubuntu, in the Heddle folder), or sudo dnf install chromium (Fedora)

Set CHROMIUM_PATH to the browser's executable if heddle diagrams says no Chromium could be launched.

ImageMagick, librsvg and zip

heddle brand draws the downloadable brand kit. rsvg-convert renders the SVG marks, magick sizes the PNGs and zip packs the kit.

System Install
macOS brew install imagemagick librsvg zip
Windows winget install ImageMagick.ImageMagick (and WSL for rsvg-convert and zip)
Linux sudo apt install imagemagick librsvg2-bin zip

Check it with magick -version && rsvg-convert --version.

ffmpeg

The video agent and heddle video render cut the narration and frames into a film with ffmpeg. Only needed when video is switched on.

System Install
macOS brew install ffmpeg
Windows winget install Gyan.FFmpeg
Linux sudo apt install ffmpeg

Check it with ffmpeg -version.

Get Heddle

Heddle is not published on npm. It is a git repository you are given read access to. Clone it beside your site's repository, so the site's scripts find it at ../heddle; set HEDDLE_DIR when it lives anywhere else.

git clone <the Heddle repository URL> heddle
cd heddle
npm ci
npm link

npm link puts the heddle command on your path. Without it, run node <path to heddle>/bin/heddle.mjs wherever the documentation says heddle. Check it with heddle on its own, which lists the 32 commands.

Accounts and keys

Cloudflare account and zone

The site runs on a Cloudflare Worker in your account, its domain is a zone in the same account, and the judging model (Workers AI) and the agents' Claude access (AI Gateway) are billed there.

Needed always; read by heddle agent, heddle install, heddle check, heddle deploy and heddle covers.

  1. Create a Cloudflare account, or use the one your sites already deploy to.
  2. Add the domain (Add a site) in that account and set the registrar's nameservers to the two Cloudflare gives you. Custom domains attach only from the zone's own account, so keep the zone and the Worker together.
  3. Copy the account id from the dashboard's Workers and Pages overview. It is an identifier that is safe to commit, so put it in wrangler.jsonc account_id as well.
Variable What it holds Where it is set
CLOUDFLARE_ACCOUNT_ID the account id your shell, GitHub secret

Workers AI token (the judging model)

The model gates (helpful, buyer, quality, answers) and every agent's self-checks read pages with a model on Workers AI. Without the token those checks report SKIPPED, which never counts as a pass, and in CI heddle check fails on them.

Needed for the model checks and the agents; read by heddle agent, heddle check, heddle deploy, heddle launch and heddle covers.

  1. Cloudflare dashboard, My Profile, API Tokens, Create Token, the Workers AI template (Workers AI Read), limited to your account.
  2. site.json model.tokenEnv names the variable it is read from (CLOUDFLARE_API_TOKEN unless you set another, such as HEDDLE_AI_TOKEN); model.accountEnv names the account variable.
Variable What it holds Where it is set
CLOUDFLARE_API_TOKEN the default name for the Workers AI token your shell, GitHub secret
HEDDLE_AI_TOKEN a common name for a dedicated Workers AI token, when site.json model.tokenEnv says so your shell, GitHub secret

Cloudflare AI Gateway (Claude for the agents)

Agents that draft (the writer, the SEO agent's titles and answers, covers, ideas) call Claude through an AI Gateway on unified billing: Cloudflare pays from the gateway's credits, so there is no separate model-provider key.

Needed for the agents that draft; read by heddle agent, heddle ideas and heddle covers.

  1. Cloudflare dashboard, AI, AI Gateway, Create gateway. Note its name.
  2. Add credits to the gateway and leave automatic top-up off; autonomy.json budget.floorUsd stops the agents before it runs dry.
  3. Create a token with AI Gateway Run (and Workers AI Read, so one token serves both).
  4. A 402 "insufficient credits" answer means the credits are empty; the token is fine.
Variable What it holds Where it is set
CF_AIG_TOKEN the gateway token your shell, GitHub secret
CF_AIG_GATEWAY the gateway's name your shell, GitHub secret

Cloudflare launch token

heddle launch --apply creates what a launch is missing (KV namespaces, Email Routing, the DMARC record, Turnstile hostnames) with a token made for that and nothing else. It never borrows another token to make changes.

Needed for heddle launch --apply; read by heddle launch.

  1. My Profile, API Tokens, Create Token, Custom token. Add Zone: Zone Read, DNS Edit, Email Routing Rules Edit, Zone Settings Edit, and Account: Email Routing Addresses Edit, Turnstile Edit, Workers KV Storage Edit, Workers Scripts Read.
  2. Account Resources. The account the sites deploy to. Zone Resources. All zones from that account.
  3. Keep it on your own machine. Launches run from a person's machine and never from CI, so it belongs in no repository and no GitHub secret.
Variable What it holds Where it is set
CLOUDFLARE_LAUNCH_TOKEN the launch token your shell

Cloudflare Turnstile

Turnstile is the contact form's spam check, and its widget must list the domain, or every enquiry from it is refused from the minute the domain goes live.

Needed for the contact form.

  1. Cloudflare dashboard, Turnstile, Add widget, with the domain and www as hostnames.
  2. The site key goes in the site's .env.local; the secret key is a Worker secret (npx wrangler secret put TURNSTILE_SECRET_KEY).
Variable What it holds Where it is set
NEXT_PUBLIC_TURNSTILE_SITE_KEY the widget's site key (public) your shell
TURNSTILE_SECRET_KEY the widget's secret key Worker secret

Google Search Console property and service account

Positions, clicks, indexing and the weekly reports come from Search Console, read with a service account that has restricted (read-only) access to the property.

Needed for research, indexing and the SEO agent; read by heddle agent, heddle indexing, heddle research, heddle launch, heddle legacy and heddle data.

  1. Search Console. Add a Domain property for the domain and verify it with the TXT record, added in Cloudflare DNS.
  2. Google Cloud console. Create a project, enable the Google Search Console API, then IAM and admin, Service accounts, Create service account. Open it, Keys, Add key, JSON, and keep the downloaded file outside any repository (chmod 600).
  3. Search Console, Settings, Users and permissions, Add user, with the service account's email address and the Restricted permission.
  4. Check it. heddle research <site> gsc check lists the properties the key can read.
Variable What it holds Where it is set
GSC_KEY_FILE the path to the key file, on your machine your shell
GSC_SERVICE_ACCOUNT_JSON the whole key file's contents, for the agents GitHub secret

DataForSEO

Search volume, cost per click, live results pages and position tracking. Prepaid. It fails by running out, and an empty balance answers exactly like a wrong password.

Needed for research and the agents that measure demand; read by heddle agent, heddle research, heddle propose and heddle data.

  1. Sign up at dataforseo.com and add funds. The API login and password are on the API Access page; the password is not your account password.
  2. Before blaming the key, check the balance with heddle research <site> balance. autonomy.json budget.dataFloorUsd stops the agents' data calls under that balance.
Variable What it holds Where it is set
DATAFORSEO_LOGIN the API login your shell, GitHub secret
DATAFORSEO_PASSWORD the API password your shell, GitHub secret

OpenSEO (optional)

An alternative source for search data, declared in site.json data.providers. Heddle reads it and never starts a paid run or creates a project on it.

Needed optional.

  1. Take the API URL and key from your OpenSEO account, and declare it in site.json data.providers.
Variable What it holds Where it is set
OPENSEO_API_KEY the OpenSEO key your shell, GitHub secret

Bing Webmaster Tools

Bing's index feeds Bing, Copilot and ChatGPT search, and Google's tools see none of it. IndexNow submissions report into the same account.

Needed recommended at launch.

  1. bing.com/webmasters, sign in, Import from Google Search Console. It verifies the domain and brings the sitemap with it.
  2. Check that the sitemap is listed, then read Search Performance and AI Performance there each week.
Variable What it holds Where it is set
BING_WEBMASTER_API_KEY an API key from Bing Webmaster Tools, Settings, API access, when site.json data.providers declares bing your shell, GitHub secret

PageSpeed Insights API key (optional)

The design and development agent reads Core Web Vitals from PageSpeed Insights. It works without a key at a low volume; a key raises the quota.

Needed optional; read by heddle data.

  1. In the Google Cloud console project that holds the service account, enable the PageSpeed Insights API, then Credentials, Create credentials, API key. Restrict it to that API.
Variable What it holds Where it is set
PAGESPEED_API_KEY the API key GitHub secret

Plunk (email out)

The contact form, the agents' reports and the signed approval links are sent through Plunk, from your own domain.

Needed for email from the site and the agents; read by heddle agent, heddle indexing, heddle ideas and heddle launch.

  1. Create a project at useplunk.com and copy its secret API key (sk_).
  2. Project settings, Domains, Add the domain. Add the DKIM, SPF and bounce records it shows in Cloudflare DNS as DNS only, then press Verify. Leave out the inbound MX at the bare domain, which stops Cloudflare Email Routing from enabling.
  3. The key is a Worker secret for the contact form and a GitHub secret for the agents' reports.
Variable What it holds Where it is set
PLUNK_API_KEY the secret API key your shell, GitHub secret, Worker secret
PLUNK_PROJECT_ID optional: lets heddle launch read the domain's status from Plunk's API your shell

GitHub repository, secrets and tokens

The agents run as GitHub Actions in the site's repository. They need read access to Heddle and, for ideas by email, a token the Worker uses to start a run.

Needed for the agents.

  1. Copy templates/github/heddle-agents.yml into the site's .github/workflows/.
  2. Create a fine-grained personal access token with Contents read-only on the Heddle repository, and set it as the site's HEDDLE_REPO_TOKEN secret with gh secret set HEDDLE_REPO_TOKEN -R <owner>/<site>. A read-only deploy key (HEDDLE_DEPLOY_KEY) works instead where the organisation allows deploy keys.
  3. Set every other secret the same way, without echoing a value.
Variable What it holds Where it is set
HEDDLE_REPO_TOKEN read access to the Heddle repository GitHub secret
HEDDLE_DEPLOY_KEY or: a read-only deploy key on the Heddle repository GitHub secret
GITHUB_DISPATCH_TOKEN ideas by email: a fine-grained token on the site's repository with Actions read and write, so the Worker can start the ideas workflow Worker secret

Secrets you generate

Shared secrets between the agents and the site's Worker. Nobody issues these; make each one a long random string, for example with openssl rand -hex 32, and set it in both places.

Needed for approvals, leads and ideas; read by heddle ideas.

  1. Generate the value, then npx wrangler secret put <NAME> in the site and gh secret set <NAME> -R <owner>/<site>.
Variable What it holds Where it is set
HEDDLE_APPROVAL_SECRET signs the approval links; the Worker verifies them GitHub secret, Worker secret
HEDDLE_LEADS_TOKEN lets the follow-up agent read new enquiries from the Worker your shell, GitHub secret, Worker secret
HEDDLE_IDEAS_TOKEN ideas by email: signs the approve and withdraw links and reads the ideas the Worker holds GitHub secret, Worker secret

Reddit API app (optional)

heddle research <site> reddit quotes buyers' own words from Reddit threads. Hacker News needs nothing.

Needed optional; read by heddle research.

  1. reddit.com/prefs/apps, create an app of type script, and use its client id and secret with your username.
Variable What it holds Where it is set
REDDIT_CLIENT_ID the app's client id your shell
REDDIT_CLIENT_SECRET the app's secret your shell
REDDIT_USERNAME your Reddit username, for the user agent your shell

ElevenLabs (video narration, off by default)

The video agent narrates explainers with an ElevenLabs voice. Video is off until this is set.

Needed for video; read by heddle video.

  1. Copy an API key from your ElevenLabs profile. To use a cloned voice, put its id in the variable autonomy.json runtime.video.voiceIdEnv names.
Variable What it holds Where it is set
ELEVENLABS_API_KEY the API key GitHub secret
ELEVENLABS_VOICE_ID optional: the voice id GitHub secret

YouTube channel (video publishing, off by default)

heddle video publish uploads a merged, rendered film to your channel. A person runs it; no agent uploads.

Needed for heddle video publish; read by heddle video.

  1. Google Cloud console. Enable the YouTube Data API v3 and create an OAuth client with the youtube.upload and youtube.force-ssl scopes. The channel's owner authorises it once and you keep the refresh token. Until Google's API audit passes, uploads stay private.
Variable What it holds Where it is set
YOUTUBE_CLIENT_ID the OAuth client id your shell
YOUTUBE_CLIENT_SECRET the OAuth client secret your shell
YOUTUBE_REFRESH_TOKEN the channel's refresh token your shell

Where the values live

Values live in three places, and never in a repository.

  • Your shell, for commands you run. Keep the values in a file outside every repository with permissions 600, and load it only in the shell that needs it with set -a; . <file>; set +a. Check that the file ends with a newline before you append to it.

  • GitHub Actions secrets, for the agents, set with gh secret set <NAME> -R <owner>/<site>, which reads the value without echoing it.

  • Worker secrets, for the site itself, set with npx wrangler secret put <NAME> in the site's repository.

heddle research <site> check says which data sources are configured, and heddle launch <site> lists every secret the Worker and the repository still lack.

Generated from the Heddle repository at ddb1b16.

Questions

Do I need every account on this page?

No. Node.js, git, the GitHub CLI and a Cloudflare account are needed for any install. Search Console and DataForSEO are needed for research and for the agents that measure. The rest are optional, or for video, which is off by default.

Where should the keys live?

Keys you use from your own machine live in your shell's environment, loaded from a file outside every repository. The agents read theirs from GitHub Actions secrets, and the site's Worker from its own secrets. None of them is ever committed.