Keep your Markdown consistent, connected, and queryable as it grows.
Rootline treats your documentation as structured data. .stem files define schemas (what fields must exist, their types, allowed values). Validation rules enforce consistency. Queries retrieve relevant records without reading every file. Field provenance shows where every value came from and how it was computed. Humans, automation, and AI agents all consume the same governed outputs.
- Installation
- Why It Matters
- Quick Start
- Core Concepts
- Command Capabilities
- Optional Integrations
- Documentation & References
- Development
- License
curl -fsSL https://raw.githubusercontent.com/pablontiv/rootline/master/install.sh | bashirm https://raw.githubusercontent.com/pablontiv/rootline/master/install.ps1 | iexgo install github.com/pablontiv/rootline/cmd/rootline@latestAs Markdown documentation grows, two problems emerge: structural drift and retrieval difficulty. Rootline solves both.
- Schema inheritance prevents drift: Parent directories define rules that child documents inherit. Fields, types, and constraints flow top-down; mutations raise errors immediately.
- Validation rules catch inconsistencies early:
required,enum, and structural constraints enforce consistency without manual review. - Queryable fields eliminate document reading: Search by metadata (estado, tipo, tags) using declarative filters — no grep, no manual scanning.
- Link graphs show dependencies: Discover which documents reference each other, block on external targets, or form cycles.
- Humans, agents, and automation consume the same governed outputs: Stable JSON contracts mean your Markdown structure is machine-readable and auditable.
Rootline does not render documentation. It models it — making your Markdown a queryable, governed knowledge system.
Initialize your documentation directory, validate its structure, and query its contents.
# 1. Initialize — infer a .stem schema from existing documents
# (writes a root: true marker so schema discovery knows where to stop)
rootline init docs/
# 2. Query — find records by metadata
rootline query docs/ --where 'estado == "published"'
# 3. Validate — check documents against their schema rules
# Schema discovery walks up the tree until it hits a root: true .stem
# (or the filesystem root). No Git required.
rootline validate --all docs/
# 4. Graph — render the dependency diagram (Mermaid)
rootline graph docs/ --format mermaid -o table
# 5. New — scaffold a document from the effective schema
rootline new docs/task-001.md
# 6. Explain — trace where a field value came from
rootline explain docs/task-001.mdMost commands output JSON by default. Use --output table for human-readable tables. (graph --check reports cycles and broken links as text plus an exit code.)
- Directory hierarchy: Directories are tables; files are records.
- Inherited rules:
.stemfiles define schemas; rules flow from parent to child via top-down merge. - Derived fields: Expressions compute fields (slugify, concatenate, filter); aggregates roll up from children to parents.
- Links: Documents reference each other via
[[wiki-links]]and[markdown](links), forming a queryable dependency graph. - Queryable outputs: Every command returns stable JSON; records can be filtered, sorted, and projected.
Rootline discovers schemas by walking up your directory tree:
- Start at the target path (file or directory)
- Collect
.stemfiles at each level, moving up toward the filesystem root or aroot: truemarker - Merge collected schemas from root to leaf (parent → child)
Each level can add new fields, override parent definitions, or remove inherited rules (with null). Type-driven merge rules ensure predictable inheritance (maps merge key-level; arrays and scalars replace entirely).
A .stem file with root: true marks the governance boundary; walk-up discovery stops there. Without an explicit marker, discovery continues to the filesystem root. Git is optional — Rootline works in any directory, with or without Git.
A .stem file is the DDL schema for a directory. It defines what fields exist, what types they have, which are required, and how values are validated.
version: 2
schema:
title: { type: string, required: true }
status:
type: enum
values: [draft, review, published]
default: draft
required: true
aggregate:
completed: 'len(filter(descendants, .status == "published"))'
links:
allowed: [blocks, depends]Sections (
type: section) are first-class schema fields — validated, defaulted, and queryable alongside frontmatter.
Validation enforces consistency using rules defined in .stem:
- required: Field must be present and non-empty
- enum: Field value must be one of allowed choices
- type: Field must match declared type (string, number, section, array)
- exists: Path (file or directory) must exist
- structural: Directory naming, required children, index files
Violations are reported as errors; the command exits with code 1. Use --strict to treat warnings as errors.
Queries retrieve relevant records without scanning entire documents:
- Declarative filtering:
--where 'estado == "published" && tipo == "epic"' - Metadata projection:
--select path,estado,titlereturns compact rows - Graph traversal:
--has-inbound/--has-outboundwith link predicates - Counted results:
--countreturns summary statistics
These outputs are JSON, suitable for piping to automation and AI consumers.
Rootline ships as a single static Go binary with no dependencies. Commands are grouped by use case. Most commands support --where 'expr' (expr-lang syntax) to filter records before processing.
Check documents against inherited schemas and trace field origins.
-
validate— Check documents against.stemrulesrootline validate [file...]— Single filerootline validate --all [--where 'expr'] [--strict]— All files in scoperootline validate --staged— Git staging area only
-
describe— Show effective schema for a directoryrootline describe <path>— Merged schema with all inherited rulesrootline describe <path> --by-domain <name>— Filter output by domain
-
explain— Trace field origins, derivations, and errorsrootline explain <file>— See where every value came from
Find records and visualize dependencies.
-
query— Search by metadata using declarative filtersrootline query [path] --where 'expr'— Filter recordsrootline query --where 'expr' --count— Summary countrootline query --where 'expr' --select path,estado,title— Compact row outputrootline query --where 'expr' --has-inbound '<sub-expr>'— Records with inbound linksrootline query --where 'expr' --has-outbound '<sub-expr>'— Records with outbound links
-
tree— Hierarchical view with completion countsrootline tree [path] [--where 'expr']— Directory structure with metadata
-
graph— Dependency graph from wiki-links and markdown linksrootline graph [path]— Dependency graph as JSON (default)rootline graph [path] --format dot|mermaid -o table— Render a diagramrootline graph [path] --check— Validate cycles and broken links (text report + exit code)rootline graph [path] --fail-cycles— Treat cycles as errors
Create and update documents.
-
init— Generate.stemschema from existing documentsrootline init [path]— Infer schema from frontmatter patternsrootline init [path] --template owner/repo[@tag]— Fetch.stemfrom remoterootline init [path] --force— Overwrite existing.stemrootline init [path] --dry-run— Preview without writing
-
new— Scaffold a document from effective schemarootline new <filepath>— Create with frontmatter pre-populatedrootline new <filepath> --force— Overwrite an existing filerootline new <filepath> --dry-run— Preview generated content
-
set— Mutate frontmatter and sections with validationrootline set <file> field=value [field2=value2 ...]— Set fieldsrootline set <file> field=@file— Load content from filerootline set <file> field+=@file— Append to sectionrootline set <file> ... --create— Create new sectionsrootline set <file> ... --dry-run— Preview changes
-
fix— Auto-repair validation errorsrootline fix [file...]— Fix single filerootline fix --all— Fix all files in scoperootline fix --dry-run— Preview proposed changes
Analyze patterns and manage schema evolution.
-
analyze— Run 14 inference detectors (12 data + 2 governance)rootline analyze [directory]— Produce structured reportrootline analyze [directory] --incremental— Only inferences not covered by existing.stem
-
schema— Schema operationsrootline schema propose [directory]— Generate schema proposalsrootline schema apply --report <file>— Apply schema proposals to.stemfiles
-
repair— Apply data-only repairs from analyze reportrootline repair apply --report <file>— Fix frontmatter only (not.stem)rootline repair apply --report <file> --dry-run— Preview repairs
-
migrate— Detect and apply schema changesrootline migrate [path]— Compare current.stemagainst git HEADrootline migrate [path] --rename old_field=new_field— Bulk field renamerootline migrate [path] --split— Convert flat.stemto hierarchical per-level filesrootline migrate [path] --scaffold— Create missing required sectionsrootline migrate [path] --dry-run— Preview without modifying
-
completion— Generate shell completion scriptsrootline completion bash|zsh|fish— Load in your shell
-
hooks— Git pre-commit hook managementrootline hooks install— Enable pre-commit validationrootline hooks status— Check installation statusrootline hooks uninstall— Remove hook
All commands support --output json|table and --field for dot-path extraction, including array projection:
# Dot-path extraction
rootline describe docs/prd/ --field schema.id.next
# "T004"
# Simple field projection from query
rootline query --where 'estado == "Pending"' --field path
# docs/projects/P01/tasks/T005-deploy-grafana.md
# Array projection: extract fields from arrays (rows, edges, etc.)
rootline query --field 'rows[].path'
# ["docs/projects/P01/tasks/T005-deploy-grafana.md", ...]
rootline query --field 'rows[].frontmatter.estado'
# ["Pending", "In Progress", ...]
rootline graph docs/ --field 'edges[].source'
# ["docs/api/auth.md", ...]
# Compact query projections with --select (JSON, JSONL, CSV)
rootline query --select path,estado,title
# {"rows": [{"path": "...", "estado": "Pending", "title": "..."}, ...]}
rootline query --select path,estado --output jsonl
# {"path": "...", "estado": "Pending"}
# {"path": "...", "estado": "In Progress"}
rootline query --select path,estado,title --output csv
# path,estado,title
# docs/api/auth.md,Pending,Authentication Guide
# docs/api/endpoints.md,In Progress,Endpoint Reference
# Filtering across commands
rootline tree docs/epics/ --where 'estado != "Completed"'
rootline stats docs/epics/ --where 'tipo == "software-module"'
rootline graph docs/epics/ --where 'tipo != "feature"' --checkQueries use expr-lang/expr syntax. Multiple --where flags are combined with AND:
rootline query --where 'estado == "Pending"'
rootline query --where 'tipo in ["lxc", "vm"]' --where 'estado != "Completed"'
rootline query --where 'body contains "migration"'
rootline query --where 'tags != nil' --count.stem files can define derived fields (computed per-record) and aggregates (rolled up from children to parent index files):
derive:
slug: 'slugify(titulo)'
name_lower: 'lower(nombre)'
aggregate:
total: 'len(descendants)'
completed: 'len(filter(descendants, .estado == "Completed"))'Derived and aggregated fields appear alongside frontmatter in query results, stats, and tree output.
Documents reference each other via [[wiki-links]] in their body. Rootline extracts these links and builds a directed graph:
rootline graph docs/ # Dependency graph as JSON (default)
rootline graph docs/ --format mermaid -o table # Mermaid diagram
rootline graph docs/ --format dot -o table # Graphviz DOT
rootline graph docs/ --check # Validate: cycles + broken links (text + exit code)Link schemas in .stem files control which link types are allowed and validate targets against regex patterns.
rootline fix goes beyond adding missing fields — it proposes intelligent repairs:
rootline fix doc.md --dry-run # Preview proposed changes
rootline fix --all # Fix all files in scopeProposals include: correct misspelled enum values (Levenshtein matching), extend .stem enums for new valid values, migrate values with wiki-link insertion, and infer fields from child documents.
rootline explain traces why a document has its current state — field origins, derivation expressions, aggregation sources, and validation errors:
rootline explain docs/projects/P01/F01/README.mdShows each field's origin (frontmatter, schema default, derived, or aggregated) with the source .stem file and expression.
Git is optional. Rootline works in any directory, with or without version control.
Rootline integrates with Git for continuous validation and collaborative workflows:
- Staged validation — The
.githooks/pre-commithook runsvalidate --stagedautomatically, catching schema violations before commit - CI validation — GitHub Actions workflows in
.github/workflows/run full validation and lint on every push - Merge conflict detection — Rootline's graph analyzer can detect when
.stemfile changes conflict with document mutations - Diff-aware reviews — Queries and validation support
--wherefilters, making it easy to review only changed documents
These workflows are optional enhancements, not product requirements. You can use Rootline without Git by running commands manually.
Rootline is designed as a structured knowledge source for AI assistants. Data commands output stable, versioned JSON contracts (each payload carries its own version field), making them suitable for tool use and automation.
AI assistants and automation should call the Rootline CLI directly and consume stable JSON output from commands such as query, validate, describe, tree, stats, explain, fix, graph, set, and new.
Rootline's engine decides everything resolvable from form — frequency
thresholds (a field present in ≥80% of records is required), unanimous or
majority value agreement, and structural conventions (directory naming, type
consistency). Decisions that need meaning — is this value semantically the
same as that one? — are not guessed: analyze marks those proposals
requires_agent for a human or agent to resolve. The report exposes
percentage evidence, not opinions; consumers apply their own thresholds.
| Topic | Description |
|---|---|
| Init | Schema inference from existing documents |
| Validate | Validation rules, batch mode, staged checks |
| Describe | Describe output, field extraction, source tracking |
| Query Engine | Query contract, operators, result shapes |
| New | Document scaffolding from effective schema |
| Set | Mutate frontmatter and sections with schema validation |
| Fix & Proposals | Auto-repair, enum correction, field inference |
| Analyze | Infer schemas and patterns from documents |
| Explain | Field origin tracing, derivation chain, error diagnosis |
| Tree | Hierarchical view with completion counts |
| Stats | Summary counts by type and state |
| Dependency Graph | Wiki-links, link schema, cycle detection, DOT/Mermaid |
| Derivation Engine | Derive and aggregate expressions, builtins, linked fields |
| Schema Migration | Breaking change detection, field rename, v2 upgrade |
| Levels & Match | Hierarchical field scoping with match patterns |
| Extensibility | Extractor architecture, future formats |
| Visual Identity | Logo, colors, usage guidelines |
Release builds auto-update in the background using a staged async pattern — the new binary is downloaded during run N and applied at the start of run N+1. Local builds (version == "dev") skip this entirely. See docs/auto-update.md for details.
- Product requirement: Go 1.26+
- Contributor workflow: Git (for pre-commit hooks, tests, CI)
go build ./cmd/rootline/ # Build
go test ./... -race # Tests with race detector
go vet ./... # Static analysis
golangci-lint run ./... # Full lintPre-commit hooks run golangci-lint and gofmt automatically. Commits follow Conventional Commits (type(scope): description), enforced by a commit-msg hook. To manually sync skills and rebuild after pulling: bash .githooks/pre-push.
Note: Git workflow is contributor-only; Rootline itself does not require Git.
Apache License 2.0 — free for commercial and non-commercial use.