ProtoML is a lightweight markup language for structured meeting documents. It is designed for meeting notes, tasks, reusable snippets, shared tags, and export to HTML, PDF, and JSON.
This repository contains:
- the parser
- the HTML and PDF renderers
- the CLI tools
- the Electron viewer
- bundled macros
ProtoML now has two documentation layers:
-
orienting CHM guide pages in
docs/chm/html_docs/ -
topic-by-topic built-in help in
docs/*.pmlforprotoparser --docs <topic> -
or use the GitHub Pages docs: ProtoML Documentation
Recommended reading order for new users:
- Documentation Index
- Quick Start
- ProtoML Concepts
- Authoring Guide
- Macros Guide
- CLI Reference
- Own Macro Registry Guide
- Macro Security And Trust Model
- Validation And Analysis Workflows
From source:
git clone https://github.com/ente/protoml-parser.git
cd protoml-parser
npm install -g .From npm:
npm install -g protoml-parserRequires Node 18.
Typical ProtoML releases are structured into three deliverables:
-
Source code The repository itself for development, npm publishing, local builds, and contribution.
-
Windows and Linux executables Standalone CLI builds for users who want to run ProtoML without a local Node.js setup.
-
Native Windows CHM help A compiled
docs/chm/protoml-help.chmhelp file for offline Windows-native documentation.
During release preparation, the distributable artifacts are collected in dist/.
That directory is intended to contain the Windows and Linux executables, a copied protoml-help.chm, and a SHA256SUMS.txt checksum file for the release set.
The checksum file also records the UTC generation timestamp.
It is recommended to wrap file and directory paths in double quotes whenever they are passed to ProtoML commands or used in ProtoML import and macro declarations.
This is especially important for:
- paths that contain spaces
- paths that use
{{macro_dir}} - shells that may interpret braces or special characters before ProtoML sees them
Recommended examples:
protoparser "test.pml" html
protoparser --listMacros "{{macro_dir}}"
protoparser --macroHelp "{{macro_dir}}/finance/f_entry.pml"@macro image "{{macro_dir}}/image.pml"
@import snippet "snippet.html" html
@tags_import "_tags.pml"
Example file:
@tags_import "_tags.pml"
@protocol "Project Protocol - {{date}}"
@date:24.05.2025
@participants
=pt1:John Doe,jdoe,jdoe@example.com
=pt2:Jane Doe,jane,jane@example.com
@subjects
=0:Project status
=1:Next steps
@tasks
-[ ] Prepare release notes @ptp=pt1 =1 @tag=important
-[x] Review parser output @ptp=pt2 =0 @tag=1
@notes
- HTML export works -b very well -b-
@meeting "Minutes"
# Weekly Sync
## Participants
@@e=pt1, @@e=pt2
## Topic
@@e=0
Render it:
protoparser "test.pml" htmlOpen it in the viewer:
protoviewer "test.pml"Try the complete feature suite:
protoparser "examples/feature-suite/main_demo.pml" html
protoparser tags "examples/feature-suite/_workflow_tags.pml" statisticsmain_demo.pml loads the imported .pml, the imported .html, shared tag files, and macros.
The tag statistics command can be run against either shared tag file in the feature suite because the tag files are cross-referenced via @tags_import.
For a guided step-by-step walkthrough, see docs/chm/html_docs/02_quick_start.html.
ProtoML is built around a few core ideas:
- block-based structure with commands such as
@participantsor@meeting - small inline reference syntax such as
@@e=pt1 - reusable external content via
@import - reusable external templates via
@macro - shared task classification via
@tagsand@tags_import
Meta fields use @key:value.
Examples:
@date:24.05.2025
@location:Berlin
Special meta and directive commands:
@author:...sets the document author@version:...sets the document version@status:...sets the document lifecycle status such asdraft,review, orapproved@record_id:...sets a stable record or document identifier@confidentiality:...sets a confidentiality level such aspublic,internal, orconfidential@effective_date:...sets the date from which the document is intended to apply@valid_until:...sets an optional end date for validity@review_date:...sets the next review date for the document@protocol "..."sets the HTML<title>and top page heading@meeting "..."starts the@meetingblock and sets the meeting section heading@title "..."is used by shared tag files for tag analysis output@meta=key:valuesets additional custom metadata entries
@protocol "..." supports placeholders such as {{date}}.
All @key:value meta fields are stored in the same metadata object. @meta=key:value is mainly intended for custom keys; built-in keys should prefer their direct form for clarity.
Example:
@author:Jane Doe
@version:1.0
@status:review
@record_id:PROTO-2026-001
@confidentiality:internal
@effective_date:24.05.2025
@valid_until:31.12.2025
@review_date:01.09.2025
@protocol "Protocol - {{date}}"
@meta=department:Platform
@meeting "Minutes"
Supported blocks:
@participants@subjects@tasks@notes@meeting@tags@tag_sources@signatures@approvals@references@attachments
Example:
@participants
=pt1:John Doe,jdoe,jdoe@example.com
@subjects
=0:Project status
@tags
=important:Critical, high priority
Declarations use =id:value. Their meaning depends on the current block.
- in
@participants:=id:name,alias,email - in
@subjects:=id:text - in
@tags:=id:label
Examples:
=pt1:John Doe,jdoe,jdoe@example.com
=0:Project status
=important:Critical, high priority
Tasks use -[ ] for open items and -[x] for completed items.
Supported task metadata:
@ptp=idassigns the task to a participant=subjectIdlinks the task to a subject@tag=idassigns a tag
Example:
@tasks
-[ ] Prepare release notes @ptp=pt1 =1 @tag=important
-[x] Review parser output @ptp=pt2 =0 @tag=1
The @meeting block is freeform content with lightweight formatting and inline commands.
Supported inside @meeting:
- headings:
#,##,### - inline references:
@@e=id - structured references:
@@ref=group:id[:field] - table of contents:
@@toc - signatures:
@@signature=id - approvals:
@@approval=id - macros:
@@macro=name:param=value - content imports:
@@import=nameand@@output=name - inline styling:
-b text -b--i text -i--a=url label -a-
Example:
@meeting "Weekly Notes"
@@toc
# Weekly Sync
## Participants
@@e=pt1, @@e=pt2
## Topic
@@e=0
Author: @@ref=meta:author
Reviewer mail: @@ref=participants:pt2:email
@@macro=badge:text=review
@@e=id resolves values from:
@subjects@participants@tags
Examples:
@@e=pt1
@@e=0
@@e=important
Structured references with @@ref=... can resolve specific fields:
@@ref=meta:author
@@ref=participants:pt1:email
@@ref=signatures:lead:role
@@ref=approvals:security:status
ProtoML supports shared participants, shared tags, macro registration imports, and content imports.
@participants_import "file.pml" loads participants from another ProtoML file.
Example:
@participants_import "_participants.pml"
Example shared participant file:
@participants
=lead:John Doe,jdoe,jdoe@example.com
=review:Jane Doe
Rules:
- imported participants are merged into the current document
- local participants override imported participants with the same ID
- imported participants can be reused in
@tasksvia@ptp=id - imported participants can be referenced with
@@ref=participants:id:field
@tags_import "file.pml" loads tags from another ProtoML file.
Example:
@tags_import "_tags.pml"
Example shared tag file:
@tags
=0:Important
=1:Normal
=2:Minor
Rules:
- imported tags are merged into the current document
- local tags override imported tags with the same ID
- imported tags can be used in
@tasksvia@tag=id
Shared tag files can also define @tag_sources for cross-file statistics.
Example:
@title "Shared Project Tags"
@tags
=important:Critical, high priority
=1:Normal
@tag_sources
- "meetings/week1.pml"
- "meetings/week2.pml"
Rules:
@tag_sourcesis intended for imported tag files such as_tags.pml@tag_sourcesis ignored during normal document rendering@title "..."is only relevant for tag analysis output- without
@title, the report title falls back to the tag file name
@import name "file" type registers a file for later output inside @meeting.
Examples:
@import legal "snippet.html" html
@import appendix "appendix.pml" pml
Use them inside @meeting:
@@import=legal
@@output=appendix
Supported content import types:
html: inserts the file contents directlypml: parses the file and inserts its resolved@meetingblock
For pml imports:
meta,participants,subjects,tags,macros, andimportsare merged into the main AST- the imported
@meetingcontent is inserted where@@import=...or@@output=...appears
Commands currently intended for reuse across files are:
@import ...for named content reuse inside@meeting@tags_import ...for shared task tags@participants_import ...for shared participant lists@macros_import ...for shared macro registrations@macro ...for registering external macro files
Notes:
@new_macrois not imported directly into another document@new_macrocan now also be written inline in a normal.pmlfile- instead, a
.pmlfile that starts with@new_macrois referenced through@macro ... - there is no separate
@participantcommand; participants are declared inside the@participantsblock
Macros can be defined in external ProtoML files or inline inside a normal .pml document via @new_macro.
Register a macro:
@macro myMacro "macros/myMacro.pml"
Use it inside @meeting:
@@macro=myMacro:title=Alert;text=Something happened
Example macro file:
@new_macro
=name:myMacro
=template:
<div class="warn-box"><strong>{{title}}</strong><br>{{text}}</div>
Builtin macros can be referenced with {{macro_dir}}.
Example:
@macro image "{{macro_dir}}/image.pml"
Notes:
- macros are primarily intended for HTML rendering
- macro templates may contain HTML and JavaScript
- plain HTML alone is not an automatic trust failure
- JavaScript and external URLs are treated as untrusted by the trust checker
- detached signatures are stored in
*.sig.jsonsidecar files
ProtoML supports reusable signature and approval entries.
Signature entries:
@signatures
=lead:Jane Doe,Project Lead,18.04.2026,Signed digitally
Approval entries:
@approvals
=security:Security Review,approved,Jane Doe,18.04.2026,Reviewed and accepted
Use them inside @meeting:
@@signature=lead
@@approval=security
They can also be referenced field-by-field with @@ref=signatures:... and @@ref=approvals:....
ProtoML also supports lightweight reference and attachment sections.
References:
@references
- ProtoML README|https://github.com/Ente/protoml-parser
Attachments:
@attachments
- Demo graph|main-demo-graph.mmd
These blocks are rendered as their own sections in HTML output.
Tags define reusable task categories. They can be declared locally with @tags or shared across documents with @tags_import.
Typical uses:
- priority labels such as
important,normal,minor - workflow labels such as
blocked,review,followup - domain labels such as
frontend,backend,ops
In normal document rendering:
- tasks can reference tags via
@tag=id - the HTML renderer computes per-tag statistics and renders a
Tagssection - tasks receive tag-based CSS classes such as
task-tag-important
Computed statistics include:
totalopendone
Example:
@tags
=important:Critical, high priority
@tasks
-[ ] Prepare release notes @tag=important
Shared tag files can also act as analysis entry points across multiple meeting files.
CLI command:
protoparser tags "_tags.pml" statisticsAvailable analysis formats:
statisticsjsonhtmlpdf
Examples:
protoparser tags "_tags.pml" statistics
protoparser tags "_tags.pml" json
protoparser tags "_tags.pml" html
protoparser tags "_tags.pml" pdfThe tag analysis command:
- reads the tag file
- evaluates its
@tag_sources - parses the referenced meeting files
- groups the result by tag file, source file, and matching tasks
- resolves tag IDs against the effective tag set of the analyzed tag file, including nested
@tags_importfiles - keeps local source tag overrides visible in task entries when a source document redefines an imported tag ID
Each matching task can include:
- task text
- tag ID and label
- open or done state
- assigned participant
- subject
If the tag file defines @title, that title is used in text, JSON, HTML, and PDF tag reports.
The repository includes a complete demo and test set in examples/feature-suite/.
Included files:
- 2 shared tag files
- 2
.pmlfiles - 1 imported
.htmlfile
The suite exercises:
@author@version@meta=key:value- local tags
- shared tags
- nested
@tags_import - local tag overrides
@@ref@@toc@@signature@@approval@import ... html@import ... pml- macros
- inline references
- tag statistics
Recommended test commands:
protoparser "examples/feature-suite/main_demo.pml" html
protoparser tags "examples/feature-suite/_workflow_tags.pml" statistics
protoparser analyze "examples/feature-suite/main_demo.pml" statisticsBecause the shared tag files reference each other through imports, the statistics command can also be run against the other tag file in the same folder.
Basic usage:
protoparser [options] <filename> <format>
protoparser [options] <filename> <format> <output_dir>
protoparser tags <tags_file> <format>Common examples:
protoparser "test.pml" html
protoparser "test.pml" html "./html"
protoparser "test.pml" json
protoparser "test.pml" markdown
protoparser "test.pml" text
protoparser -output=notes "test.pml" pdf
protoparser tags "_tags.pml" statistics
protoparser tags "_tags.pml" validate
protoparser tags "_tags.pml" html
protoparser analyze "test.pml" statistics
protoparser analyze "test.pml" graph
protoparser analyze "test.pml" html
protoparser register "examples/feature-suite" statistics
protoparser bundle "test.pml"
protoparser macro_install init
protoparser macro_install init_registry "./my-registry"
protoparser macro_install init_pack "legal-pack" "./my-registry"
protoparser macro_install add_registry "./my-registry"
protoparser macro_install install "legal-pack"
protoparser validate "test.pml"
protoparser macros "test.pml"
protoparser scaffold meeting "./demo"
protoparser init "./project"
protoparser chm
protoparser chm path
protoparser chm download
protoparser --listMacros "{{macro_dir}}"
protoparser --macroHelp "{{macro_dir}}/finance/f_entry.pml"
protoparser --listMacrosJson "{{macro_dir}}"
protoparser --listDocs
protoparser --docs meeting-output=<filename> sets the output base name explicitly.
The third positional argument can be used as an output directory:
protoparser "test.pml" html "./html"This writes html/test.html.
If a document uses @import ... html or @import ... pml and no explicit output path is given, the renderer automatically writes into a format subdirectory such as html/test.html to avoid cluttering the source directory.
General cross-reference analysis for .pml files is available via:
protoparser analyze "<pml_file>" statistics
protoparser analyze "<pml_file>" json
protoparser analyze "<pml_file>" html
protoparser analyze "<pml_file>" pdf
protoparser analyze "<pml_file>" graphThe analysis includes:
- local document stats
- resolved document stats after imports and tag merging
- content imports for
.pmland.html - nested
@tags_importreferences - registered macros
- recursive reference trees across imported
.pmlfiles
For graph output, the view can be adjusted via CLI:
protoparser analyze "test.pml" graph -graphView=compact
protoparser analyze "test.pml" graph -graphView=full -graphDirection=LR
protoparser analyze "test.pml" graph -output=test-graphSupported graph views:
compactfullimportstags
If -output=... is set for graph, the Mermaid-compatible graph output is written as a .mmd file instead of being printed to stdout.
The .mmd file is Mermaid source, so open it in Mermaid-capable software such as the Mermaid Live Editor if you want to inspect or edit it directly.
When -output=... is used, ProtoML also writes a companion .html preview next to the .mmd file for direct browser visualization.
Governance-style register reports across many .pml files are available via:
protoparser register "<dir>" statistics
protoparser register "<dir>" json
protoparser register "<dir>" html
protoparser register "<dir>" pdfThe register is intended for document directories such as meetings, contracts, onboarding collections, or compliance folders. It highlights:
- missing
record_id,author,version, orstatus - documents past
valid_until - documents due for review based on
review_date - documents with open tasks
- status distribution across the directory
Use it on document directories rather than entire repository roots when possible.
Bundled archive output for a single .pml file is available via:
protoparser bundle "<pml_file>"This writes a self-contained .pml file where imported ProtoML and HTML content has been expanded into a single document.
The default output name is based on the input file, for example:
protoparser bundle "test.pml"This writes test-bundle.pml.
Project-local external macro pack workflows are available via:
protoparser macro_install init
protoparser macro_install init_registry "./my-registry"
protoparser macro_install init_pack "legal-pack" "./my-registry"
protoparser macro_install add_registry "./my-registry"
protoparser macro_install install "legal-pack"
protoparser macro_install search "legal-pack"
protoparser macro_install list
protoparser macro_install info "legal-pack"
protoparser macro_install remove "legal-pack"This creates and uses:
protoml.macros.jsonas the project definition file.protoml/macro-packs/as the local install directory.protoml/macro-packs/macros.index.pmlas the generated macro import indexprotoml.registry.jsonas a local registry fileprotoml-pack.jsonas a pack manifest
Dependencies declared in protoml-pack.json are resolved during macro_install sync.
If a dependency does not specify a registry explicitly, the current registry is used.
If a requested package version is no longer available in the registry, macro_install sync falls back to the newest available registry version and updates the project package entry to match.
Use the generated index in a document with:
@macros_import ".protoml/macro-packs/macros.index.pml"
The generated index works as a single project-local macro entry point and contains @macro ... declarations for all installed pack macros.
Document validation is available via:
protoparser validate "<pml_file>"
protoparser tags "<tags_file>" validateThe validation commands check for:
- missing import files
- missing macro files
- unresolved references in strict mode
- duplicate IDs in common blocks
- missing tag source files
- untrusted used macros or imported
.pmlfiles
With -v, validation also reports what was detected in the file, such as meta keys, present blocks, counts, imports, tag imports, and macros.
Dedicated trust inspection is available via:
protoparser trust "test.pml"
protoparser verify "./governance/release-approval.pml"
protoparser validate "test.pml" -trust=strict -trustRegistry="./authors-registry" -trustRegistry="./macro-registry"
protoparser sign macro "./macros/warn_box.pml" "./keys/alice-private.pem" "Alice" alice-main
protoparser sign pml "./governance/release-approval.pml" "./keys/alice-private.pem" "Alice" alice-main
protoparser verify macro "./macros/warn_box.pml" -trustRegistry="./my-registry"The trust model is intentionally lightweight:
trusted: either a known bundled built-in macro whose hash matches the shipped built-in manifest and has no hard risk flag, or content with a valid signature by a registry author markedtrustedunknown: notuntrusted, but also not eligible fortrusted; typical cases are unsigned content or valid signatures without a matching trusted registry authoruntrusted: invalid signature, author markeduntrusted, JavaScript, external URLs, modified built-in macros, or imported/used untrusted content
-trustRegistry=... is a flag for trust, verify, and validate, not a standalone subcommand.
It accepts a local registry directory, a direct registry JSON path, or an HTTP/HTTPS registry URL.
It is repeatable, so multiple registry sources can be merged in one command.
If a nearest protoml.macros.json exists next to the target file or in one of its parent directories, those project registries are auto-discovered even without the flag.
In practice it adds author/key lookup sources; it does not override hard risk flags and does not make unsigned content trusted.
Macro usage inspection is available via:
protoparser macros "<pml_file>"This lists:
- macros registered by the document
- macros actually used in the meeting content
- macro usage inside recursively imported
.pmlfiles
The CLI also includes small bootstrap commands:
protoparser scaffold meeting "[target_dir]"
protoparser init "[target_dir]"scaffold meeting creates a starter meeting file and _tags.pml.
init creates a small project structure with:
meetings/_tags.pmlmeetings/main.pml
On Windows you can associate .pml files with ProtoML so they stop opening in Process Monitor:
protoparser associateThis writes a per-user file association in HKCU\Software\Classes and opens .pml files with the ProtoML viewer workbench.
| Flag | Description |
|---|---|
-v, -vv, -vvv |
Set verbosity level |
-output=<filename> |
Set output base name without extension |
-theme=<name> |
Set HTML or PDF theme |
-hideMeta |
Hide metadata sections in rendered HTML, Markdown, Text, and PDF output |
-strict |
Fail on unresolved references or missing imports |
--help |
Show CLI help |
--version |
Show version and build number |
--listMacros <dir> |
List macros in a directory |
--macroHelp <file> |
Show docs for a macro file |
--listMacrosJson <dir> |
Output macro metadata as JSON |
--listDocs |
List bundled documentation topics |
--docs <name> |
Show a documentation topic from docs/ |
ProtoML help is available independently of Windows CHM support via the generated HTML help viewer:
protoparser chmUseful variants:
protoparser chm browser
protoparser chm path
protoparser chm compiled
protoparser chm compiled_path
protoparser chm downloadBehavior:
protoparser chmopens the integrated Electron help viewer with TOC and generated HTML docsprotoparser chm browseropens the same help viewer in the system browserprotoparser chm pathprints the generated HTML help viewer pathprotoparser chm compiledopens the native.chmfile on Windows if availableprotoparser chm compiled_pathprints the resolved compiled CHM pathprotoparser chm downloaddownloads the compiled CHM asset without opening it
Verbosity levels for text-based CLI commands such as validate, tags ... statistics, analyze ... statistics, register ... statistics, and macros:
-vadds a compact structural overview-vvadds detailed lists such as macros, imported files, and nested sections-vvvadds the most verbose diagnostic detail available for that command
The CLI and macro loader support {{macro_dir}} for the built-in macro directory.
Examples:
protoparser --listMacros "{{macro_dir}}"
protoparser --macroHelp "{{macro_dir}}/finance/f_entry.pml"@macro image "{{macro_dir}}/image.pml"
Supported render formats:
jsonhtmlpdfmarkdowntext
Notes:
- if no format is passed, the CLI currently defaults to
json - if no explicit output name is passed, the input filename without extension is used
- the
jsonrenderer outputs the current AST - the
markdownandtextrenderers create readability-focused exports and strip embedded CSS and JavaScript from macro-heavy meeting content markdownis written as.mdtextis written as.txt- HTML and PDF themes can be selected with
-theme=<name>or via document meta such as@theme:dark - rendered metadata can be hidden with
-hideMetaor document meta such as@hide_meta:true
Common AST fields:
metaparticipantssubjectstagstasksnotesmeetingtag_stats
protoviewer opens a rendered ProtoML document in the bundled Electron viewer.
protoviewer test.pml
protoviewer test.pml darkThe browser-based viewer can be opened via:
protoparser viewer
protoparser viewer browser "./test.pml"
protoparser viewer app "./test.pml"
protowebviewer "./test.pml"Use protoparser viewer when you want the browser and app workbench for authoring, rendering, and lightweight checks, while CHM remains the bundled Help/Docs experience on Windows.
The independent browser viewer lives in web/.
Open:
web/index.html
Build the browser bundle:
npm run build:webStart a local development server:
npm run devThe browser viewer supports:
- editing ProtoML directly in the browser
- loading local
.pmlfiles - drag and drop
- in-browser preview
- exporting the rendered HTML
git clone https://github.com/ente/protoml-parser.git
cd protoml-parser
npm installUseful commands:
npm run build:web
npm run build:chm:project
npm run build:chm
npm run dev
npm run build:exeThe repository includes a native Windows HTML Help project in docs/chm/.
If you just want to use the help locally on Windows, run:
protoparser chmIf you want to compile the CHM on your own machine, you need Microsoft HTML Help Workshop installed first. An archived installer is still available here:
https://web.archive.org/web/20160201063255/http://download.microsoft.com/download/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe
Use:
npm run build:chm:projectto regenerate the CHM project files and topic HTML pages, and:
npm run build:chmto compile docs/chm/protoml-help.chm with Microsoft HTML Help Workshop on Windows.
To use the local version globally:
npm uninstall -g protoml-parser
npm install -g .ProtoML is not:
- a programming language
- a general-purpose template engine
- full Markdown
- a runtime with loops or arbitrary execution
ProtoML is:
- a readable format for structured meeting documents
- a lightweight task and note format with references
- a modular document format with imports and macros
- a good fit for HTML views, viewers, and structured export pipelines