FourIA — Contributing Guidelines
On this page
Mandatory development standards for all contributors (humans and AI agents).
Pre-Commit Hook
The .githooks/pre-commit hook runs from the repository root on every commit and
only runs the checks that match the staged files:
# when TypeScript/JavaScript (or other oxfmt-formatted) files are staged:
bun run lint
bun run format:check
# when Elixir files (*.ex/*.exs) are staged:
mix check
mix check is the root Mix workspace alias. It runs mix format --check-formatted
and mix credo --strict for every Elixir project under apps/. Lerma CI invokes the
same strict Credo command from the root. Enter the root Nix development shell first
(nix develop .) so Bun and Mix are available, then fetch all dependencies with
mix deps.get followed by mix workspace.run -t deps.get.
Bun install configures Git to use .githooks through the root package’s prepare
script. If you are not running bun install, enable it manually:
git config core.hooksPath .githooks
The hook is bypassed when HUSKY=0 or SKIP_HOOKS=1 is set in the environment
(the release workflow sets HUSKY=0 so release-it can commit version bumps in
CI, which has no Elixir toolchain). When Elixir files are staged but mix is not
installed, the hook skips mix check with a warning instead of failing — run it
in the Nix dev shell (nix develop .) before merging.
Commits are blocked if linting or formatting fails. Run these manually before committing:
bun run lint # oxlint — static analysis
bun run format:check # oxfmt — formatting check
bun run format # auto-fix formatting
bun run lint:fix # auto-fix linting issues
For Elixir changes, run the strict workspace checks (exit 0):
mix credo --strict
mix check
mix precommit
Dependency Automation
Dependencies are updated automatically by Dependabot (.github/dependabot.yml):
| Ecosystem | Scope | Schedule |
|---|---|---|
mix | apps/lerma (Elixir deps) | weekly |
bun | workspace root (bun.lock) | weekly |
github-actions | CI workflows | weekly |
Dependabot PRs are labelled dependencies (+ Lerma or Fouria) and must pass CI before merge.
License Audit (private-source compliance)
Lerma is a private-source project, so its dependencies must not carry copyleft licenses
(GPL, AGPL, LGPL, …). mix lerma.license_audit (run in the Lerma CI workflow via the
root mix license_audit alias) fails when a dependency declares a license outside the
allowlist in Lerma.LicenseAudit.allowed_licenses/0, and also fails when a dependency’s
license cannot be determined.
When adding a new dependency, extend the allowlist deliberately — never blanket-allow a
license without checking its terms.
Test-Driven Development (TDD)
TDD is mandatory. Write failing tests first, then implement.
Coverage Requirements
| Component | Unit Test Coverage | Integration Test Coverage |
|---|---|---|
| API implementations | ≥ 95% | ≥ 80% |
| Business logic | ≥ 80% | ≥ 80% |
| UI components | ≥ 80% | N/A |
| Config/IaC modules | ≥ 80% | N/A |
Testing Tools
| Tool | Purpose |
|---|---|
| Vitest | Unit + integration tests (all packages) |
| cctr | CLI corpus tests for E2E (CLI tools) |
| Playwright | Browser E2E testing for the dashboard |
| jsdom | DOM simulation for React component tests |
AI Skills for TDD
Always load these skills before writing code:
tdd-workflow— Test-driven development methodologyai-regression-testing— Patterns for AI-assisted regression testingwebapp-testing— Playwright-based browser testinge2e-testing— End-to-end testing patternsopenclaw-plugin-tdd— TDD for OpenClaw provider plugins
TDD Workflow
- RED: Write failing test →
bun run testto verify failure - GREEN: Implement minimal code to pass →
bun run testto verify - REFACTOR: Clean up code, keep tests passing
- VALIDATE:
bun run typecheck+bun run lint+bun run test
Runtime: Bun over npm
Always use Bun. Never use npm, yarn, or pnpm.
| Context | Command |
|---|---|
| Install | bun install |
| Run script | bun run <script> |
| Test | bun run test |
| Add dep | bun add <package> |
| Run file | bun <file.ts> |
Exception: CI/CD workflows (GitHub Actions) may use npm for compatibility, but local development MUST use Bun.
Shared Dependencies
Root package.json defines shared dev dependencies via the monorepo workspace:
| Dependency | Version | Purpose |
|---|---|---|
typescript | ^5.9.3 | Type checking (strict mode) |
vitest | ^4.1.8 | Test runner (all packages) |
oxlint | latest | Linting |
oxfmt | latest | Formatting |
wrangler | ^4.97.0 | Cloudflare Workers CLI |
@cloudflare/vitest-pool-workers | 0.16.12 | Vitest integration for Workers |
Catalog dependencies (shared version pinning):
| Package | Version |
|---|---|
openclaw | ^2026.6.6 |
wrangler | latest |
@types/bun | latest |
Always use catalog refs when adding these to sub-package.json: "wrangler": "catalog:"
Code Conventions
TypeScript
- Strict mode (
strict: truein all tsconfig.json files) - Prefer explicit types for function signatures
- Use Zod schemas for config validation
- Never use
anywithout explicit justification - One module per file — never nest multiple classes in one file
Hono (Worker Framework)
- Route handlers should be thin — extract logic to separate modules
- Use
c.json(),c.html()for responses - Middleware order matters: logging → auth → RBAC → route handler
Environment Variables
- Secrets come from env vars, never from config files
- Use Worker Secrets (
wrangler secret put) for production - Use
.dev.varsfor local development (gitignored) - If changing env vars: update
.dev.vars.example,src/gateway/env.ts, and relevant docs
Naming
- Files: kebab-case (
user-secrets-store.ts) - Functions: camelCase (
buildEnvVars) - Types/Interfaces: PascalCase (
AppEnv) - Constants: UPPER_SNAKE_CASE (
GATEWAY_PORT)
Validation Checklist
Before submitting any change:
-
bun run typecheckpasses -
bun run lintpasses -
bun run format:checkpasses -
bun run testpasses (all packages) - New code has ≥ 80% unit test coverage (≥ 95% for API routes)
- Integration tests pass with ≥ 80% coverage (for API changes)
-
If changing env vars: update
.dev.vars.example, docs, andsrc/gateway/env.ts - If adding routes: add tests
- If releasing: bump component version per VERSIONING.md
Pull Request Guidelines
- One concern per PR — don’t mix feature work with refactoring
- TDD evidence — tests committed before or alongside implementation
- No commented-out code — remove debug lines before PR
- No secrets — never commit
.dev.vars, API keys, or tokens - Use
bun run formatbefore final push
AI Agent Guidelines
When AI agents contribute to this codebase:
- Read
AGENTS.mdfirst — each component has its own AGENTS.md - Load relevant skills — check the
available_skillslist for domain-specific guidance - Follow TDD — write tests before implementation, even when suggested by AI
- Never commit without explicit user approval
- Read OpenClaw docs before modifying OpenClaw-related code (config, CLI, gateway)
- Use the exploration tools to understand existing patterns before writing new code