PR & Code Conventions

PR & Code Conventions

Before You Start

  • Check open issues to see if someone is already working on what you have in mind
  • For substantial changes, open an issue first to discuss the approach before writing code
  • For small fixes (typos, docs, obvious bugs), a PR without a prior issue is fine

Branch Naming

fix/short-description
feat/short-description
docs/short-description
refactor/short-description
perf/short-description

Commit Messages

Use Conventional Commits:

feat(plugins): add support for agents in plugin manifests
fix(tui): prevent feed from jumping on permission prompt
docs(workflows): clarify loop schema fields
perf(feed): cache stringWidth results per row

The project uses release-please for automated releases. Commit messages feed directly into the changelog — write them for a reader.

Code Style

  • TypeScript strict mode is enabled (tsconfig.json). Do not use any without a comment explaining why.
  • Prefer explicit types on function signatures. Inferred return types are fine inside function bodies.
  • Use const by default. let only when reassignment is necessary.
  • ESM only — no require(), no CommonJS.
  • Imports: Node built-ins → external packages → internal modules. One blank line between groups.

Formatting is handled by Prettier. Run the linter before committing:

npm run lint
npm run format

Architectural Boundaries

Layer boundaries are enforced by ESLint no-restricted-imports. Violating them will cause CI to fail:

  • core/ must not import from app/, ui/, or harnesses/
  • harnesses/ must not import from app/ or ui/
  • ui/ must not import from harnesses/
  • shared/ must not import from any layer

src/__sentinels__/ contains boundary enforcement tests. Do not add exceptions to ESLint config without a clear architectural justification.

Testing

  • Every new behavior should have a corresponding test.
  • Tests live alongside source files: src/infra/plugins/loader.test.ts tests src/infra/plugins/loader.ts.
  • Use Vitest's vi.mock() for external dependencies (SQLite, file system, socket). Do not make real I/O calls in unit tests.
  • For sentinel/boundary tests, add them in src/__sentinels__/.

Run tests and type-check before opening a PR:

npm test
npm run typecheck
npm run lint

PR Checklist

Before requesting review:

  • npm test passes
  • npm run typecheck passes
  • npm run lint passes with no errors
  • New behavior is covered by tests
  • Architectural boundaries are not violated
  • Public-facing changes (flags, config schema, plugin API) are documented in the relevant docs/ markdown file
  • Commit messages follow Conventional Commits

Releases

Releases are automated via release-please and the GitHub Actions workflow in .github/workflows/. Merging a PR with conventional commit messages causes release-please to open or update a release PR. When that PR is merged, a new version is published to npm automatically.

You do not need to manually bump versions or update changelogs.