- Keep one clear owner for each fact. Do not repeat provider metadata such as
displayNamein executors when it already belongs todefinition.ts; pass or inject it from the caller that has the definition/catalog. - Provider definitions are catalog source code. Build schemas with
src/core/json-schema.tshelpers, usually imported ass, instead of copying generated catalog JSON. - Keep runtime lazy: catalog generation may import provider definitions, but executor modules should load only when an action or credential validator is actually used.
- Do not create barrel files such as
index.ts. Import from the concrete module that owns the API.
- Prefer VS Code-style coherent modules: split files by responsibility or abstraction boundary, not by loose categories.
- Prefer
interfacefor object-shaped contracts. Keep unions and mapped/utility compositions astype. - Prefer named options/input interfaces over inline object types when a function signature spans multiple lines or crosses module boundaries.
- Avoid temporary ad hoc objects passed through many layers. Prefer explicit interfaces, classes, or top-level functions that match module boundaries.
- Put generic low-level casting/reading helpers in
src/core/cast.ts; avoid provider-specific wrappers for generic reads. - Avoid trivial pass-through helpers and conditional object spreads that only hide
undefinedJSON fields. - Do not manually wrap code to 80 columns. Let
oxfmtdecide formatting.
- Keep
/v1response shaping insrc/server/runtime-api.ts; route handlers should dispatch and validate, not assemble compatibility objects field by field. - Public runtime fields should have a clear source and consumer. Do not expose local implementation concepts or placeholder fields just because they are easy to add.
- Match existing runtime wire shapes deliberately: catalog index endpoints, action metadata, connection aliases, envelopes, and error codes should stay stable for SDK/CLI clients.
- If an upstream-compatible field has no local source yet, prefer omitting it or returning a documented empty value from the serializer rather than scattering optional fields in routes.
- Provider code normally lives in
src/providers/<service>/definition.ts,actions.ts,executors.ts, and provider-local runtime helper files when needed. - Prefer provider-local constants for official scopes, permissions, URLs, and API versions. Action
requiredScopesshould use provider-native scopes/capabilities, not private internal aliases. - Avoid repeated action-name wiring. Define action handlers once and derive executor maps through shared provider runtime helpers.
- Do not import provider definitions from executor modules just to reuse metadata; inject catalog metadata from the server/loader side when needed.
- Use native Node.js TypeScript execution. Do not add
tsxor--experimental-strip-types. src/,scripts/, andexamples/each have their owntsconfig.json; project checks focus onsrc.- Exported top-level functions and public types should have explicit return types and useful JSDoc when it explains business meaning.
- Use
oxfmtandoxlint; do not add Prettier.
- Examples should be concrete scripts users can run directly with
node examples/...; do not add every example topackage.json. - If an example depends on external credentials, print a clear skip message when environment variables are missing.
- Do not put web UI code under
src/. The future console should live as a separate Vite package underweb/. - Public docs should describe normal OSS usage and may include official SaaS, hosted, or team product paths when they are part of the public product strategy. Do not mention internal compatibility projects or unreleased SDK behavior.
- Before finishing code changes, run
npm run fix-check. It runs lint fixes, formatting fixes, and thesrctypecheck. - Run
npm run buildonly when you need a separate no-fix typecheck, for example after generated files changed or for CI parity. - Run
npm run generate:catalogwhen provider definitions or actions change. - Run provider examples manually when the task changes user-facing example behavior.