AHD Artificial Human Design

AHD · Setup

Install AHD.

Four install paths. The Nix flake is the reproducible one and is the path we test against. The npm path is the practical one for people not on Nix. The library path is for CI linters that do not need a browser. The ESLint and Stylelint plugins wire the rule engine into an existing source-linting flow. The vision critic needs a Chromium binary; the Nix path ships one, the npm path asks you to point at the system install.

Path 1 · Nix flake

The flake ships Node, TypeScript and a Chromium build pinned to a known-good version. On Linux it uses pkgs.chromium; on macOS it uses the bundled Chromium from pkgs.playwright-driver.browsers because pkgs.chromium is not supported on darwin. Either way, the shell exports AHD_CHROMIUM_PATH automatically so ahd critique and ahd critique-url work without further configuration.

Clone, enter the shell, install, build, test.
git clone https://github.com/Ad-Astra-Computing/ahd
cd ahd
nix develop
npm install
npm run build
npm test

Path 2 · npm without Nix

If Nix is not an option, install Node 20 or newer and go through npm directly. The source linter and brief compiler work without any browser. The vision critic and screenshot tools need a Chromium binary; export AHD_CHROMIUM_PATH pointing at it.

Clone and build.
git clone https://github.com/Ad-Astra-Computing/ahd
cd ahd
npm install
npm run build
Point at a Chromium binary (only needed for the vision critic).
# macOS
export AHD_CHROMIUM_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"

# Linux
export AHD_CHROMIUM_PATH="$(command -v chromium)"

AHD also auto-discovers a few canonical install paths before falling back to the environment variable. If your binary lives at one of these, AHD_CHROMIUM_PATH is optional.

Linux
/run/current-system/sw/bin/chromium, /usr/bin/chromium, /usr/bin/chromium-browser, /opt/homebrew/bin/chromium
macOS
/Applications/Chromium.app/Contents/MacOS/Chromium, /Applications/Google Chrome.app/Contents/MacOS/Google Chrome, plus the per-user ~/Applications/ variants

Path 3 · As a library

If you only want the linter in CI, install AHD as a dev dependency. No browser, no API key.

Install + run against built output.
npm install --save-dev @adastracomputing/ahd
npx ahd lint dist/**/*.html dist/**/*.css

Path 4 · Inside ESLint or Stylelint

If you already run ESLint or Stylelint in CI, adding AHD there fires the same taxonomy rules during a normal lint pass. No second CI step, no second config file to chase. Shipped as two scoped packages alongside the main framework; versions move together.

ESLint (works from v8 to v10).
npm install --save-dev eslint @adastracomputing/eslint-plugin-ahd

In flat config (eslint.config.js):

import ahd from "@adastracomputing/eslint-plugin-ahd";

export default [
  {
    plugins: { "@adastracomputing/ahd": ahd },
    rules: {
      "@adastracomputing/ahd/no-centered-hero": "error",
      "@adastracomputing/ahd/no-default-grotesque": "warn"
    }
  }
];
Stylelint.
npm install --save-dev stylelint @adastracomputing/stylelint-plugin-ahd

In .stylelintrc.json:

{
  "plugins": ["@adastracomputing/stylelint-plugin-ahd"],
  "rules": {
    "ahd/line-height-per-size": true,
    "ahd/tracking-per-size": true
  }
}

Both plugins derive their rule set from the shared engine in @adastracomputing/ahd, so the rules stay in lockstep with ahd lint, the MCP server and the eval harness. A rule that lands in the main package in a given release appears in both plugins at the same release version.

Environment variables

