Releases: docmd-io/docmd
Release list
docmd@0.8.9 🔒 (Plugin Hardening + Semantic 0.1.0)
docmd 0.8.9 🔒 Plugin + Semantic 0.1.0
Build production-ready documentation from Markdown in seconds.
✨ Highlights
This release is a hardening pass on the plugin and template ecosystem. The biggest change is structural: every official @docmd/* package now carries a docmd namespace in its package.json, and a build-time registry generator reads those namespaces to produce the single source of truth that the runtime loader consumes. The plugin auto-installer is now resilient to packages that ship import-only exports fields, and a new docmd doctor pre-flight command catches configuration drift before a build. Two previously-silent bugs in published tarballs are also fixed: the 404 page now renders with the summer template and translated strings instead of falling back to the default template with raw translation keys.
No public API changes. No breaking config changes. Purely a hardening release.
🔌 Build-time plugin registry (single source of truth)
A new workspace-level script — scripts/build-plugin-registry.mjs — walks packages/{plugins,templates,engines}/*, reads each package's package.json#docmd namespace, and emits a generated JSON catalog (packages/api/registry/plugins.generated.json). Wired as the prebuild step of @docmd/api, so the registry is regenerated on every build.
The runtime loader (packages/api/src/hooks.ts getPluginRegistry) now reads from the generated file, with two resolution paths (published layout <pkg>/registry/... and monorepo dev layout <repo>/packages/api/registry/...). The hand-maintained packages/plugins/installer/registry/plugins.json that lived in the installer is no longer consulted at runtime.
📦 docmd namespace standardisation
Every official @docmd/* package now carries a docmd namespace in its package.json. The namespace is the contract that the registry generator reads and the loader cross-checks against the JS descriptor at load time. Fields: key (user-facing identifier), kind (plugin / template / engine), displayName, tagline, capabilities (required for plugins and templates, used by the build-time cross-check), and preview (template only).
Engines get the same shape but no capabilities — they don't participate in the hook system. The auto-installer checks kind === 'engine' and refuses to install them.
🩺 docmd doctor — pre-flight check
A new CLI subcommand for diagnostics. No filesystem writes, no build side-effects — purely diagnostic.
npx @docmd/core doctor [options]| Option | Description |
|---|---|
--config <path> |
Path to a non-default docmd.config.json (or .ts/.js/.mjs). |
--fix |
Auto-install missing official plugins or templates. |
--json |
Emit the report as machine-readable JSON. |
By default, doctor prints a human-readable summary covering the installed @docmd/core version, every configured plugin (with version and ✓ installed / ⚠ missing status), the active template, the requested engines (js always-on, rust opt-in), and a list of auto-install candidates. With --fix, it shells out to the project's package manager to install the candidates. With --json, the same data is emitted as a single JSON object — useful for pre-commit hooks and CI gates.
Also available as pnpm doctor (which routes through the workspace docmd script in the monorepo).
🛠 New pnpm scripts in the monorepo
The monorepo's package.json gets a batch of new pnpm scripts, all pointing at the playground via the existing --cwd flag (same pattern as pnpm dev and pnpm live):
pnpm doctor # → docmd doctor
pnpm validate # → docmd validate
pnpm migrate # → docmd migrate
pnpm gen:deploy # → docmd deploy
pnpm mcp # → docmd mcp
pnpm plugin:add foo # → docmd add foo
pnpm plugin:remove foo # → docmd remove foo
pnpm build:playground # → docmd build (separate from `pnpm build` which is the monorepo-wide build)🐛 Bug fixes
- Plugin auto-install: resilient to
import-onlyexports. The auto-installer in@docmd/apipreviously usedrequire.resolveto resolve installed packages, which throwsERR_PACKAGE_PATH_NOT_EXPORTEDfor packages that ship only animportcondition inexports. The retry path now usesawait import(name)directly, which honours theexportsfield natively. A defense-in-depth registry re-check is performed inside the retry path — the set of names that can be auto-installed is unchanged, only the set ofexportsconditions they can carry is larger. - Plugin loader: capability cache and manifest drift check. A per-key capability set cache avoids re-walking the registry on every dev-server rebuild. A new manifest drift check warns if the JS descriptor's
capabilitiesarray doesn't match the manifest'scapabilitiesarray — closing the silent-hook-drop bug where a plugin that implemented a hook but forgot the corresponding capability in its descriptor would have its hook silently skipped. - Better "Could not load X after auto-install" errors. The post-install retry's catch block now surfaces
err.code(e.g.ERR_PACKAGE_PATH_NOT_EXPORTED,ERR_MODULE_NOT_FOUND) and the first line oferr.message. TheautoInstallPlugincatch block also surfaces the underlying stderr from the package manager and prints a hint for the most common cases. @docmd/ui: includetranslations/in the published tarball. The server-side translation loader reads translation JSON files at__dirname/../translations/. Thepackage.json#fileswas missing"translations", so npm packed the tarball without the translation files. The 404 page was the most visible symptom: rendered lazily by the deployed site's static-file fallback, the translation cache was empty, and the keys leaked. Now all 7 locale files ship.@docmd/template-summer: includetemplates/andassets/in the published tarball. The summer template's runtime usesnew URL('../templates/...', import.meta.url)insidedist/index.js, which resolves to<package-root>/templates/...(not<package-root>/dist/templates/...). Thepackage.json#fileswas just["dist"], so the published tarball only containeddist/, and the resolver fell back to the default template. Now the published tarball matches the monorepo dev layout and the summer template renders correctly.- Dev server: strip leading slash before
safePath(). The CWE-22 fix from 0.8.9 (replacingfilePath.startsWith(rootAbs)withsafePath(rootAbs, ...)) had a regression in the dev server: URL pathnames always start with/, andpath.resolve('/abs/root', '/index.html')returns/index.html— which always failed thesafePathboundary check and produced403 Forbiddenfor every legitimate request. Fix: strip the leading/from the URL pathname before passing tosafePath(). - Live editor, port probe, and Docker docs default to loopback. The live editor's
server.listenand thecheckPortInUseprobe now bind to127.0.0.1instead of0.0.0.0. LAN access is opt-in viaDOCMD_HOST=0.0.0.0or--host 0.0.0.0, with a TUI warning when active. Thedocker/DOCKER.mdexamples now use the loopback default. - Utils:
scriptLiteralandjsonInjectharden inline script escaping. Both now properly escape</script,<!--, U+2028, and U+2029 in addition to the existing JSON-safe encoding. The hardening is silent for non-conflicting strings; round-trips throughJSON.parsestill work because the escape uses JSON-safe sequences.
Changelog
- Registry: New
scripts/build-plugin-registry.mjs— generatespackages/api/registry/plugins.generated.jsonfrom each official package'sdocmdnamespace. - Loader:
getPluginRegistryreads the generated file with two resolution paths; the hand-maintainedinstaller/registry/plugins.jsonis no longer consulted at runtime. - Namespace:
docmdnamespace added to all 14 official@docmd/*packages (12 plugins, 2 engines) and updated on@docmd/template-summerwithkey: "summer". - Loader: Per-key capability set cache + manifest drift check (
checkManifestCapabilityDrift). - Auto-install: Retry path uses
await import(name)instead ofrequire.resolve + import(file://path), with a defense-in-depth registry re-check. - Auto-install errors:
err.code+ first line oferr.messagesurfaced; package-manager stderr + hint printed. - CLI:
docmd doctorsubcommand added with--config,--fix,--jsonflags. Registered in the CLI dispatcher; help text updated. - CLI: New pnpm scripts in the monorepo —
doctor,validate,migrate,gen:deploy,mcp,plugin:add,plugin:remove,build:playground. - UI:
packages/ui/package.json#filesnow includestranslations/. - Template:
packages/templates/summer/package.json#filesnow includestemplates/andassets/. - Dev server:
safePath()inserveStaticstrips the leading/from URL pathnames. - Live editor:
server.listenandcheckPortInUsebind to127.0.0.1;DOCMD_HOST=0.0.0.0opt-in. - Docker docs: Three
command: dev --host 0.0.0.0examples replaced with the loopback default; "Network Issues" troubleshooting documents the opt-in path. - Utils:
scriptLiteralandjsonInjectescape</script,<!--, U+2028, U+2029. - Tests:
packages/utils/test/html-escape.test.jsupdated to assert the new escape behaviour. - Docs: New "ESM Exports — the
defaultCondition" section inbuilding-plugins.mdandbuilding-templates.md; new "Bundled registry removal in 0.9.0" callout; newdocmd doctorentry in `reference/cl...
docmd@0.8.8 🛡️ (Security Hardening + OKF)
docmd 0.8.8 🛡️ Security + OKF Integration
Build production-ready documentation from Markdown in seconds.
A focused hardening release with OKF (Open Knowledge Format) Integration.
Every change here is either a regression caught by users, a CI workflow bug, or a build-time reliability issue.
🐛 Bug fixes
Docker: volume mount permissions fixed
docmd init and other file-writing commands failed with "Permission denied" when /docs was a host-mounted volume owned by a uid other than the container's built-in docmd user (uid 1001).
The image now ships with su-exec and the entrypoint detects the host uid:gid of the mounted directory and re-execs as that identity before running any command — same pattern used by the official postgres and redis images.
# All of these now work without -u flags on a host volume
docker run -v $(pwd):/docs ghcr.io/docmd-io/docmd:latest init
docker run -v $(pwd):/docs -p 3000:3000 ghcr.io/docmd-io/docmd:latestThe cp -a (archive) mode that triggered "Operation not permitted" warnings on ownership preservation is gone.
The -u $(id -u):$(id -g) workaround is no longer required and has been removed from all READMEs and the Docker deployment guide.
Docker: init now non-blocking in CI
The interactive "Do you want to override these files?" prompt hung in non-TTY environments (CI, docker run without -it, piped input).
The CLI now detects non-interactive mode and skips the prompt automatically — keeping existing files by default (safe), or accepting -y/--yes to opt into overwrite.
A new --force flag also works in any environment for explicit override.
# Force overwrite in CI / Docker / piped input
docker run --rm -v $(pwd):/docs ghcr.io/docmd:latest init --force
# Or use -y
docker run --rm -v $(pwd):/docs ghcr.io/docmd:latest init -ydocmd add on npx: false "npm not found" on Windows
npx @docmd/core add <plugin> on Windows PowerShell printed "The package manager 'npm' was not found on your system PATH" even though npm --version worked fine in the same shell.
Root cause: when @docmd/core is launched through npx, the spawned child process inherits a stripped PATH on Windows.
The installer now resolves npm/pnpm/yarn/bun relative to process.execPath (Node's own location), which always works regardless of how @docmd/core was launched.
The error message also now detects the specific case (Node reachable + binary missing) and suggests installing the plugin via the host package manager directly.
Template registry lookup for @docmd/template-*
Setting theme.template to an official template like summer or @docmd/template-summer printed:
⬢ Plugin "template-summer" not found in official registry - manual installation required
Root cause: the auto-install registry lookup stripped @docmd/plugin- from the package name to derive the registry key, but didn't strip @docmd/template-.
So @docmd/template-summer resolved to key template-summer instead of summer, which doesn't exist in the registry.
Now both prefixes are stripped correctly.
Custom/third-party templates were never affected.
Semantic search peer dependency handling
When plugins.search.semantic = true was set and the ML peer dependencies (@huggingface/transformers, onnxruntime-node) weren't present, the build silently fell back to keyword search with a confusing error buried deep inside docmd-search:
⬢ Semantic indexing failed: Embedding failed: Failed to load model "Xenova/all-MiniLM-L6-v2": Cannot find package '@huggingface/transformers'
Two improvements:
- Clear pre-flight check — the plugin now verifies the peer dependencies are resolvable after auto-install and emits an actionable error naming the missing package, instead of letting the failure surface from inside
docmd-search. - Stale module cache fix — after auto-installing
docmd-searchmid-build, the current Node process's module cache couldn't see the new packages.
Indexing now runs in a child process so it starts with a clean module resolution.
npm installauto-install also passes--foreground-scriptssoonnxruntime-node's postinstall (native binary download) actually runs in CI environments with npm'sallow-scriptssecurity feature enabled.
npm-publish: packages/templates/* now in the publish loop
The npm-publish.yml workflow was iterating packages/*, packages/legacy/*, packages/plugins/*, packages/engines/* but missing packages/templates/*.
Templates like @docmd/template-summer and @docmd/template-rain were not being released.
Now included.
docmd init no longer makes a network call by default
Previously docmd init always fetched SKILL.md from raw.githubusercontent.com/docmd-io/docmd-skills on every run.
The fetched content overrode the bundled default if it succeeded.
Two changes:
- Default is now local-only — the bundled
SKILL.mdcontent ships with the package and is written without any network call. - Opt in via
--with-skillflag orDOCMD_FETCH_REMOTE_SKILL=1env var to fetch the latest SKILL.md from the docmd-skills repo (CI environments and offline workstations can keep using the bundled default).
docmd init --with-skill # fetch latest SKILL.md from docmd-skills
DOCMD_FETCH_REMOTE_SKILL=1 docmd init # same, via env vardocker-publish: stopped firing on every push to main
The docker-publish.yml workflow had a push: branches: [main] trigger that caused it to run on every commit to main, not just on release events. Removed — it now only fires on v* tag pushes, published releases, and manual dispatch.
Dockerfile: pnpm install made reliable in CI
The production stage was using corepack prepare pnpm@10.33.2 --activate (with explicit version), but the builder stage's corepack prepare --activate (no version) failed in GitHub Actions CI because it required a package.json in the current working directory.
Both stages now use npm install -g pnpm@10.33.2 directly — simpler, no corepack resolution steps, and works identically in CI and local.
On a clean build, pnpm also refused to remove the existing node_modules directory without interactive confirmation in the non-TTY Docker environment.
The install command now passes --config.confirmModulesPurge=false, which is pnpm's targeted flag for this case.
The broader ENV CI=true route was considered and rejected because it leaks into every subsequent RUN.
UI translation keys render as literal text in published package
builtWith, copyContext, copiedToClipboard and other template-translated strings rendered as literal key text in built output when using the published @docmd/ui package.
The monorepo worked fine because packages/ui/translations/ existed alongside dist/, but the published package's files array didn't include the translations/ directory, so pnpm pack stripped it from the tarball.
Added translations to the files array; loadTranslations now also emits a clear warning when the directory is missing so future regressions don't surface as silent literal-key output.
@docmd/template-* registry key mismatch
Setting theme.template to summer or @docmd/template-summer printed "Plugin 'template-summer' not found in official registry — manual installation required" even though the package was installed.
Root cause: the auto-install registry lookup stripped @docmd/plugin- from the package name to derive the registry key, but didn't strip @docmd/template-.
So @docmd/template-summer resolved to the key template-summer instead of summer.
Both prefixes are now stripped correctly.
Custom/third-party templates were never affected — they bypass the registry lookup entirely.
--offline mode: navigation links don't navigate (#164)
Clicking a navigation sidebar child link in an --offline build only toggled the parent's collapse state instead of opening the target page.
Root cause: the data-spa-enabled flag stayed true for offline builds, so the SPA click handler bound and consumed clicks with preventDefault().
But file:// has no fetch for the SPA path-fetch, so the navigation never happened.
Fixed in two places:
data-spa-enabledis nowfalsewhenisOfflineModeis true, so the SPA handler never binds and the browser does normal full-page navigation.- A safety-net check in the main SPA click handler bails out for
file://protocol, so the click isn't consumed even if the flag is wrong.
docmd build --offline # SPA now disabled automatically
# Workaround on 0.8.7: open via local server, or set layout.spa: false--offline mode: comprehensive file:// robustness pass
While fixing #164, audited every other place the client-side JS touches localStorage, fetch, XMLHttpRequest, or relies on SPA/network.
All localStorage writes (sidebar collapse, theme toggle, locale preference, cookie consent) are now wrapped in try/catch so file:// builds don't throw in Chromium-based browsers where local storage is blocked.
The version switcher's HEAD fetch check is skipped under file:// (browsers block it anyway), going straight to direct navigation.
XHR in the noStyle i18n loader is wrapped with onerror handling.
URL builder already appended /index.html for offline mode (unchanged).
Result: opening a built site via file:// now works end-to-end with no JS errors, no broken navigation, and no silent feature loss.
📚 Documentation updates
The following docs were updated to reflect the fixes above:
- **[Deployment → Docker]...
docmd@0.8.7 🎭 (Custom Templates API)
docmd 0.8.7 • Custom Templates API
Build production-ready documentation from Markdown in seconds.
Templates are now plugins. The first official template, Summer, ships alongside two new opt-in UI features — cookie consent and an announcement banner — built directly into @docmd/ui. Also includes a Docker :latest fix so quick-start works out of the box, and a handful of post-release hardening fixes below.
✨ What's new
Templates are now plugins
A template package declares capabilities: ['template'] and ships layout overrides plus its own CSS/JS. The new resolver checks four levels, falling back to the default at any step:
frontmatter.template → config.templates[glob] → config.theme.template → built-in default
// template-summer/index.js
export default {
plugin: { name: 'template-summer', version: '0.1.0', capabilities: ['template'] },
templates: [
{ type: 'layout', templatePath: '...' },
{ type: 'sidebar', templatePath: '...' },
],
templateAssets: [
{ type: 'css', path: '.../summer.css', priority: 10, position: 'head' },
],
};Templates can override any of 14 supported slots (layout, 404, sidebar, header, footer, banner, cookie-consent, and more) and can be set per-page via frontmatter, or site-wide via config. User customCss always wins — templates can't use !important.
Templates — architecture & authoring guide
☀️ Summer — the first official template (Preview)
A bright, airy layout with a top search bar, soft halo accents, and a denser card grid.
docmd add summer # installs and switches your config
docmd remove summer # reverts to default🍪 Cookie consent dialog
Built into the default UI. Off unless you opt in.
{
"cookie": {
"enabled": true,
"message": "We use cookies to ensure you get the best experience.",
"policyUrl": "/privacy",
"position": "bottom-right",
"expiryDays": 180
}
}Fires a docmd:cookie-consent event on choice, so plugins and templates can react.
📢 Site-wide announcement banner
Sits above the menubar. Supports inline markdown or raw HTML.
{
"layout": {
"banner": {
"content": "**v0.9 ships Friday** — read the announcement.",
"type": "info",
"link": { "text": "Read more", "url": "/blog/v0-9" }
}
}
}Dismiss state is stored per-session, so the banner reappears on a fresh visit.
Fixed
| Issue | Fix |
|---|---|
Docker :latest tag never published |
Workflow now tags :latest automatically on release events #153 |
Quick-start crashed on empty /docs in Docker |
Entrypoint seeds /docs from the bundled template when empty #154 |
xdg-open crash on dev server |
A missing browser-launch binary no longer crashes docmd dev #156 |
| Sidebar nav double-click bug | The main UI script could load twice under certain serving conditions, causing click handlers to fire twice and nav state to get stuck, now guarded against double-execution |
| Docker healthcheck always "unhealthy" | Now probes ports 3000–3005 to match the dev server's auto-increment |
| i18n strings not translating in sidebar/nav partials | t() function now passed to all layout partials; 13 missing keys added across all 7 locales |
| Copy-code button floated above the code block | Button now anchors to the outer wrapper instead of an inner one |
| Mermaid diagrams broke on SPA navigation (not on full reload) | Plugin <script> tags are now synced into the live DOM on every page swap, not just initial load |
| Non-English search results jumped to the page top instead of the heading | Semantic-search client now uses a Unicode-aware slug regex, matching the parser-side generator (fixes Chinese, Japanese, Korean, Cyrillic, diacritics) #148 |
appearance: "system" issue |
Default-theme partial now reads DOCMD_APPEARANCE (the canonical name) and only honours localStorage when it holds a concrete light/dark value #160 |
| Dev server kept rebuilding every few seconds with no edits | New content-signature tracker ignores phantom fs.watch events from Spotlight/iCloud/Time Machine; config watcher now watches the parent directory instead of the file directly |
tag container didn't accept quoted URLs or the external: prefix |
Parser regex now supports "..." and '...' around option values; url: is the canonical property name, link: kept as an alias |
Improved
- Conditional plugin asset loading — plugins can now declare a
conditionon their assets so JS/CSS only ship to pages that actually need them. Verified on the playground: Mermaid's ~500 KB library now loads on 3/11 pages (was 11/11) and KaTeX's ~30 KB CSS on 1/1 math page (was 11/11). - Sensible config defaults — a fresh
docmd.config.json(or no config at all) now ships a fully-featured site: page navigation, copy-code buttons, breadcrumbs, search, theme switch, and more are all on by default. Full defaults table → - Tighter UI — header and menubar height reduced 52px → 44px; smaller heading-anchor icons; denser card grids.
- New default 404 page — glass-card layout with soft halo background, Return Home / Go Back actions, fully translated and RTL-aware.
- Step permalinks — every
<li>in a docmd steps list now carries a globally-uniqueid="step-N"and a hidden link-2 icon that fades in on hover or focus, so individual steps are easy to share and deep-link. - Contrast pass — text and link colors adjusted across light and dark themes to meet WCAG AA.
- Redesigned active sidebar link — a "node on thread" pill replaces the old left-border style.
- Keyboard focus is now visible —
:focus-visiblegets a halo glow site-wide. - Changelog entry permalinks — mirrors the step-permalink pattern: every changelog entry date now carries an
idand a hidden link-2 icon that fades in on hover, so individual releases are easy to share and deep-link. --verboseis now universal — previously only respected byadd/remove. Now setsDOCMD_VERBOSE=truein the environment so every subcommand (build, dev, live, init, validate) can opt-in to detailed logs, and is also forwarded tobuildSiteandbuildLivefor the structured path.- Docker image works with zero setup —
docker run ghcr.io/docmd-io/docmd:latestnow seeds a demo site automatically; no volume mount required. @docmd/plugin-searchmissing runtime dependency —markdown-itwas incorrectly listed as dev-only; installing the plugin now works on first try.- Docker tags simplified — releases now publish exactly two tags: the version number and
:latest.
Looking ahead — Node 20+ in v0.9.0
The next minor release raises the floor to Node.js 20+ (from 18+), bringing the engine requirement, shipped Docker runtime, and CI environment all onto Node 22. Node 18 reached end-of-life in April 2025; this keeps docmd on a supported runtime with room to spare.
This release (0.8.7) is unaffected — the >=18 floor stays until 0.9.0 ships.
| Now (0.8.x) | Next (0.9.0) | |
|---|---|---|
| Minimum Node | 18+ | 20+ |
| Docker base | 20-alpine |
20-alpine |
| Type Node | ^24 | ^24 |
| CI target | 24 | 24 |
Skills Update (docmd-skills@1.1.0)
Skills have been updated for 0.8.7 with three specialised skills that work together. The agent automatically selects the most relevant skill based on the current task and context, reducing unnecessary token usage while maintaining accuracy.
npx docmd-skills [dir]Replace [dir] with the directory location where you keep agent skills — common choices are ~/.claude/skills/, ~/.cursor/skills/, or a project-level folder like ./.skills/.
Thanks 💖
Thanks to all contributors and community members who reported issues and provided feedback.
Documentation: https://docs.docmd.io/
GitHub: https://github.com/docmd-io/docmd
Skills: https://github.com/docmd-io/docmd-skills
Full Changelog: 0.8.6...0.8.7
docmd@0.8.6 🧠 (AI-First Integration & Native MCP Server)
docmd 0.8.6 • Native MCP + Agentic Skills
Build production-ready documentation from Markdown in seconds.
✨ Highlights
This release officially establishes docmd as the premier "AI-First" documentation engine. The centrepiece is a native Model Context Protocol (MCP) server enabling AI agents to interact with documentation workspaces via docmd mcp.
Alongside this, the release delivers a modular agent instruction set (docmd-skills), an official Docker image with multi-architecture support, client-side "Copy Markdown" and "Copy Context" widgets for LLMs, a search tokeniser overhaul supporting CJK and spaceless languages, critical enhancements to the Table of Contents layout, and a visual overhaul of the UI featuring radial top glows, a continuous changelog timeline, and upgraded steps components.
🔌 Native Model Context Protocol (MCP) Server
You can now start a native MCP server directly from your workspace:
docmd mcpThe server runs in local stdio mode (protocol version 2025-03-26), allowing AI developer agents (like Claude Desktop, Cursor, or Windsurf) to securely interface with your documentation workspace to:
- Perform full-text and semantic documentation searches (
search_docs) - Read markdown files and configurations (
read_doc) - Run hyperlink and relative path validations (
validate_docs) - Retrieve the unified repository context (
get_llms_context)
Full protocol compliance including ping health checks and notifications/initialized lifecycle.
📖 Modular Agent Instruction Set (docmd-skills)
When running docmd init, a version-controlled SKILL.md is generated in the project root. The full instruction set is maintained as a modular collection in the docmd-skills repository:
cli.md: Setup, all CLI commands with flags and per-command options.config.md: Completedocmd.config.jsonschema with defaults and inline comments.plugins.md: Every built-in plugin with all config keys, defaults, and behaviour.plugin-development.md: Hook signatures, lifecycle, ActionContext, custom plugin creation guide.formatting.md: Container syntax, frontmatter reference, self-closing rules.api.md: Node.js build API, browser API, MCP server, URL utilities, client-side events.validation.md: Link checking and CI/CD integration.
All skill files include inline comments explaining defaults, reference links to full documentation, and llms-full.txt discoverability guidance.
🐳 Official Docker Image
docmd is now available as an official Docker image with multi-architecture support (linux/amd64 and linux/arm64):
# Pull and run with demo site
docker pull ghcr.io/docmd-io/docmd:latest
docker run -p 3000:3000 ghcr.io/docmd-io/docmd:latest
# Build your docs
docker run -v $(pwd)/docs:/docs -v $(pwd)/site:/site ghcr.io/docmd-io/docmd:latest buildFeatures include Docker Compose and Kubernetes deployment examples, non-root security, Alpine Linux base, health checks, and GitHub Actions CI/CD integration.
🧠 AI-First Context Extraction Widgets
To enable seamless documentation ingestion by AI assistants, we have introduced two new localised buttons next to page breadcrumbs:
- Copy Markdown: Copies the clean body content of the document, automatically stripping YAML frontmatter metadata so LLMs ingest pure content.
- Copy Context: Copies structured context containing the page URL, title, tags, version, and text, optimised for direct copy-pasting into AI chat windows.
- Localisation: Supports translations and copied confirmations for all 7 primary languages (
en,de,es,fr,hi,ja,zh).
🔍 Spaceless Script Search Tokenization (CJK, Thai, Lao, etc.)
We have resolved a search indexing limitation in MiniSearch for languages that do not use spaces between words. Previously, continuous character blocks (such as Chinese, Japanese, Korean, Thai, Lao, Khmer, Burmese, or Tibetan text) were indexed as single giant tokens, causing partial/sub-word matches to fail.
A unified CJK_AND_SPACELESS_REGEX tokenizer has been added. It splits spaceless character scripts into individual character tokens while preserving default space-based tokenization for English and other languages. This tokenizer runs symmetrically on:
- The build-time offline index generator.
- The multi-threaded background build worker.
- The client-side browser query parser.
🔢 docmd-search 0.1.0-alpha.1
This release includes docmd-search 0.1.0-alpha.1, which fixes a critical bug where confidence percentages in search results could exceed 100% in certain edge cases. The scoring algorithm has been corrected to properly normalise relevance scores within the expected 0-100% range.
📚 Table of Contents Enhancements
The table of contents (TOC) component has received significant improvements in this release, addressing long-standing issues with scrolling behaviour and heading coverage.
H1 Heading Support
H1 headings (# Heading) are now properly included in the table of contents. Previously, only H2-H4 headings were displayed in the TOC, which meant important top-level headings were missing from the navigation sidebar.
Improved Scrolling Behaviour
The TOC sidebar now scrolls independently when it contains many items, preventing it from overlapping or interfering with the page footer. The active heading is automatically centred in the TOC view as you scroll through the content, making it easier to track your position in long documents.
Smooth scrolling has been optimised with debouncing to prevent jittery or jarring movements, providing a more polished reading experience.
Changelog
- MCP: Implemented native
docmd mcpserver capabilities running on local stdio. - MCP: Updated protocol to
2025-03-26— addedpinghandler, fixednotifications/initializedlifecycle. - MCP: Fixed
readlineoutput pollution that corrupted the JSON-RPC stream. - MCP: Added dedicated MCP Server documentation page.
- Skills: Modularized agent manuals into 7 skill files under
docmd-skills/with inline defaults and doc references. - Skills: Added
api.md(Node.js, browser, MCP, URL utilities) andplugin-development.md(hooks, lifecycle) modules. - Skills: Added
llms-full.txtdiscoverability guidance and agent usage instructions. - Docker: Added official Docker image with multi-architecture support (amd64/arm64).
- Docker: Added Docker Compose, Kubernetes, and GitHub Actions deployment examples.
- Docker: Non-root security, Alpine base, health checks, SBOM attestation.
- AI: Added "Copy Markdown" and "Copy Context" UI widgets with translations for 7 languages.
- Search: Added a unified tokeniser for CJK, Thai, Lao, Khmer, Burmese, and Tibetan scripts in MiniSearch. #145
- Search: Fixed confidence percentage calculation in docmd-search 0.1.0-alpha.1 to prevent scores exceeding 100%.
- TOC: Added support for H1 headings in the table of contents with proper anchor links and styling.
- TOC: Implemented independent scrolling for the TOC sidebar with
max-heightconstraints to prevent footer overlap. - TOC: Added automatic centring of active TOC items during page scroll with debounced smooth scrolling.
- TOC: Extended scroll spy to observe H1 headings alongside H2-H4.
- Parser: Updated heading anchor injection to include H1 headings for permalink icons.
- UI: Fixed footer rendering issues caused by TOC overflow on pages with many headings.
- UI: Upgraded steps component with precise alignments, hover states, and glowing brand nodes.
- UI: Refactored changelog timeline to utilize a continuous grid axis with interactive expandable markers.
- UI: Added a modern adaptive radial halo glow at the top of the content page (light and dark modes).
- UI: Redesigned copy widgets as a unified, sleek segmented control button group.
- UI: Fixed a critical SPA routing bug where head assets (stylesheets and icons) were duplicated during client-side navigation due to relative path resolution shifts.
Thanks 💖
Thanks to all contributors and community members who reported issues and provided feedback on TOC behaviour and AI integrations.
Documentation: https://docs.docmd.io/
GitHub: https://github.com/docmd-io/docmd
Full Changelog: 0.8.5...0.8.6
docmd@0.8.5 ⚡️ (Offline Semantic Search Preview)
docmd 0.8.4 • Semantic Search 0.1.0-alpha.0
Build production-ready documentation from Markdown in seconds.
✨ Highlights
This release introduces semantic search as an alpha preview, adds automatic robots.txt generation in the SEO plugin, fixes Mermaid C4Context rendering, and includes a new config upgrade command for modernising existing projects.
Semantic Search (Alpha Preview)
docmd now supports semantic search powered by local embeddings, enabling context-aware search results beyond simple keyword matching.
Features
- Context-aware search beyond exact keyword matches
- Natural typo tolerance
- Finds related content even when different terminology is used
- Fully local processing with no external services or API calls
Enable semantic search by adding semantic: true to your configuration:
{
"plugins": {
"search": {
"semantic": true
}
}
}The search plugin automatically installs docmd-search and downloads required models, if failed to do so, it falls back to keyword search.
Documentation - https://docs.docmd.io/plugins/search/#semantic-search-alpha-preview
Note: Multilingual models are available but still being tested. docmd currently uses
docmd-search@0.1.0-alpha.0, so you may encounter bugs or inaccurate confidence scores while development continues.
Introducing Offline Semantic Search Engine (docmd-search)
We're excited to introduce docmd-search.
npm install docmd-searchdocmd-search is a semantic search engine built for documentation sites. It runs entirely in the browser or CLI, requires no servers or API keys, and keeps all processing local.
Although created for docmd, it can be integrated into other documentation platforms, websites, and web applications.
This is an early alpha release and will continue to evolve, but the foundation is already in place.
GitHub: https://github.com/docmd-io/docmd-search
Documentation: https://docs.docmd.io/search/
SEO Plugin: robots.txt Auto-Generation
The SEO plugin now automatically generates a robots.txt file during the build process if one does not already exist.
Features
- Smart defaults with
User-agent: *andAllow: / - Automatic sitemap references when
config.urlis configured - Optional AI crawler controls
- Existing
robots.txtfiles are never overwritten
{
"plugins": {
"seo": {
"aiBots": false
}
}
}By default AI crawlers are allowed. Setting aiBots: false adds directives for GPTBot, ChatGPT-User, Google-Extended, CCBot and other supported AI crawlers.
Mermaid C4Context Fix
C4Context diagrams now render correctly instead of appearing as blank white boxes.
The issue was caused by a missing SVG namespace generated by Mermaid when rendering C4Context diagrams. docmd now automatically injects the required namespace before parsing, ensuring these diagrams render correctly.
Thanks to @sinsombat for the fix and accompanying test suite.
Config Upgrade Command
A new --upgrade flag has been added to the docmd migrate command.
npx @docmd/core migrate --upgradeRunning the command automatically updates older configuration files to the modern schema.
The following legacy keys are migrated automatically:
| Legacy Key | Modern Key |
|---|---|
projects |
workspace.projects |
siteTitle |
title |
siteUrl / baseUrl |
url |
srcDir / source |
src |
outputDir |
out |
defaultLocale |
i18n.default |
Existing values are preserved during migration.
TOC HTML Entity Decoding
Heading text containing special characters such as <, >, &, and smart quotes now displays correctly in the Table of Contents sidebar.
Previously, these characters appeared as raw HTML entities instead of their intended representation.
Changelog
New Features
- Added alpha preview support for semantic search via
docmd-search. - Added automatic
robots.txtgeneration to the SEO plugin. - Added
search.showFiltersto hide the version filter bar above search results. - Added
search.showConfidenceto display semantic search confidence percentages. - Added right-aligned search result metadata for versions and confidence badges.
Bug Fixes
- Fixed Mermaid C4Context diagrams rendering as blank white boxes.
- Fixed Live Editor template rendering crash caused by early
workspaceaccess. - Fixed HTML entity decoding in the Table of Contents.
- Fixed excessive dev server reloads caused by duplicate
fs.watchevents on macOS.
Improvements
- Added
docmd migrate --upgradefor automated configuration modernisation. - Restyled the Project Switcher to align with the appearance and language controls.
- Config and
navigation.jsonchanges now trigger fast targeted rebuilds instead of full restarts. - The dev server now automatically opens the documentation URL in the default browser on startup.
Thanks 💖
Thanks to all contributors, testers, and issue reporters who helped improve this release.
Documentation: https://docs.docmd.io/
GitHub: https://github.com/docmd-io/docmd
What's Changed
- fix(mermaid): resolve C4Context white-page caused by missing
xmlns:xlinknamespace declaration in #140
Full Changelog: 0.8.4...0.8.5
docmd@0.8.4 🚀 (Deployer V2 for Vercel, Netlify & GH Pages)
docmd 0.8.4 • Deployer V2
Build production-ready documentation from Markdown in seconds.
✨ Highlights
This release introduces the new Deployer V2 system, alongside improvements to plugin safety, build reliability, and development workflows.
Deployment targets
The deployment engine has been extracted into a dedicated @docmd/deployer package with provider-based deployment targets.
You can now generate deployment files directly for GitHub Pages, Vercel, and Netlify:
docmd deploy --github-pages
docmd deploy --vercel
docmd deploy --netlifyGenerated files automatically inherit values from your docmd.config.json, including the output directory, site URL, SPA routing, and Node.js version.
Existing deployment targets for Docker, Nginx, and Caddy continue to work unchanged.
Markdown line breaks
A new markdown.breaks option has been added to docmd.config.json.
Set this to false to disable automatic markdown line breaks and preserve wrapped markdown formatting.
{
"markdown": {
"breaks": false
}
}Changelog
- Deployer: Extracted the deployment engine into
@docmd/deployerwith native support for GitHub Pages, Vercel, and Netlify targets. - Markdown formatting: Added the
markdown.breaksconfiguration option to control automatic soft-wrap line breaks (#137, #127). - Installer security: Restricted plugin installs to the official npm registry and replaced unsafe shell-based execution paths.
- Threads plugin: Disabled raw HTML rendering inside thread comments whilst preserving standard markdown formatting (#136).
- Build reliability: The parser and build lifecycle now exit with non-zero status codes on plugin failures, improving CI pipeline behaviour (#134).
- Developer experience: Reduced development server noise during hot reloads and added
filePatharguments to parser lifecycle hooks (#135). - UI updates: Refined the version switcher with Lucide icons and aligned Project Switcher dropdown styles with the standard theme menus.
- Bug fixes: Fixed project-switching cache overlaps, translation fetch issues on
noStylepages, and copy-code icon hover states.
Thanks 💖
Thanks to all contributors, testers, and issue reporters who helped improve this release. Special thanks to security researchers for coordinating responsible disclosures.
Documentation: https://docs.docmd.io/
GitHub: https://github.com/docmd-io/docmd
New Contributors
- @chocolatecake777 made their first contribution in #136
Full Changelog: 0.8.3...0.8.4
docmd@0.8.3 🗂️ (Workspaces & Enhanced Security)
docmd v0.8.3 is a major architectural update that introduces Workspaces, enabling centralised management of multiple documentation projects. This release also prioritises Security & Stability with hardened rendering across the ecosystem and improved routing reliability.
✨ Highlights
🚀 Workspaces Architecture
The multi-project system has been completely reimagined as Workspaces. You can now manage multiple independent documentation projects from a single root configuration with powerful new capabilities:
- Global Configuration Cascading: Define your
theme,menubar,navigation, andlogoat the root to apply them across all projects automatically. - Premium Project Switcher: A new slim UI component for seamless navigation between projects, supporting multiple positions (
sidebar-top,sidebar-bottom, andoptions-menu). - Flexible Overrides: Projects can selectively override global defaults in their own local configuration.
- Backward Compatibility: Existing multi-project configurations are automatically normalised to the new workspace schema.
Check complete Workspaces documentation.
🛡️ Enhanced Security & Stability
This release introduces a series of internal improvements to harden the documentation engine and its plugins against edge-case rendering issues:
- Hardened Rendering: Systematically replaced
innerHTMLusage with secure DOM APIs (createElement,DOMParser) across the core and plugins. - Universal Security Audit: The monorepo Failsafe pipeline now includes a specialised, AST-based security audit to detect and block unsafe DOM patterns (
innerHTML,outerHTML,document.write) before any release. - Improved Search Safety: Search results now use a more robust rendering pipeline to ensure content is always handled securely.
- Dev Server Isolation: Enhanced directory traversal protection in the local development server for improved environment isolation.
🛠 Improvements & Fixes
Auto-Designated Index Normalisation
Fixed a bug in the Zero-Config auto-router where files designated as directory indexes (when no index.md is present) failed to render correctly due to a trailing slash mismatch. The engine now correctly normalises these paths, ensuring stable routing and correct index.html generation for all auto-indexed directories.
Routing Stability
Improved path predictability in the Auto-Router to resolve trailing slash inconsistencies in directories without a dedicated index file.
TUI Pipeline & Workspace Build Clarity
Refined the terminal output (TUI) for multi-project Workspace builds. Build logs are now consistently structured into strict sections (Data Indexing, Publishing, etc.) across both standalone and workspace builds, preventing overlapping text, looping spinners, and disconnected status messages.
UI Sidebar Adjustments
Fixed a layout bug where dropdown menus (Version, Language, and Project Switchers) inside the sidebar would get cropped by the sidebar's bounding box. These menus now securely render over the main content area and dynamically align to the sidebar width, preventing them from overflowing the browser viewport.
📦 Package Updates
- Node.js Types: Updated
@types/nodetov25.8.0. - GitHub Actions: Updated CI/CD workflows to latest stable versions for improved reliability.
📝 Complete Changelog
🚀 New Features
- Core Engine: Introduced
workspaceschema for centralised project management. - UI Components: Added
project-switcherpartial and event delegation logic. - Config Loader: Implemented global default merging and
menubaritem aliasing (title/path). - Pipeline: Integrated a static-analysis Security Audit into the Universal Failsafe V5.0 to enforce strict DOM safety standards across all packages.
🐛 Bug Fixes
- Threads Plugin: Hardened comment rendering and metadata escaping by moving to DOMParser.
- Search Plugin: Improved results rendering and data attribute safety, replacing innerHTML.
- Icon Renderer: Hardened icon attribute rendering for SVG icons.
- Tabs Component: Improved attribute safety in tab navigation items.
- Core Engine: Fixed path normalisation for auto-designated index files in the generator.
- Routing: Removed implicit index designation in the Auto-Router to improve path predictability.
- Dev Server: Enhanced path validation for static file serving.
- UI Assets: Removed
overflow: hiddenfrom sidebar and refactored positioning contexts to prevent cropped dropdown menus. - CLI / TUI: Fixed dangling status messages and unclosed UI sections during workspace and dev builds.
Infrastructure
- Refactoring: Renamed workspace engine to
workspace.tsand refactored terminology across the monorepo. - Dependencies: Bumped
@types/nodefrom 25.7.0 to 25.8.0. - Workflows: Updated GitHub Actions group to latest versions.
📥 Upgrade
npm install -g @docmd/coreWhat's Changed
- fix(core): strip trailing slash from _sourceFile in navDesignatedIndexFiles by @sinsombat in #131
- fix(core): remove implicit file-promotion + clean dev output + full rebuild on watch by @sinsombat in #133
New Contributors
- @sinsombat made their first contribution in #131
Full Changelog: 0.8.2...0.8.3
docmd@0.8.2 🩹 (Patch Release)
This is a critical patch release that resolves installation issues for users using npm and standardises the monorepo's internal dependency resolution.
🚀 Highlights
Fixed npm install Compatibility
Resolved a critical issue where packages published to the NPM registry contained unresolved workspace: protocol references in their optionalDependencies. This caused npm install to fail with an EUNSUPPORTEDPROTOCOL error. The publishing pipeline has been updated to ensure all dependency types are correctly resolved to semver ranges.
🛠 Improvements & Fixes
- Publishing Pipeline: Fixed
scripts/resolve-ws-deps.jsto correctly transformoptionalDependenciesduring the release process. - Dependency Standardisation: Updated all internal package references to ensure consistency across the ecosystem.
- Workflow Optimisation: Updated GitHub Actions to use stable runner configurations for reliable binary generation.
📦 Package Updates
All packages in the @docmd ecosystem have been bumped to v0.8.2 to ensure full compatibility and lock-step versioning.
For a full list of architectural changes introduced in the v0.8 series, please refer to the v0.8.1 Release Note.
Full Changelog: 0.8.1...0.8.2
docmd@0.8.1 ⚙️ (Pluggable Rust Engine - Preview)
docmd v0.8.1 introduces a pluggable engine architecture, major improvements to git indexing performance, and important fixes for SPA navigation.
✨ Highlights
Pluggable Engine Architecture (Preview)
docmd now supports a pluggable engine system. The new @docmd/engine-rust package provides a foundation for accelerated I/O operations, designed to work seamlessly with existing plugins.
{
"engine": "rust"
}The engine is optional - the default JavaScript engine handles all workloads. The Rust engine provides measurable gains for large repositories (1000+ files) where git indexing and batch file operations dominate build time.
Architecture highlights:
- Pluggable design: Engines are packages under
@docmd/engine-*, following the same pattern as plugins - Bundled pre-built binaries: All supported platform binaries are now delivered via a single centralised
@docmd/engine-rust-binariespackage - Lazy loading: Native binaries are only loaded when the engine is explicitly selected
- Plugin-compatible: Plugins can leverage the engine API for accelerated I/O
- Automatic fallback: If the native binary isn't available, the JS engine takes over transparently
Available engine packages:
| Package | Description |
|---|---|
@docmd/engine-js |
Default JavaScript engine (always available) |
@docmd/engine-rust |
Rust engine loader (orchestrates native acceleration) |
@docmd/engine-rust-binaries |
Centralised native binary distribution for all platforms |
Note: The Rust engine is in preview. In the initial v0.8.1 rollout, pre-compiled native binaries are exclusively published for macOS ARM64 (Apple Silicon) platforms within the binaries package. Builds executed on other architectures automatically and transparently fallback to the high-performance JS engine. Internal benchmarks show a ~25% improvement on cold builds and ~17% on warm builds for an 886-page multi-project site.
Git Indexing: Persistent Disk Cache
The git plugin now persists indexing results to disk across builds. Previously, git metadata was re-indexed from scratch on every build - even when no files had changed. The new cache system:
- Routes cache storage cleanly to your operating system's isolated temporary directory (
os.tmpdir()), preventing top-level directory clutter. - Secures cache retrieval persistently across directory renames or moves by generating a robust hash anchored to your repository's Git tracking URL or unique OS inode identifiers.
- Supports configurable storage paths via the new
tmpconfiguration parameter. - Works with both engine paths (Rust and JS) and the
execFilefallback. - Provides ~45% faster warm builds on the official documentation site (886 pages).
Configurable tmp Directory
By default, docmd now routes internal state and build caches to your system's isolated temporary folder to keep your project root clean. For environments that require persistent caching in specific locations (e.g., CI/CD pipelines with cache-key requirements), you can now configure the full storage path using the new tmp key:
{
"src": ".",
"out": "site",
"tmp": ".docmd-cache"
}This allows you to anchor the .docmd/ state folder to any directory, ensuring it can be easily cached and restored across build sessions. As suggested in #124
JSON Configuration Standard
Starting with v0.8.0, docmd.config.json is the recommended configuration format. All v0.8 documentation has been updated to use JSON examples. The .js and .ts formats remain fully supported as fallbacks for dynamic configuration logic.
🐛 Bug Fixes
External Links in SPA Navigation
Fixed an issue where external links defined in navigation.json with external: true were incorrectly resolved as relative paths after navigating to another internal page via the SPA router. The links now correctly preserve their absolute URLs during client-side navigation.
Navigation External Link Shorthand
The external: prefix, previously available only in Markdown content, now works in navigation.json as a convenient shorthand:
[
{ "title": "GitHub", "path": "external:https://github.com/docmd-io/docmd" }
]This is equivalent to:
[
{ "title": "GitHub", "path": "https://github.com/docmd-io/docmd", "external": true }
]Git Cache Directory Stability & Relocation
Fixed a bug where the git plugin's disk cache was written to shifting directories during multi-project builds. The cache has been cleanly relocated out of the project root directory directly into os.tmpdir() using a persistent repository identifier, fully supporting the custom tmp override path parameter.
Engine Configuration Respected
The git plugin now respects the engine configuration key. Previously, it always attempted to load the Rust engine first regardless of configuration. Setting "engine": "js" now correctly forces the JavaScript engine.
📝 Complete Changelog
🚀 Engine & Architecture
- Pluggable Engine System: New
Engineinterface in@docmd/apifor build acceleration - JS Engine Package: Default engine extracted to
@docmd/engine-js - Rust Engine Ecosystem: Native Rust acceleration with centralised binary distribution via
@docmd/engine-rust-binaries - Engine Loader API:
loadEngine()andregisterEngine()for custom engine registration - Engine Config Key: New
enginekey indocmd.config.jsonto select build engine - Engine Prominence: Elevated top-level logging prominence for custom build engines inside TUI layouts
⚡ Performance
- Git Disk Cache: Engine-path results now persisted to disk for warm builds
- Persistent Identification: Dual-mode cache identification using Git remote URL hashing and OS inode fallback
- Configurable Storage: Added support for overriding cache destination via the
tmpconfig parameter - Config Resolvers: Added seamless detection support for standard JSON config files in multi-project sub-project loops
- Disk Cache Pre-warming: Build pipeline reads disk cache before engine/subprocess calls
🐛 Bug Fixes
- SPA Router: External links in sidebar navigation now correctly preserved during client-side navigation. Fixed #123
- Navigation Config:
external:prefix now supported as shorthand innavigation.json - Link Resolution: Fixed URL resolution edge case for protocol-relative URLs
- Git Plugin: Now respects the
engineconfiguration key instead of always defaulting to Rust - Multi-Project Cache: Relocated state storage to deterministic temporary OS structures to prevent loss between loop boundaries
📥 Upgrade
npm install -g @docmd/coreFull Changelog: 0.8.0...0.8.1
docmd@0.8.0 ⚡ (The Parallel Engine Era)
docmd v0.8.0 introduces a new parallel build engine, first-class multi-project support, and major improvements to indexing performance. Large documentation sites can now build significantly faster while maintaining low incremental rebuild latency during development.
✨ Highlights
- Native multi-threaded build engine with WorkerPool support
- First-class multi-project documentation builds
- Persistent Git indexing cache with parallel I/O
- Worker-thread APIs for plugins
- TypeScript and JSON configuration support
- Improved Mermaid diagram controls and fullscreen support
⚡ Benchmarks
This release introduces a new parallel build pipeline, persistent worker pools, and AST caching. Large documentation sites now rebuild significantly faster, with incremental performance continuing to improve across subsequent builds.
|
docmd < 0.7.9
|
docmd 0.8.0+
|
🚀 New Features
Parallel Build Engine
docmd now processes pages in parallel using a native WorkerPool architecture. Markdown parsing and processor hooks can run across multiple CPU cores, significantly reducing build times for large documentation sites.
- Up to 10x faster builds on large sites
- Persistent workers during development
- Automatic CPU-aware thread allocation
- Reduced incremental rebuild latency
Multi-Project Support
You can now build multiple independent documentation projects into a single site output. This is ideal for monorepos and large documentation ecosystems.
- Shared output directory across projects
- Independent versioning and i18n contexts
- Separate plugin configurations per project
- Supports unified documentation domains
Plugin Worker API
Plugins can now offload expensive tasks to background threads using the new ctx.runWorkerTask() API.
- Background processing for indexing and parsing
- Better main-thread responsiveness
- Shared WorkerPool support across plugins
- Available across plugin lifecycle hooks
Persistent Git Indexing
The Git plugin has been redesigned with persistent disk caching and parallel I/O processing.
- Subsequent indexing reduced from ~18s to ~3.5s on large repositories
- Automatic pruning for deleted or renamed files
- Parallel Git metadata syncing
- Reduced redundant
git logoperations
SEO-Friendly README Routes
README.md files are now automatically treated as directory indexes.
/guide/README.mdresolves to/guide/#117index.mdremains the primary priority- Clean URL generation for README and index routes
Modern Configuration Support
docmd configuration can now be written in TypeScript or JSON.
docmd.config.tswith type-safedefineConfig#115- Lightweight
docmd.config.jsonsupport - Improved configuration discovery
- Fully serialisable resolved config output
Note: We will soon migrate all default configs to .json file type with .ts and .js as fallback.
Better Mermaid Diagrams
The Mermaid plugin now provides a cleaner experience for large diagrams.
- Zoom and pan controls moved to the bottom-left
- Improved fullscreen navigation #120
- Better interaction for oversized diagrams
🛠 Developer & Architecture Changes
Worker Pipeline
- Added dynamic markdown processor hydration inside worker threads
- Added MD5-based AST caching for unchanged files
- Added persistent development worker pools
- Added CPU-aware worker throttling
- Added dynamic EventEmitter listener scaling for large builds
Plugin System
- Added
onBeforeBuildlifecycle hook - Added
ctx.runWorkerTask()across plugin contexts - Added worker-thread search indexing support
- Added persistent Git cache infrastructure
- Added parallel Git metadata processing
Terminal Interface
- Added stable in-place TUI progress bars
- Added plugin-level progress rendering support
- Improved indexing visibility during builds
Infrastructure
- Added
docmd.config.tsanddocmd.config.jsondiscovery - Added direct utility exports from
@docmd/utils - Improved config serialisability across worker boundaries
- Centralised Git root and branch utilities
⚠️ Breaking Changes
Utility Imports
Custom plugins relying on internal core imports must migrate to @docmd/utils.
Serialisable Hooks
markdownSetup hooks must now be serialisable to support worker-thread execution.
🔄 Migration Guide
Most projects can upgrade without configuration changes.
If you maintain custom plugins:
- migrate internal imports to
@docmd/utils - ensure
markdownSetuphooks are serialisable
See Building Plugins for a full api walkthrough.
📥 Upgrade
npm install -g @docmd/coreFull Changelog: 0.7.9...0.8.0



