Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CLI guide

Reference for project.yaml, every subcommand, and editor / LSP integration.

MarkSpec follows the Command Line Interface Guidelines. Every command supports --help. Commands that produce structured output support --format json for machine-readable output to stdout (diagnostics always go to stderr).

Exit codes: 0 success, 1 error, 2 warnings only (validate).

Global options (available on every command):

FlagDescription
-h, --helpShow help
-V, --versionShow version
-q, --quietSuppress non-error output

Project configuration

project.yaml

Every MarkSpec project requires a project.yaml in the project root. MarkSpec discovers it by walking up from the current directory.

Minimal example

name: my-project
version: "1.0.0"

Complete example

name: io.acme.braking-system
version: "2.3.0"
labels:
  - ASIL-A
  - ASIL-B
  - ASIL-C
  - ASIL-D
parents:
  - https://acme.com/refhub
parent-fallback: https://driftsys.github.io/refhub

Fields

FieldTypeRequiredDefaultDescription
namestringyesProject name. Reverse-DNS convention recommended.
versionstringyes"0.0.0"Project version. Quote in YAML to avoid number coercion.
labelsstring[]no[]Allowed label vocabulary. Empty means no constraint.
parentsstring[]no[]Upstream parent registry URLs, searched in order.
parent-fallbackstringnohttps://driftsys.github.io/refhubFallback registry when parents don’t resolve a reference.

Directory conventions

