Contributing
Thank you for your interest in contributing to Nudo. This guide covers setup, project structure, development workflow, and how to extend the system.
Prerequisites
- Node.js 20 or later
- pnpm 8 or later
npm install -g pnpm
Clone and Setup
git clone https://github.com/nudojs/nudo.git
cd nudo
pnpm install
pnpm run build
Project Structure
The monorepo uses pnpm workspaces. Key packages:
| Package | Description |
|---|---|
@nudojs/core | Type system (Abs algebra), extensional rendering (format), Environment |
@nudojs/parser | Babel parse, directive extraction, parseCaseArgExpr |
@nudojs/cli | CLI commands only (infer, check, types, watch, generate, harvest, test, interface) |
@nudojs/service | High-level API: analyzeFile, getTypeAtPosition, getCompletionsAtPosition |
@nudojs/lsp | Language Server Protocol implementation, including AI-agent executeCommand/custom requests (see the Agent guide) |
@nudojs/harvester | Converts @types/*.d.ts declarations into Nudo env files (powers nudo harvest) |
@nudojs/env | Built-in environment type definitions (/// @nudo:env es|web|node, subpath exports /es /web /node) |
vite-plugin-nudo | Vite plugin for type inference during dev |
nudo-vscode | VS Code / Cursor extension |
website | Docusaurus documentation site |
Development Workflow
Run tests
pnpm run test
pnpm run test:watch # watch mode
Build all packages
pnpm run build
Run CLI locally
pnpm exec tsx packages/cli/src/index.ts infer path/to/file.js
# or
pnpm exec nudo infer path/to/file.js
How to Add New Operator Semantics (Abs-native)
Operator semantics live in the algebra, not a separate Ops layer:
-
Binary arithmetic / comparison —
packages/core/src/algebra/arithmetic.ts(Abs-to-Abs). Unary ops and strict equality live inpackages/core/src/algebra/surface.ts(typeofAbs,negAbs,notAbs,strictEqAbs). -
Branch merge helpers —
packages/service/src/evaluator/abs-route.ts(tryAbsJoinObjects, φ-constraint helpers) joins object shapes when branches merge. -
Add tests in
packages/core/src/algebra/__tests__/(e.g.surface.test.ts,arithmetic.test.ts) orpackages/service/src/__tests__/.
How to Add New Directives
-
Define the directive type in
packages/parser/src/directives.ts:export type MyDirective = { kind: "my"; param: string };
export type Directive = CaseDirective | ... | MyDirective; -
Add a regex and parsing logic in
parseDirectivesFromComments:const MY_REGEX = /@nudo:my\s+(\w+)/g;
// In the loop: match, extract, push { kind: "my", param: ... } -
Use the directive in the evaluator or service:
packages/cli/src/index.tsorpackages/service/src/analyzer.tsfor analysis behavior.- Filter
fn.directivesbyd.kind === "my"and apply your logic.
-
Update
parseCaseArgExprif the directive takes type-expression arguments. -
Add tests in
packages/parser/src/__tests__/directives*.test.ts.
PR Guidelines
- Keep PRs focused; prefer several small PRs over one large one.
- Add or update tests for new behavior.
- Run
pnpm run buildandpnpm run testbefore submitting. - Update docs (e.g.
docs/concepts/directives.md, API reference) when adding directives or public APIs. - Docs drift rule: when changing CLI commands/options, exported APIs, or directive syntax, update the documentation under
packages/websitein the same PR — both the English sources (docs/) and the Chinese mirrors (i18n/zh-Hans/docusaurus-plugin-content-docs/current/).
Code Style
- TypeScript: strict mode, ES modules.
- Types: Prefer
typeoverinterfaceandenum. - Structure: Avoid class/OOP; use plain functions and objects.
- Mutability: Minimize
let; preferconstand pure functions. - Control flow: Minimize conditional branches; use early returns and small functions.