Configuration: .hookci.yml reference

Configuration

.hookci.yml reference

Every key in .hookci.yml, with types, defaults, and a snippet for each section.

.hookci.yml lives at the root of your repository. If the file is missing, HookCI auto-detects your stack and builds a default job list (see examples). Write hookci init to generate a starter file from detection, then edit it.

hookci init
hookci validate

hookci validate [path] [--self-hosted] [--json] lints the file against the schema. --self-hosted also applies the stricter self-hosted rules. Exit code 0 means valid.

Editor autocompletion

HookCI publishes a JSON schema, hookci.schema.json. Add a yaml-language-server comment as the first line and editors that use the YAML language server (VS Code YAML extension, Neovim, Zed) offer completion and inline errors.

# yaml-language-server: $schema=https://hookci.com/hookci.schema.json
version: 1

Full shape

version: 1
checks:
  on:
    pull_request: true
    push: { branches: [main] }
  trust: collaborators
  forks: gated
  limits: { cpus: 2, memory: 4G, timeout: 15m, tasks: 512 }
  setup:
    - run: npm ci
      cache: { key: [package-lock.json], paths: [node_modules] }
  jobs:
    lint: { run: npm run lint, annotate: eslint }
    test: { run: npm test, needs: [lint], timeout: 15m, limits: { memory: 6G } }
  services:
    postgres: true
  egress: [registry.npmjs.org]
notify:
  slack: { channel: "#ci", on: [failure], notify: normal, alert: channel }
redact: [MY_SECRET]
logs: hub

version

Field Type Default Description
version integer none Schema version. Use 1.
version: 1

checks.on

Which events start a run.

Field Type Default Description
pull_request boolean true Run on pull requests. Who may trigger runs is controlled by checks.trust and checks.forks.
push.branches list of strings none Run on pushes to these branches.
checks:
  on:
    pull_request: true
    push: { branches: [main, release] }

checks.trust

Field Type Default Description
trust collaborators | approve | all none collaborators runs pull requests from repo collaborators only. approve waits for an Approve click in Slack. all runs everything and is not recommended for public repos.
checks:
  trust: approve

See Trust and forks for the full outcome table.

checks.forks

Field Type Default Description
forks gated | never none gated: pull requests from forks need approval before they run. never: fork pull requests are ignored.
checks:
  forks: never

checks.limits

Resource limits applied to each job through its systemd transient unit under hookci.slice. See Isolation and egress.

Field Type Default Description
cpus number none CPU quota in cores.
memory size string, e.g. 4G none Memory limit.
timeout duration, e.g. 15m none Wall-clock limit for a job.
tasks integer none Maximum number of processes and threads.
checks:
  limits: { cpus: 2, memory: 4G, timeout: 15m, tasks: 512 }

Each job can override limits and timeout in its own block (see checks.jobs).

checks.setup and cache

setup is a list of steps run before the jobs, for example installing dependencies. Setup output is available with hookci logs <run> setup.

Field Type Default Description
setup[].run string none Shell command for this step.
setup[].cache.key list of file paths none Files whose contents are hashed to form the cache key. When they change, the cache is rebuilt.
setup[].cache.paths list of directories none Directories saved and restored under that key.
checks:
  setup:
    - run: pnpm install --frozen-lockfile
      cache:
        key: [pnpm-lock.yaml]
        paths: [node_modules]

checks.jobs

A map of job name to job definition. Jobs run in dependency order and in parallel up to --slots (default: half the CPUs).

Field Type Default Description
run string none Shell command. A non-zero exit fails the job.
needs list of job names none Jobs that must succeed first. A job whose dependency fails does not run.
timeout duration inherits checks.limits.timeout Per-job time limit.
limits map inherits checks.limits Per-job override of cpus, memory, tasks.
annotate eslint | tsc none Parse the job output into file and line annotations on the GitHub check run. At most 500 annotations per job are kept.
checks:
  jobs:
    lint:
      run: npm run lint
      annotate: eslint
    typecheck:
      run: npx tsc --noEmit
      annotate: tsc
    test:
      run: npm test
      needs: [lint, typecheck]
      timeout: 15m
      limits: { memory: 6G }

Run one job locally with hookci run test.

checks.services

Field Type Default Description
postgres boolean none Start a PostgreSQL service for the jobs. See the docker-compose example.
checks:
  services:
    postgres: true

checks.egress

Field Type Default Description
egress list of hostnames none Hostnames jobs may reach on port 443 through the egress proxy. Everything else is blocked.
checks:
  egress:
    - registry.npmjs.org
    - github.com

How the proxy works, and how to find the host you are missing: Isolation and egress.

deployments

deployments:
  production:
    on: { push: { branch: main } }
    strategy: restart        # restart | compose-bluegreen
    target: /srv/app
    build: npm run build
    migrate: npm run migrate
    env_file: /etc/app.env
    health: { url: http://127.0.0.1:3000/health, timeout: 60s }
    rollback: auto           # planned, value shape not final
    approve: true
Field Type Description
on.push.branch string Branch that triggers the deploy.
strategy restart | compose-bluegreen How the new version replaces the old one.
target path Directory on the agent host.
build string Build command.
migrate string Migration command, run before switching.
env_file path Environment file on the host. Contents are not sent to the hub.
health.url, health.timeout string, duration Health check polled after the switch.
rollback string Rollback behavior. Not final.
approve boolean Require an approval click before deploying.

notify.slack

Field Type Default Description
channel string none Slack channel for run messages, for example "#ci".
on list of failure | success | deploy | all none Which outcomes post.
notify quiet | normal | verbose none How much each message shows.
alert channel | dm none Where failure alerts go: the channel or a direct message.
notify:
  slack:
    channel: "#ci"
    on: [failure]
    notify: normal
    alert: channel

See Slack.

redact

A list of names or values scrubbed from job logs before they leave the agent.

Field Type Default Description
redact list of strings none Secrets or values to replace in logs.
redact: [MY_SECRET, STAGING_TOKEN]

logs

Field Type Default Description
logs hub | local none hub uploads job logs to the hub (capped at 10 MiB per job) and serves them through signed links valid 15 minutes. local keeps logs on the agent only.
logs: local

Read local logs with hookci logs <run> [job|setup] [-f].