MarkSpec does not enforce a directory layout. By convention:

  • docs/ — Markdown files containing requirements and design documentation
  • src/ — source code with doc-comment entries (Rust ///, Kotlin /**)
  • project.yaml — project root marker

The compile and report commands accept explicit paths or globs:

markspec compile "docs/**/*.md"
markspec compile docs/requirements.md src/main.rs

Profile configuration (.markspec.yaml and profile manifests) is covered in the Profile guide.


Commands

Authoring

format

Stamp ULIDs, fix indentation, normalize attributes.

markspec format <file...>
markspec format --check <file...>
FlagTypeDefaultDescription
--checkboolfalseReport changes without writing. Exit 1 if changes needed

Examples:

# Format a single file (writes changes in place)
markspec format docs/requirements.md

# Format multiple files
markspec format docs/*.md

# Check mode for CI — reports but doesn't modify
markspec format --check docs/*.md

validate

Check broken refs, missing Ids, malformed entries, duplicates.

markspec validate <file...>
FlagTypeDefaultDescription
--strictboolfalsePromote warnings to errors
--formatstringtextOutput format: json, text

Examples:

# Validate a file
markspec validate docs/requirements.md

# Strict mode — warnings become errors (useful for CI)
markspec validate --strict docs/requirements.md

# JSON output for tool integration
markspec validate --format json docs/*.md

Querying

show

Show details of a single entry by display ID or ULID.

markspec show <id> <paths...>
FlagTypeDefaultDescription
--formatstringtextOutput format: json, text

Examples:

markspec show STK_PRJ_0001 "docs/**/*.md"
markspec show --format json STK_PRJ_0001 docs/requirements.md

context

Walk the Satisfies chain upward from an entry to see what it ultimately satisfies.

markspec context <id> <paths...>
FlagTypeDefaultDescription
--depthnumber10Maximum depth to walk
--formatstringtextOutput format: json, text

Examples:

markspec context SRS_PRJ_0001 "docs/**/*.md"
markspec context --depth 3 SRS_PRJ_0001 docs/requirements.md

dependents

List all entries that depend on (satisfy) a given entry.

markspec dependents <id> <paths...>
FlagTypeDefaultDescription
--formatstringtextOutput format: json, text

Examples:

markspec dependents STK_PRJ_0001 "docs/**/*.md"

Building

compile

Parse files, build traceability graph, output compiled result.

markspec compile <paths...>
FlagTypeDefaultDescription
--formatstringtextOutput format: json, text

Examples:

# Summary output
markspec compile "docs/**/*.md"

# Full JSON output for downstream tools
markspec compile --format json "docs/**/*.md" > compiled.json

report

Generate a traceability matrix or coverage report.

markspec report <kind> <paths...>

kind is one of: traceability, coverage.

FlagTypeDefaultDescription
--formatstringmdOutput format: md, json, csv
--scopestringFilter by domain abbreviation
--labelstringFilter by label value
--outputstringWrite to file instead of stdout

Examples:

# Traceability matrix in Markdown
markspec report traceability "docs/**/*.md"

# Coverage report as CSV
markspec report coverage --format csv "docs/**/*.md"

# Write to file
markspec report traceability --output matrix.md "docs/**/*.md"

# Filter by label
markspec report traceability --label ASIL-B "docs/**/*.md"

export

Emit the compiled traceability graph in a portable format.

markspec export <format> <paths...>

Supported formats: json, yaml, csv.

Examples:

# JSON export
markspec export json "docs/**/*.md" > compiled.json

# CSV — one row per entry with display ID, title, type, shape, id, file, line
markspec export csv "docs/**/*.md" > entries.csv

# YAML
markspec export yaml "docs/**/*.md"

insert

Append a scaffolded entry block to a file. This is the agent write path — use it from scripts or AI agents rather than hand-authoring new blocks.

markspec insert <type> <file>
FlagTypeDefaultDescription
--printboolfalseEcho the inserted block to stdout as well

The command:

  1. Finds the highest existing display ID for <type> in <file>.
  2. Computes the next sequential display ID.
  3. Generates a fresh ULID.
  4. Appends the block with a blank separator.

Example:

markspec insert requirement docs/requirements.md --print
# → appends SRS_PRJ_0003, prints block to stdout

Follow with markspec format to normalize indentation and markspec validate to confirm no broken references.

create

Print a scaffolded entry block without writing it to any file.

markspec create <type> <paths...>

Example:

markspec create requirement "docs/**/*.md"

next-id

Print the next available display ID for a profile-declared type without creating an entry.

markspec next-id <type> <paths...>
FlagTypeDefaultDescription
--formatstringtextOutput format: json, text

Example:

markspec next-id requirement "docs/**/*.md"
# → SRS_PRJ_0004

markspec next-id requirement "docs/**/*.md" --format json
# → {"type":"requirement","displayId":"SRS_PRJ_0004"}

lint

Run prose-quality analysis on entries (INCOSE lexicon, modal keywords, structural checks). Returns MSL-Q and MSL-M codes.

markspec lint <paths...>
FlagTypeDefaultDescription
--formatstringtextOutput format: json, text
--strictboolfalsePromote warnings to errors

Lint does not run as part of validate or the pre-commit hook. It is a review-time quality gate.

Examples:

markspec lint docs/requirements.md
markspec lint --strict "docs/**/*.md"
markspec lint --format json "docs/**/*.md"

hook

Run format --check and validate on a list of files. Designed as a pre-commit hook entry point.

markspec hook [files...]

Exits 0 when no files are given (nothing staged). Exits 1 if any file needs formatting or has validation errors.

See Pre-commit hook for setup instructions.

Documents

doc build

Generate a single-document PDF via Typst.

markspec doc build <file>
FlagTypeDefaultDescription
-o, --outputstring<file>.pdfOutput file path

Examples:

markspec doc build docs/spec.md
markspec doc build -o output/spec.pdf docs/spec.md

Books

book build

Generate a multi-chapter static HTML site from a SUMMARY.md.

markspec book build
FlagTypeDefaultDescription
-o, --outputstring_siteOutput directory
-s, --summarystringSUMMARY.mdSUMMARY.md path

Examples:

markspec book build
markspec book build -o dist -s docs/SUMMARY.md

Profile and diagnostics

profile show

Show the active profile chain and effective configuration.

markspec profile show
FlagTypeDefaultDescription
--formatstringtextOutput format: json, text

profile new

Scaffold a new profile directory with a starter manifest.

markspec profile new <id>

<id> must be lowercase alphanumeric with hyphens, optionally scoped (@org/name).

markspec profile new my-profile
markspec profile new @acme/iso26262

Creates <id>/markspec.yaml and <id>/README.md.

profile add

Add a profile to the project’s .markspec.yaml.

markspec profile add <spec>

<spec> is a local path or a scoped package name.

markspec profile add ./profiles/my-profile
markspec profile add @driftsys/iso26262

profile publish

Validate a profile manifest for publishability and print any issues.

markspec profile publish [--dir <dir>] [--format json|text]

Checks required fields (id, version), warns about missing description and license, and reports any manifest validation errors. Exits 0 when the manifest is publish-ready.

profile describe

Show full details for a profile element (type, attribute, relation, label, or convention).

markspec profile describe <kind> <name>

kind is one of: type, attribute, relation, label, convention.

markspec profile describe type requirement
markspec profile describe attribute ASIL
markspec profile describe relation Satisfies

doctor

Project health check: verifies project.yaml, profile configuration, and project structure.

markspec doctor
FlagTypeDefaultDescription
--formatstringtextOutput format: json, text

AI agent integration

mcp

Start the MarkSpec MCP server. Communicates over stdio JSON-RPC. Exposes the active project as MCP resources and tools to any MCP-capable AI client (Claude Code, Claude Desktop, GitHub Copilot in VS Code, OpenCode).

markspec mcp
Resources
  • markspec://profile — distilled profile manifest (types, attributes, link kinds, labels).
  • markspec://entries — index of all project entries, grouped by type.
  • markspec://entry/{displayId} — one entry per resource, with attributes, body, outgoing/incoming links.
Tools
  • entry_search { query, limit? } — rank-search entries by display ID and title.
  • entry_context { id, depth? } — walk the satisfies chain upward.
  • validate { files? } — run the validator, return a Markdown diagnostics report.
  • markspec_refresh — force-invalidate the compile cache (call after agent edits to guarantee freshness).
Claude Desktop config

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "markspec": {
      "command": "markspec",
      "args": ["mcp"],
      "cwd": "/path/to/your/markspec-project"
    }
  }
}

