Getting Started

Five minutes to your first rendered Noma document.

Install

Install the CLI when you want to author documents outside this checkout:

npm install -g @ferax564/noma-cli
noma --version
noma init my-spec
noma render my-spec/demo.noma --to html --out my-spec/demo.html

Install the VS Code extension for syntax highlighting, folding, embedded YAML / JSON / LaTeX / Mermaid / DOT scopes, and warning scopes for raw escape hatches:

ext install ferax564.noma-language

For contributor work, clone the repo and install dependencies:

git clone https://github.com/ferax564/noma.git
cd noma
npm install

Render an example

The repo ships working examples in examples/ — three full-surface demos, starter templates, the original intro files, and a multi-file book:

npm run noma -- render examples/agent-plan.noma --to html --out dist/agent-plan.html
npm run noma -- render examples/research-thesis.noma --to html --out dist/research-thesis.html
npm run noma -- render examples/tech-doc.noma --to html --out dist/tech-doc.html

Open any of the produced files in a browser — they are fully self-contained and include the default theme inline.

Choose a starter template

Copy a template when you want a known-good document shape before adding project-specific content:

cp examples/templates/research-memo.noma my-research-memo.noma
cp examples/templates/decision-record.noma my-decision.noma
cp examples/templates/technical-spec.noma my-spec.noma
cp examples/templates/agent-refresh.noma my-refresh-pack.noma

The rendered template guide explains when to use each one: templates.noma.

Render to LLM context

npm run noma -- render examples/thesis.noma --to llm
npm run noma -- render examples/thesis.noma --to llm --select claim,evidence,risk
npm run noma -- render examples/thesis.noma --to llm --exclude dataset,plot --budget 12000

The output is deterministic plain text designed for LLM input: typed blocks become [CLAIM], [EVIDENCE], [RISK] tags with attributes preserved. --select and --exclude match AST node types or directive names; --budget trims at a line boundary when possible.

List IDs for agents

npm run noma -- ids examples/thesis.noma
npm run noma -- ids examples/book/book.noma.yml

The registry includes canonical IDs in document order, alias-to-canonical mappings, source line numbers, and basic block metadata. On book manifests it uses the same scoped IDs and aliases as validation and rendering.

Use Noma from agents

The CLI is the stable contract, but two public packages make agent integrations easier:

npm install @ferax564/noma-mcp-server
npm install @ferax564/noma-agent-sdk

Use the MCP server from any stdio-capable MCP host:

{
  "mcpServers": {
    "noma": {
      "command": "npx",
      "args": ["-y", "@ferax564/noma-mcp-server"]
    }
  }
}

Use the TypeScript SDK when you want a small client wrapper and retry-aware patch workflow:

import { NomaTools, NomaWorkflow } from "@ferax564/noma-agent-sdk";

const tools = await NomaTools.spawn();
try {
  const workflow = new NomaWorkflow(tools);
  const result = await workflow.safePatch("memo.noma", {
    op: "update_attribute",
    id: "launch-decision",
    key: "status",
    value: "accepted",
  });
  if (!result.ok) throw new Error(result.error);
} finally {
  await tools.close();
}

The server exposes read_doc, list_ids, validate_doc, and patch_block. The SDK remains experimental during v0.x; the patch schemas and CLI behavior are the stable surface.

Validate

npm run noma -- check examples/thesis.noma
npm run noma -- check examples/research-thesis.noma --stale-days 30

The validator catches duplicate IDs, broken references (including [[wikilink]] targets across all chapters of a book), plots missing data, plots referencing unknown datasets or unknown columns, figures without alt text, claims missing evidence, risks without owners, decisions without status, agent tasks without scope, state_change blocks missing block/from/to, citations older than the staleness window, untrusted ::html / ::svg / ::script escape hatches, and (when a profile is declared in frontmatter) any directive outside the declared profile. Add the noverify flag attribute to any block to silence rules on it individually.

The staleness window defaults to 365 days. Override it for one document via stale_citation_days: 30 in frontmatter, for one citation via stale_after_days=30 on the citation, or globally with --stale-days 30 on the CLI.

Pick a theme

npm run noma -- render examples/research-thesis.noma --to html --theme dark

Two themes ship with the CLI: default (warm cream paper) and dark. Inside a document, use {variant="important|subtle|success|danger|info"} on a card, callout, or claim/evidence/risk block to switch its emphasis without touching CSS.

