Skip to main content

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:

PackageDescription
@nudojs/coreType system (Abs algebra), extensional rendering (format), Environment
@nudojs/parserBabel parse, directive extraction, parseCaseArgExpr
@nudojs/cliCLI commands only (infer, check, types, watch, generate, harvest, test, interface)
@nudojs/serviceHigh-level API: analyzeFile, getTypeAtPosition, getCompletionsAtPosition
@nudojs/lspLanguage Server Protocol implementation, including AI-agent executeCommand/custom requests (see the Agent guide)
@nudojs/harvesterConverts @types/*.d.ts declarations into Nudo env files (powers nudo harvest)
@nudojs/envBuilt-in environment type definitions (/// @nudo:env es|web|node, subpath exports /es /web /node)
vite-plugin-nudoVite plugin for type inference during dev
nudo-vscodeVS Code / Cursor extension
websiteDocusaurus 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:

  1. Binary arithmetic / comparison — packages/core/src/algebra/arithmetic.ts (Abs-to-Abs). Unary ops and strict equality live in packages/core/src/algebra/surface.ts (typeofAbs, negAbs, notAbs, strictEqAbs).

  2. Branch merge helpers — packages/service/src/evaluator/abs-route.ts (tryAbsJoinObjects, φ-constraint helpers) joins object shapes when branches merge.

  3. Add tests in packages/core/src/algebra/__tests__/ (e.g. surface.test.ts, arithmetic.test.ts) or packages/service/src/__tests__/.


How to Add New Directives​

  1. Define the directive type in packages/parser/src/directives.ts:

    export type MyDirective = { kind: "my"; param: string };
    export type Directive = CaseDirective | ... | MyDirective;
  2. 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: ... }
  3. Use the directive in the evaluator or service:

    • packages/cli/src/index.ts or packages/service/src/analyzer.ts for analysis behavior.
    • Filter fn.directives by d.kind === "my" and apply your logic.
  4. Update parseCaseArgExpr if the directive takes type-expression arguments.

  5. 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 build and pnpm run test before 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/website in 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 type over interface and enum.
  • Structure: Avoid class/OOP; use plain functions and objects.
  • Mutability: Minimize let; prefer const and pure functions.
  • Control flow: Minimize conditional branches; use early returns and small functions.