Restart Claude Desktop. The MarkSpec resources and tools appear in the attach menu.

Claude Code
claude mcp add markspec --command markspec --args mcp --cwd /path/to/project
VS Code (Copilot)

The markspec-ide extension auto-registers the MarkSpec MCP server with VS Code 1.101+ — install the extension and the server appears in Copilot’s MCP picker. See Editor and LSP integration — VS Code below.

For users who don’t run the extension, the manual recipe still works. Add a .vscode/mcp.json in your project:

{
  "servers": {
    "markspec": {
      "command": "markspec",
      "args": ["mcp"]
    }
  }
}

Copilot does not support MCP resource subscriptions today, but the markspec:// resources still work — the server runs a fresh staleness check on every read, so a re-read after an edit returns up-to-date content.

mcp install

Print MCP server configuration for a client.

markspec mcp install --client <client>

Supported clients: claude-desktop, cursor, vscode.

markspec mcp install --client claude-desktop
markspec mcp install --client cursor
markspec mcp install --client vscode

lsp install

Print LSP server configuration for an editor.

markspec lsp install --editor <editor>

Supported editors: vscode, neovim, zed.

markspec lsp install --editor neovim
markspec lsp install --editor zed

Not yet implemented

These commands are registered but print an error and exit:

CommandIntended purpose
book devLive preview with hot reload
deck buildSlides → PDF via Touying/Typst
deck devLive slide preview

Editor and LSP integration

MarkSpec ships a built-in Language Server Protocol (LSP) server. Run it with:

markspec lsp

The server communicates over stdio JSON-RPC — the standard transport that every LSP-capable editor supports.

Features

