Configuration
Config examples
Ready-to-use .hookci.yml files for Node, Python, Go, Rust, docker-compose, and monorepos.
Without a .hookci.yml, HookCI detects your stack. Detectors exist for node (npm, yarn, pnpm, bun, turbo), python (pip, uv), go, rust, and docker-compose. Check what it found:
~/my-app recording $ hookci detect ✓ node (pnpm) detected jobs: lint, test, build $ hookci init ✓ wrote .hookci.yml
Illustration. hookci detect prints the jobs it would run. hookci init writes them to .hookci.yml.
Detection is a starting point. Write an explicit file when you need needs, limits, caching, services, or extra egress hosts. The examples below show what to write. Validate any of them with hookci validate.
Node
Package manager is detected from the lockfile: package-lock.json (npm), yarn.lock, pnpm-lock.yaml, bun.lockb or bun.lock. A turbo.json selects turbo.
version: 1
checks:
setup:
- run: npm ci
cache: { key: [package-lock.json], paths: [node_modules] }
jobs:
lint: { run: npm run lint, annotate: eslint }
typecheck: { run: npx tsc --noEmit, annotate: tsc }
test: { run: npm test, needs: [lint] }
build: { run: npm run build, needs: [test] }
egress: [registry.npmjs.org]
For other package managers change the setup step, the cache key, and the registry host as needed:
# pnpm
setup:
- run: pnpm install --frozen-lockfile
cache: { key: [pnpm-lock.yaml], paths: [node_modules] }
# yarn
setup:
- run: yarn install --frozen-lockfile
cache: { key: [yarn.lock], paths: [node_modules] }
# bun
setup:
- run: bun install --frozen-lockfile
cache: { key: [bun.lockb], paths: [node_modules] }
With turbo, let turbo run the tasks:
version: 1
checks:
setup:
- run: pnpm install --frozen-lockfile
cache: { key: [pnpm-lock.yaml], paths: [node_modules] }
jobs:
lint: { run: pnpm turbo run lint }
test: { run: pnpm turbo run test, needs: [lint] }
egress: [registry.npmjs.org]
Python
version: 1
checks:
setup:
- run: pip install -r requirements.txt
cache: { key: [requirements.txt], paths: [.venv] }
jobs:
lint: { run: ruff check . }
test: { run: pytest, needs: [lint] }
egress: [pypi.org, files.pythonhosted.org]
With uv:
version: 1
checks:
setup:
- run: uv sync --frozen
cache: { key: [uv.lock], paths: [.venv] }
jobs:
lint: { run: uv run ruff check . }
test: { run: uv run pytest, needs: [lint] }
egress: [pypi.org, files.pythonhosted.org]
Go
version: 1
checks:
setup:
- run: go mod download
cache: { key: [go.sum], paths: [/var/lib/hookci/go-mod] }
jobs:
vet: { run: go vet ./... }
test: { run: go test ./..., needs: [vet] }
egress: [proxy.golang.org, sum.golang.org]
Adjust the cache path to wherever your GOMODCACHE points.
Rust
version: 1
checks:
setup:
- run: cargo fetch --locked
cache: { key: [Cargo.lock], paths: [target] }
jobs:
clippy: { run: cargo clippy --all-targets -- -D warnings }
test: { run: cargo test --locked, needs: [clippy] }
limits: { memory: 8G }
egress: [index.crates.io, static.crates.io]
docker-compose with postgres
Use services.postgres for a database the tests can connect to, instead of managing a compose stack in the job.
version: 1
checks:
services:
postgres: true
setup:
- run: npm ci
cache: { key: [package-lock.json], paths: [node_modules] }
jobs:
test:
run: npm test
timeout: 20m
egress: [registry.npmjs.org]
If a docker-compose.yml is present and no config exists, the docker-compose detector builds jobs from it. Check with hookci detect.
Monorepo with needs
Fan out independent packages and join them with needs:
version: 1
checks:
on:
pull_request: true
push: { branches: [main] }
limits: { cpus: 2, memory: 4G, timeout: 15m, tasks: 512 }
setup:
- run: pnpm install --frozen-lockfile
cache: { key: [pnpm-lock.yaml], paths: [node_modules] }
jobs:
lint: { run: pnpm -r lint, annotate: eslint }
api-test: { run: pnpm --filter api test, needs: [lint], limits: { memory: 6G } }
web-test: { run: pnpm --filter web test, needs: [lint] }
e2e: { run: pnpm --filter e2e test, needs: [api-test, web-test], timeout: 25m }
egress: [registry.npmjs.org]
api-test and web-test run in parallel up to --slots. e2e starts only after both pass.
Auto-detected versus explicit
| Auto-detected | Explicit .hookci.yml |
|
|---|---|---|
| Jobs | Derived from your tooling | Whatever you list |
needs ordering |
Chosen by the detector | You define it |
| Limits | Agent defaults | checks.limits and per job |
| Cache | Detector defaults | Your setup[].cache |
| Trust and forks | Safe defaults | You set them, see Trust and forks |
| Egress hosts | Hosts for the detected package registry | Your egress list |
Field details: reference.