This file is the canonical instruction set for AI coding agents (Claude Code, Cursor, Codex, Aider, etc.) working in this repo. It overrides any conflicting tool defaults. Read it before starting work.
If anything below conflicts with explicit instructions from the human in the current session, follow the human.
- Package manager: pnpm 9.15.0 (pinned via
packageManager). Never use npm or yarn. - Language: TypeScript, run directly via
tsx(no separate build step in the dev loop). - Runtime: Node.js 22+.
- Test runner: built-in
node:testvianode --test --import tsx. - Lint: oxlint. Format: oxfmt. (Not eslint, not prettier, not biome.)
- Releases: changesets. Versions and CHANGELOGs are bot-managed; do not edit them by hand.
- Validation: zod schemas at every boundary (manifests, configs).
generata/
├── packages/
│ ├── core/ # @generata/core - the published engine + CLI
│ └── templates/<name>/ # git-cloned templates (not published as npm packages)
├── .changeset/ # pending changesets, consumed by the release workflow
├── .github/workflows/ # ci.yml, release.yml
└── (root configs)
The engine's public API is exactly what packages/core/src/define.ts exports. Internals (engine, registry, runner, precheck, metrics) are not part of the public API and may change without a major bump.
- Never push directly to
main. Branch protection enforces it; direct pushes will be rejected. - Branch names follow
<type>/<short-description>. Types:feat,fix,chore,docs,refactor,test,ci. Examples:feat/init-flag,fix/resolver-subdir,chore/bump-deps. - One PR = one logical change. Don't mix unrelated edits.
- Merge style is squash only. The merge commit message defaults to the PR title — keep PR titles in conventional-commit format (
feat:,fix:, etc.). - Use
gh pr create --fill && gh pr merge --squash --autoto push and queue auto-merge once CI passes. - After merge, the source branch is auto-deleted by GitHub. Don't manually clean up.
- Claude Code shortcut: invoke
/shipto run the full sequence (branch from latest main, commit, push, PR, matchingpatch/minorchangeset). See.claude/skills/ship/SKILL.md.
Before committing, run:
pnpm fmt && pnpm lint && pnpm typecheck && pnpm testIf you touched anything in packages/core/src/, also run:
pnpm buildIf the change is release-worthy (anything a consumer of @generata/core would notice), also:
pnpm changesetThe interactive prompt asks for the package, the bump type, and a one-line summary. The summary becomes the CHANGELOG entry. Pick:
- patch — bug fixes, internal refactors, doc tweaks that don't change behaviour
- minor — new features, new flags, new exports
- major — breaking changes to the public API
Commit the generated .changeset/<name>.md file with the code change in the same PR. Don't add changesets in a separate "release" PR.
If the change is not release-worthy (CI tweaks, internal docs, test fixtures), skip the changeset.
- Do not run
npm installoryarn install. Alwayspnpm install. - Do not push to
maindirectly under any circumstances. - Do not edit version numbers in
packages/*/package.jsonmanually. The changeset workflow handles bumps. - Do not edit
CHANGELOG.mdfiles manually. Changesets prepends entries. - Do not add backwards-compatibility shims, deprecation comments, or feature flags for changes that haven't been released yet. Just edit the code.
- Do not introduce eslint, prettier, biome, jest, vitest, mocha, or other tooling that duplicates what's already here.
- Do not switch the bin (
packages/core/bin/generata) from its currentnode --import tsxre-launch pattern unless the user explicitly asks. - Do not invent template specifier syntax. The resolver supports: catalog aliases (
@generata/<name>), GitHub short form (<owner>/<repo>), full git URLs, absolute/relative local paths. - Do not run destructive git operations (
git reset --hard,git push --force,git branch -D) without explicit user authorisation.
- Public API surface is
packages/core/src/define.ts. The exports map inpackages/core/package.jsonenforces this. Anything else is internal. - Catalog entries in
packages/core/templates.jsonuse the object form:{ "url": "...", "subdir": "...", "ref": "..." }. The plain-string form is supported for back-compat but new entries should use the object form for monorepo subdirs. - TypeScript loading at runtime: the engine loads user
.tsfiles (agent definitions, workflow definitions, project configs) vialoadTs()frompackages/core/src/ts-loader.ts. Never use bareimport()for user files —loadTs()handles tsx's namespace double-wrap quirk. - Project root discovery: the engine anchors on
generata.config.ts(or.mjs/.js) viafindProjectRoot(). Never assumeprocess.cwd()or__dirname— always go throughfindProjectRoot(). - Test fixtures live at
packages/core/test/fixtures/. Thetemplate-fakefixture is exercised by the init smoke test; don't break its shape. - Templates are content, not packages. Files under
packages/templates/<name>/are not built, not bundled, not type-checked as part of the engine. They're copied verbatim byinit. - Agent file names are kebab-case and the loader derives the agent/workflow name from the path under
agentsDir/(soagents/core/plan-dreamer.tsbecomescore/plan-dreamer). Segments must match^[a-z][a-z0-9-]*$. Files and directories prefixed with_(e.g.agents/_out-of-scope.ts) are treated as private/shared modules and skipped by the loader. Use that prefix when an agent file needs a sibling helper without registering it as its own agent.
# Test loop
pnpm test # all tests once
pnpm test -- --watch # watch mode
node --test --import tsx packages/core/src/cli/manifest.test.ts # single file
# Quick CLI try (uses tsx, no build needed)
node --import tsx packages/core/src/cli.ts help
node --import tsx packages/core/src/cli.ts init ./packages/templates/coding /tmp/foo --yes --skip-install
# Build artefacts (only when verifying the published-package path)
pnpm build
./packages/core/bin/generata help
# Pre-commit gauntlet
pnpm fmt && pnpm lint && pnpm typecheck && pnpm test
# Author a release-worthy change
pnpm changeset # then commit alongside the code change- Read
packages/core/src/cli.tsto see how commands dispatch. - Read
packages/core/src/define.tsfor the public API shape. - Read
packages/core/src/cli/init.tsfor the canonical multi-step CLI pattern. - Read
.github/workflows/release.ymlfor the release pipeline. - Read
packages/templates/coding/generata.template.jsonfor a real template manifest example.