Diagnostics — broken references, missing IDs, duplicate display IDs, and malformed entries appear as inline errors and warnings as you type. File-local checks run immediately; cross-file validation runs on save.

Entry block completion — type - [ at the start of a line to get a pre-filled entry block scaffold with the next available display ID for each type defined in your profile.

ID reference completion — after a trace attribute keyword (Satisfies:, Derived-from:, Verified-by:, etc.) the server suggests all known display IDs in the project.

Source file context guard — in source files (Rust, Kotlin, Java, C, C++), completions only activate near entry markers or trace keywords. The server won’t interfere with your language’s native LSP (rust-analyzer, kotlin-lsp, etc.).

VS Code

Install the MarkSpec extension from the editors/vscode/ directory in this repository. The extension requires VS Code 1.101 or newer (the version that introduced the stable MCP extension API).

The extension provides two integrations in one install:

  • LSP — diagnostics, completions, and entry-block scaffolding in the editor.
  • MCP — registers a markspec MCP server with VS Code so Copilot (and any other MCP-aware client) can use the project’s resources and tools without a separate .vscode/mcp.json.

Both point at the same markspec binary, resolved from markspec.server.path.

From source

cd editors/vscode
npm install
npm run compile

Then in VS Code: Extensions → ⋯ → Install from VSIX or press Ctrl+Shift+PExtensions: Install from VSIX… and select the .vsix file, or use the development host:

code --extensionDevelopmentPath=editors/vscode

Configuration

SettingDefaultDescription
markspec.server.path"markspec"Path to the markspec binary (used by both LSP and MCP).
markspec.server.args["lsp"]Arguments passed to start the LSP server.
markspec.mcp.enabledtrueRegister the MarkSpec MCP server with VS Code.
markspec.mcp.args["mcp"]Arguments passed to start the MCP server.
markspec.trace.server"off"Trace level: off, messages, or verbose.

If markspec is not on your PATH, set the full path:

{
  "markspec.server.path": "/home/you/.local/bin/markspec"
}

MCP server

Once the extension is installed, the MarkSpec MCP server appears in Copilot’s MCP picker — no .vscode/mcp.json required. To disable the registration:

{
  "markspec.mcp.enabled": false
}

The manual .vscode/mcp.json recipe in mcp — VS Code (Copilot) remains supported for editors that don’t run the extension.

Neovim

Neovim’s built-in LSP client works out of the box. Add this to your init.lua:

vim.api.nvim_create_autocmd("FileType", {
  pattern = { "markdown" },
  callback = function()
    vim.lsp.start({
      name = "markspec",
      cmd = { "markspec", "lsp" },
      root_dir = vim.fs.root(0, { "project.yaml", ".git" }),
    })
  end,
})

For source files (Rust, Kotlin, etc.) where MarkSpec entry blocks appear in doc comments, add the relevant file types to the pattern list:

pattern = { "markdown", "rust", "kotlin", "java", "c", "cpp" },

The server’s context guard ensures it only activates near MarkSpec entry markers, so it won’t conflict with rust-analyzer or other language servers running on the same buffer.

With nvim-lspconfig

If you use nvim-lspconfig, add a custom server definition:

local lspconfig = require("lspconfig")
local configs = require("lspconfig.configs")

if not configs.markspec then
  configs.markspec = {
    default_config = {
      cmd = { "markspec", "lsp" },
      filetypes = { "markdown", "rust", "kotlin", "java", "c", "cpp" },
      root_dir = lspconfig.util.root_pattern("project.yaml", ".git"),
    },
  }
end

lspconfig.markspec.setup({})

Other editors

Any editor with LSP support can use markspec lsp. The server expects:

  • Transport: stdio (stdin/stdout JSON-RPC)
  • Trigger characters: [ (block scaffold) and : (ID reference)
  • Document sync: full text on each change

Point your editor’s LSP client at markspec lsp and it should work. If your editor needs a specific configuration example, please open an issue.