Thanks for considering a contribution. Whether you're fixing a bug, adding a parser, writing an emitter, or improving documentation, this guide will get you oriented quickly.
Nous is a monorepo managed with pnpm workspaces and Turborepo. Every package under packages/ is independently buildable and publishable. Browse the README for a full package index and architecture overview.
- Node.js >= 20.0.0
- pnpm >= 10.18.0 (corepack-managed)
corepack enable
corepack prepare pnpm@10.18.3 --activategit clone https://github.com/salmad3/nousdev.git
cd nousdev
pnpm install
pnpm buildTurborepo handles dependency ordering across packages:
pnpm build # Build all packages
pnpm dev # Start dev server with watch mode
pnpm typecheck # Type-check all packages
pnpm lint # Lint all packages
pnpm test # Run all test suitesTo build a single package:
pnpm --filter @nousdev/agent-metadata buildThe @nousdev/agent-metadata package runs protocol version verification before every build via the prebuild npm lifecycle hook. This check scans emitter code, documentation, and type comments for version strings that have drifted from the centralized manifest at packages/agent-metadata/src/protocols.ts.
If you update a protocol version, edit protocols.ts first, then run:
pnpm --filter @nousdev/agent-metadata verify-protocolsThe script identifies every stale reference with its file path and line number.
pnpm nous devOpens at http://localhost:4321. The site is built entirely with Nous, with every page authored in KD. Changes to parsers, emitters, or the renderer are immediately visible here.
Nous processes documentation through a four-phase pipeline:
-
Parsing: Format-specific parsers (
parser-kd,parser-md, etc.) convert source files into the Nous Document Model (NDM), an immutable semantic AST. -
Inference: The inference engine analyzes parsed NDM nodes and attaches block-level annotations (
type,audience,answers) to blocks that lack explicit metadata. -
Transformation: Plugins compose pure functions that receive document nodes and return new nodes without mutation. The
agent-metadataplugin collects documents during this phase. -
Emission: The HTML renderer produces human-readable output. The agent-metadata plugin emits machine-readable formats (Schema.org JSON-LD, A2A agent cards, MCP resources, RAG chunks, llms.txt, AGENTS.md, and others).
The NDM is the contract between parsers and consumers. Any format that can produce valid NDM nodes integrates with the full pipeline automatically.
Adding support for a new source format means writing an NDM adapter. KD and KDX have custom parsers because their block annotation model has no upstream equivalent. For other formats, adapters wrap an established parser and convert its AST into NDM nodes.
Each parser package exports a single parse function:
import type { DocumentNode } from '@nousdev/types';
export function parse(source: string, filePath: string): DocumentNode;The returned DocumentNode must conform to NDM types. Adapters should delegate syntax parsing to the upstream library and focus their logic on the AST-to-NDM conversion: mapping frontmatter, headings, code blocks, and (where available) semantic annotations into their corresponding NDM node types.
Agent metadata emitters follow a consistent signature:
import type { ExtractedMetadata, AgentMetadataConfig, EmitterOutput } from '@nousdev/agent-metadata';
export function emitMyFormat(
metadata: ExtractedMetadata,
config: AgentMetadataConfig,
): MyFormatOutput;Register new emitters in packages/agent-metadata/src/emitters/index.ts by adding them to the EMITTER_REGISTRY and ALL_EMITTERS array.
Follow Conventional Commits:
<type>: <description>
<optional body>
| Type | Usage |
|---|---|
feat |
New feature or capability |
fix |
Bug fix |
refactor |
Code restructuring without behavior change |
docs |
Documentation changes |
test |
Adding or modifying tests |
chore |
Build tooling, dependency updates, housekeeping |
perf |
Performance improvement |
ci |
CI/CD pipeline changes |
Keep the subject line under 72 characters. Use the body for context on why the change was made when the diff alone does not make the rationale clear.
- Create a feature branch from
main. - Make changes, ensuring
pnpm buildandpnpm testpass. - Write a PR description that includes:
- A summary of what changed and why.
- A test plan describing how to verify the changes.
- Request review. Address feedback as new commits rather than force-pushing, so reviewers can track incremental changes.
These conventions keep the codebase consistent as it grows. They are enforced in review.
- Immutability: Create new objects rather than mutating existing ones. Transforms return new document nodes; they never modify the input.
- Small files: Aim for 200-400 lines per module. Extract utilities when files exceed 800 lines.
- Explicit error handling: Handle errors at every level. Provide actionable messages.
- Input validation: Validate at system boundaries (user config, file content, external protocol responses).
- No hardcoded protocol versions: All version strings in
@nousdev/agent-metadatamust referenceprotocols.tsconstants. The pre-build verification script enforces this.
- Create the directory under
packages/. - Add a
package.jsonwith the@nousdev/scope and appropriatemain/typesfields. - Add a
tsconfig.jsonextending the root config. - Register the package in
pnpm-workspace.yamlif not already covered by the glob pattern. - Add build/test scripts and wire them into
turbo.jsonif the package has build dependencies on other Nous packages.
Open an issue or start a discussion. We are happy to help you find the right entry point for your contribution.
By contributing to Nous, you agree that your contributions will be licensed under the MIT License.