Render a multi-file book

Multi-file projects use a YAML manifest with a .yml / .yaml extension. The CLI auto-detects it:

npm run noma -- render examples/book/book.noma.yml --to html --out dist/book.html
npm run noma -- render examples/book/book.noma.yml --to llm

Chapter paths inside the manifest resolve relative to its directory.

Patch a block (without rewriting the file)

npm run noma -- patch examples/thesis.noma \
  --op '{"op":"update_attribute","id":"asml-euv-moat","key":"confidence","value":0.95}' \
  --inplace

Seven ops cover the common editing flows: replace_block, replace_body, update_heading, add_block, delete_block, update_attribute, rename_id. The source-preserving patch path rewrites only addressed line ranges or inserted blocks, so unrelated bytes stay byte-identical. See agent-protocol.noma and compatibility.noma for the schema and compatibility policy.

For multi-op agent edits, use a transaction-shaped --ops file:

{
  "ops": [
    { "op": "update_attribute", "id": "asml-euv-moat", "key": "confidence", "value": 0.95 }
  ],
  "prevalidate": true,
  "postvalidate": true
}
npm run noma -- patch examples/thesis.noma --ops patch.json --inplace

The CLI writes only after every operation applies to an in-memory candidate. If postvalidate finds errors, the original file is left unchanged.

Print the bundled machine-readable schemas when an agent or CI integration needs to validate payloads before calling the CLI:

npm run noma -- schema patch-op
npm run noma -- schema ast

Render with strict HTML safety

npm run noma -- render examples/tech-doc.noma --to html --strict --out dist/tech-doc-strict.html

--strict blocks raw ::html, ::svg, and browser ::script escape hatches and omits external CDN runtimes for math, diagrams, and Plotly. Use it for review or publishing contexts where the artifact must not execute untrusted markup.

Render in GitHub Actions

Add this workflow to another repository to validate, render, and upload a Noma artifact on every push and pull request:

name: Render Noma docs

on: [push, pull_request]

jobs:
  noma:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ferax564/noma@v0.11.0
        with:
          input: docs/spec.noma
          output: dist/spec.html
          to: html
          strict: true
          artifact-name: spec-preview

The action installs the CLI from the checked-out action ref by default, runs noma check, renders the requested target, and uploads the output with actions/upload-artifact. For book manifests, set to: site and point output at a directory. If you need an explicit package source, set cli-package to any npm package spec or cli-version to an @ferax564/noma-cli npm version range.

Re-align tables in source

npm run noma -- fmt examples/research-thesis.noma --inplace

GitHub-style pipe tables get rebuilt to a single column width. Tables inside fenced code blocks are skipped. Pipes inside ` code spans and \| escapes are preserved. Idempotent — running fmt` twice produces the same output.

Connect a plot to a dataset

Stop authoring numbers twice — link a plot to a sibling dataset by id:

::dataset{id="vertical-arr"}
schema:
  vertical: string
  growth: number
rows:
  - [legal, 3.4]
  - [healthcare, 2.9]
::

::plot{id="arr" type="bar" dataset="vertical-arr" column="growth" xcolumn="vertical"}
::

column= selects the y-series. xcolumn= (optional) pulls categorical labels from a string column. The validator emits errors when the dataset id or column name don't resolve.

Declare a profile

Tell downstream tools which directives the document guarantees to use:

---
profile: research
---

Three built-in profiles ship: minimal (markdown-equivalent), technical (product docs, landing pages), and research (theses, ADRs, recap docs). The validator warns on any out-of-profile directive. Omit the field to keep the open surface.

Render to PDF

The PDF pipeline shells out to Chromium via Puppeteer:

npm run demo

This renders all examples to HTML and produces dist/thesis.pdf. On first run, Puppeteer downloads a Chromium build (~150 MB).

Write your own

Create mydoc.noma:

---
title: My First Noma Document
---

# Hello, Noma

::callout{tone="tip"}
Plain text in. Structured documents out.
::

::claim{id="my-first-claim" confidence=0.7}
Documents that know their own structure are more useful than documents that don't.
::

Then render:

npm run noma -- render mydoc.noma --to html --out dist/mydoc.html

Where to next

  • Read docs/spec.noma for the full format specification.
  • Read PLAN.md for the long-term vision.
  • Read CLAUDE.md if you are an agent contributing to this repo.

Next guides