lmhtml

Overview

lmhtml is a native host for auditing links and CSS names, comparing HTML documents, extracting templates, and applying shared-page edits.

Install and run

Use the latest binary from Releases. For source builds, follow the setup and build steps in the README. Install Node.js 24.15 or newer for the published compiler.

lmhtml --dsl-schema
lmhtml --dsl-schema --json > lmhtml.dsl.json
lmhtml --dsl-signatures
npx --yes --package=@lmctl-ai/lmctl -- lmscript audit.lms build/audit.dslb
lmhtml --dsl build/audit.dslb [more.dslb ...]

--dsl-schema prints a compact human-readable summary; --dsl-schema --json prints the embedded compiler input byte-for-byte. --dsl-signatures prints the bound host signatures. Multiple bytecode files run in order against the same embedded schema; all files are loaded and verified before execution. Use --dry-run to report saves without writing.

Reference

The following members are copied from the output of lmhtml --dsl-schema (lmhtml v0.2.0). Contexts are followed by functions and then each host type with its methods.

Contexts and functions

context html: Html
context report: Report
fn str_contains(string, string) -> bool
fn str_difference(StrList, StrList) -> StrList
fn str_ends_with(string, string) -> bool
fn str_find(string, string) -> int
fn str_len(string) -> int
fn str_list() -> StrList
fn str_lower(string) -> string
fn str_match(string, string) -> bool
fn str_replace(string, string, string) -> string
fn str_starts_with(string, string) -> bool
fn str_substr(string, int, int) -> string
fn str_trim(string) -> string
fn str_union(StrList, StrList) -> StrList
fn suggest(string, StrList) -> StrList

Doc

Doc.byte_size() -> int
Doc.classes_used() -> StrList
Doc.css_classes() -> StrList
Doc.css_ids() -> StrList
Doc.doctype() -> string
Doc.ids() -> StrList
Doc.links() -> StrList
Doc.markup_errors() -> StrList
Doc.path() -> string
Doc.select(string) -> NodeList
Doc.source() -> string
Doc.source_inner(string) -> string
Doc.source_outer(string) -> string

DocList

DocList.at(int) -> Doc
DocList.classes_used() -> StrList
DocList.css_classes() -> StrList
DocList.css_ids() -> StrList
DocList.ids() -> StrList
DocList.len() -> int

Html

Html.diff(Doc, Doc) -> int
Html.link_exists(Doc, string) -> bool
Html.link_kind(Doc, string) -> string
Html.load(string) -> Doc
Html.load_dir(string) -> DocList
Html.load_dir(string, string, string) -> DocList
Html.parse(string) -> Doc
Html.resolve(Doc, string) -> string
Html.save(Doc, string) -> void
Html.save(string, string) -> void
Html.write_template(DocList, int, string) -> int

Node

Node.attr(string) -> string
Node.attributes() -> StrList
Node.has_attr(string) -> bool
Node.hash() -> int
Node.insert_after(string) -> Node
Node.insert_before(string) -> Node
Node.outer_html() -> string
Node.parent() -> Node
Node.path() -> string
Node.remove() -> void
Node.replace_with(string) -> Node
Node.select(string) -> NodeList
Node.set_attr(string, string) -> Node
Node.tag() -> string
Node.text() -> string

NodeList

NodeList.at(int) -> Node
NodeList.len() -> int

Report

Report.add(string, string, int, string) -> void
Report.fail_if_any() -> void
Report.write_json(string) -> void
Report.write_text(string) -> void

StrList

StrList.at(int) -> string
StrList.len() -> int

Output and exit codes

Successful execution prints one JSON line: {"ok": true, "result": null}. Exit 0 is success, 2 is usage or compilation failure, 3 is bytecode load or host runtime failure, and 4 is an application-level report failure. Reports are informational unless the script calls report.fail_if_any().

Host behavior

Limits and troubleshooting

The CLI accepts bytecode v5 and schema v2. Only the current bytecode version is read. The VM has no execution budget or allocation caps, so run trusted bytecode. HTML saving expects valid UTF-8; unsupported legacy encodings are refused. Serialization may normalize wrappers, tag casing, quoting and optional elements. If compilation reports an unknown member, retrieve the schema JSON from the same host version and compile against it. If a save fails, check that the destination is under the working directory and inspect the host error.

Markdown notes and generated indexes

lmhtml reads .md with CommonMark plus GFM tables, task lists, strikethrough and autolinks. Raw HTML is disabled by default; md2html --allow-html enables it for trusted input. A leading --- metadata block recognizes single-line title and summary values; otherwise the first h1 and paragraph supply them. Doc.title() and Doc.summary() expose the metadata.

lmhtml index durable-memory
lmhtml index durable-memory --check
lmhtml mdcheck durable-memory

The generated index.md lists relative chapter links and one-line descriptions in filename order. An optional --order FILE lists relative paths, one per line, to place first. Generation is deterministic and --check reports drift without writing. Headings receive lowercase ASCII hyphenated IDs, with numeric suffixes for duplicates.

Template a Markdown web view

A trusted HTML shell supports five placeholders: {{title}}, {{summary}}, {{path}}, {{content}}, and {{toc}}. Metadata is escaped for HTML text or quoted attributes; content and toc are markup. Substitution happens once. Without a template, output is a minimal HTML5 document with no CSS or class names.

lmhtml site durable-memory build/memory-web --template shell.html

Local chapter links become .html links with anchors preserved; assets are copied. Source links are checked before writes. Output must not overlap input and must stay within the working directory. Use a fresh output directory when removing chapters; site does not delete unrelated files. To decorate further, load Markdown with html.load, html.from_markdown, or html.render_markdown, mutate the same Lexbor tree, and save it atomically.

Plain content for agents

Use lint to measure unnecessary decoration and entities, normalize to remove them without changing the text, and clean to extract main content for agents. Plain prose has no inline code or emphasis. Copyable commands belong in blocks. Text needs only ampersand and less-than escapes; attributes need only ampersand and quote escapes.

lmhtml lint --stats --json skills tools durable-memory
lmhtml lint --stats --compare BEFORE_DIRECTORY AFTER_DIRECTORY
lmhtml normalize skills tools
lmhtml lint durable-memory
lmhtml clean page.html --base https://example.org/docs/page.html
lmhtml clean page.html --check
lmhtml clean https://example.org/docs/page.html --markdown

clean is deterministic and offline for files. URL input uses curl and requires network access; it runs no JavaScript. Extraction removes navigation, forms, scripts, styles and common advertising/cookie containers, resolves links and prints byte counts and a bytes/4 token estimate on stderr. Heuristics can miss unusual site layouts: inspect extracted content before relying on it. clean --check compares extraction with the page's main content and fails with a diff if content would be dropped.

normalize preserves code-block alignment, removes inline typography, repairs entities and unfolds prose. lint counts violations per file and in total, with densities per 100 words; --config FILE accepts DIRECTORY METRIC MAX_COUNT rows. Defaults are zero, with h2/h3 anchors retained. The DSL equivalents are Doc.normalize() and Doc.clean(base_url).