AHD_CHROMIUM_PATH
Path to a Chromium or Chrome binary. Required for ahd critique, ahd critique-url and any flow that renders a screenshot. Set automatically by the Nix devShell.
ANTHROPIC_API_KEY
Required for --critic anthropic, which is the default. Pass --critic mock to skip the live call for local development.
CF_API_TOKEN + CF_ACCOUNT_ID
Required for any cf: or cfimg: model spec (Workers AI text and image models).
OPENAI_API_KEY, GEMINI_API_KEY, GOOGLE_API_KEY
Only needed for the API-keyed gpt-*, o*, gemini-* model specs in ahd eval-live. The CLI-backed specs (claude-code:*, codex-cli:*, gemini-cli:*) use no API keys at all, they drive the Claude Code, Codex, and Gemini CLIs against whatever subscription they're already logged into.
AHD_HF_UNSAFE_ENDPOINT
Optional. Set to 1 to let HF_INFERENCE_ENDPOINT point at a non-Hugging Face host. Default is to require the endpoint URL resolve under router.huggingface.co, api-inference.huggingface.co, huggingface.co, or *.endpoints.huggingface.cloud so the HF_TOKEN cannot leak to an unexpected host.
CF_AI_GATEWAY
Optional. Set to <account>/<gateway> to route frontier providers through Cloudflare's AI Gateway for caching, spend tracking and rate-limit observability. Hostname is locked to gateway.ai.cloudflare.com so provider API keys cannot be forwarded to a non-Cloudflare host by misconfiguration.

Per-project .ahd.json

Projects that consume AHD can ship a .ahd.json at their repo root. The file declares rule severity overrides, and every override is required to carry a reason string. Silent disables are rejected at load time: AHD's argument is that a project should be able to say no, that rule does not apply to us and explain why, the same way a linter's // eslint-disable comment carries a pragma.

.ahd.json at the project root.
{
  "project": "dispatch",
  "overrides": [
    {
      "ruleId": "ahd/require-type-pairing",
      "severity": "warn",
      "reason": "Dispatch uses a deliberate single-family aesthetic across subpages."
    }
  ]
}

ahd lint auto-discovers .ahd.json or ahd.config.json in the current working directory. Pass --config <path> to point at a different file. Every applied override is printed in the lint footer and recorded in the JSON report, so a reviewer can see which rules the project chose not to enforce and the declared reason.

GitHub Actions

AHD ships four example workflows in .github/workflows/. Copy the one that matches the integration you want.

ahd-lint.example.yml
Lint as a CI gate. No deploy, no provenance file. The cheapest integration; runs ahd lint on every push and fails the build on any error-severity rule.
ahd-nix.example.yml
Same as above but inside the flake devShell, so it picks up the pinned Node, TypeScript and Chromium. Use when the project already uses Nix.
ahd-deploy.example.yml
The canonical deploy workflow for an Astro / Vite / Next site that wants AHD provenance on every push. Plain Node. npm run build is expected to end in node scripts/ahd-provenance.mjs, which writes dist/ahd.json. Wrangler deploys to Cloudflare Pages. Source lint only. The vision critic does not run here.
ahd-deploy-with-vision.example.yml
The full pipeline. Uses Determinate Systems' nix-installer-action + magic-nix-cache-action to load the flake devShell (Node, TypeScript, Chromium) in seconds on each run. Serves the built dist on localhost, runs ahd critique-url against the preview, fails the job on any vision-rule fire, then deploys. Recommended only when the project's aesthetic contract justifies gating on rendered- pixel slop on every push.

Both deploy workflows need CLOUDFLARE_API_TOKEN in secrets. Recommended: an Account API Token (prefix cfat_) scoped narrowly to Cloudflare Pages : Edit on the one account that hosts your Pages project. Narrow blast radius if the token leaks; carries account context so accountId is optional. A User API Token (prefix cfut_) also works, but because it spans multiple accounts it needs accountId supplied alongside. The examples populate accountId either way. The account ID itself is not sensitive (it appears in dashboard URLs) so you can store it in either secrets or repository variables. The vision workflow also needs ANTHROPIC_API_KEY.

Dependabot

The AHD repo ships a .github/dependabot.yml that bumps nix flake inputs, npm dependencies and github-actions versions weekly. Dependabot's native Nix flake support lets flake inputs move in the same PR cadence as npm. Copy the file into your own repo if you want the same weekly cadence.


Verify your install

One command exercises the source linter, the taxonomy, the token library and the MCP surface in one pass. No API keys, no browser, no network.

Offline round-trip through the linter.
npx ahd try briefs/landing.yml

Writes out/landing.html using the offline mock-swiss runner, lints it in place, prints the report. If that works, the install is clean.

Adjacent reading: usage, positioning, verify a site's provenance.