Serve markdown/docs/text notes with MkDocs using a specified work directory as the output folder (scripts/config/site).
Resources
2Install
npx skillscat add igamenovoer/magic-context/serve-md-by-mkdocs Install via the SkillsCat registry.
Serve Markdown by MkDocs (DocView)
Use this skill when you want a quick, web-based viewer for Markdown scattered across a repo (not necessarily docs/), while preserving the original directory structure.
Typical user phrasing that should trigger this skill:
- “serve markdowns/docs/md/textfiles/etc with mkdocs, using
<work_dir>as the work dir”
Interpretation:
<work_dir>is the work directory (create it if missing; reuse it if it exists). This folder holds the refresh script, a scanner script, a YAML manifest, the MkDocs config (if needed), a staged symlink tree, andsite/build output.- By default, staged symlinks are placed under a subdirectory (default:
<work_dir>/_staged/) so you can ignore them with a local<work_dir>/.gitignorewhile keeping scripts/config tracked if you want.
This skill’s default approach is:
- generate a staged tree under
<work_dir>/_staged/(typically symlinks; can be adapted to copying) - generate
<work_dir>/mkdocs.ymlonly if missing (existing config is preserved) - enable Mermaid + KaTeX by default (via
pymdown-extensions+ KaTeX/Mermaid JS/CSS includes) - run
<mkdocs_cmd> serve(use MkDocs defaults unless you specify otherwise)
Dependency Resolution (MkDocs)
This skill must locate an existing mkdocs first. Do not auto-install it.
Resolution order (stop at the first one that works):
- Project Pixi environment (preferred when available):
pixi run mkdocs --versionIf that works, use <mkdocs_cmd> = pixi run mkdocs.
- Active virtualenv / venv (if the user is already in one):
mkdocs --version
python -m mkdocs --versionIf either works, use <mkdocs_cmd> = mkdocs (or python -m mkdocs if the console script is not available).
- Global Pixi tools (if the user installed tools via
pixi globaland exposed them onPATH):
pixi global list
mkdocs --versionIf that works, use <mkdocs_cmd> = mkdocs.
- uv tools (only if
mkdocsis already installed as a tool; do not trigger installs):
uv tool list
uv tool dir
mkdocs --versionIf uv tool list shows mkdocs but mkdocs is not on PATH, run it via the uv tools directory:
tool_dir="$(uv tool dir)"
"${tool_dir}/mkdocs/bin/mkdocs" --versionIf that works, use <mkdocs_cmd> = mkdocs (or use the explicit path from above).
- System Python (last resort):
python3 -m mkdocs --version
python -m mkdocs --versionIf either works, use <mkdocs_cmd> = python3 -m mkdocs (or python -m mkdocs).
If none of the above finds a working mkdocs, fail fast and report “missing dependency: mkdocs”. Never attempt to install mkdocs automatically; let the user install it in their preferred environment manager.
Plugin Installation (after MkDocs is found)
Once mkdocs is found, the agent may auto-install any MkDocs plugins/themes/markdown extensions needed by <work_dir>/mkdocs.yml, but must install them into the same environment that provides <mkdocs_cmd>.
Guidance:
- Preferred verification step: run
<mkdocs_cmd> build -f <work_dir>/mkdocs.yml(or<mkdocs_cmd> serve -f <work_dir>/mkdocs.yml) and look for missing-module errors (for example:No module named ..., missingmkdocs-material, missingpymdown-extensions, missingmkdocs-extrafiles, etc). - Install only what’s needed to satisfy the config (theme/plugins/markdown_extensions). Do not install
mkdocsitself automatically.
Notes:
- Mermaid and KaTeX support in this skill’s scaffolded config does not require an MkDocs plugin; it uses built-in
extra_javascript/extra_csspluspymdown-extensions(pymdownx.superfencesandpymdownx.arithmatex).
Environment-specific install strategy:
- If
<mkdocs_cmd>ispixi run mkdocs(project Pixi):
- Prefer updating the project manifest (do not
pip installdirectly):
pixi add --pypi mkdocs-material pymdown-extensionsAdd other required plugins similarly (example):
pixi add --pypi mkdocs-extrafiles mkdocs-include-markdown-pluginThen re-run <mkdocs_cmd> build -f <work_dir>/mkdocs.yml to verify.
- If
<mkdocs_cmd>comes from a venv / system Python:
- Install into that Python (use the same interpreter that runs MkDocs):
python -m pip install mkdocs-material pymdown-extensionsThen re-run <mkdocs_cmd> build -f <work_dir>/mkdocs.yml to verify.
- If
<mkdocs_cmd>comes from a uv tool install:
- Install into the uv tool environment (only after confirming it exists; do not trigger installs of MkDocs itself):
tool_dir="$(uv tool dir)"
ls -la "${tool_dir}/mkdocs/bin" # inspect this directory to find the tool's python
"${tool_dir}/mkdocs/bin/python" -m pip install mkdocs-material pymdown-extensionsThen re-run the uv-provided MkDocs command to verify.
When to Use
- You have Markdown scattered across multiple folders (notes, design docs, runbooks, PRDs, etc).
- You want “browse everything” without curating
nav:in the mainmkdocs.yml. - You want a dedicated service name/port separate from the main docs site.
Parameters to Collect
- Work directory: e.g.
docview-prd,docview-reports,tmp/docview-issues - Site title: e.g.
PRD View - Serve address/port:
- Default: keep it local (MkDocs default is typically
127.0.0.1:8000) - If the user asks to “make it public”: bind
0.0.0.0(for example0.0.0.0:8000or0.0.0.0:<port>)
- Default: keep it local (MkDocs default is typically
- Scan inputs (repo-relative paths or glob patterns): e.g.
<docs_dir> <notes_dir>or<docs_dir>/**or**/*.md - Optional: include/exclude rules (hidden dirs, externals, and whether to respect gitignore when discovering files)
Workflow
0) If <work_dir> already exists, look for “refresh” cues first
If the user points to an existing <work_dir>, they may mean “refresh/rebuild” rather than “re-scaffold”.
Before generating anything, check for these files inside <work_dir>:
refresh-docs-tree.sh: if present, prefer running it to recreate the staged tree (typically under_staged/, or your chosen--staging-dir), while preserving existing rules and defaults.mkdocs.yml: if present, prefer reusing it (preservesdev_addr/ ports, theme/plugins, etc).docview.yml: if present, prefer reusing it (preserves the default scan patterns, exclusions, and gitignore policy).README.md: often documents the env var names (like*_DIRS/*_REPO_ROOT) and default scan patterns.
Typical “refresh intent” actions:
bash <work_dir>/refresh-docs-tree.sh
<mkdocs_cmd> serve -f <work_dir>/mkdocs.ymlOnly re-scaffold (and overwrite) if the user explicitly asks to “regenerate config/script” (use --force).
1) Create (or reuse) a dedicated work dir
Run the scaffolder (writes a new service folder with a refresh-docs-tree.sh, .gitignore, and README):
pixi run python magic-context/skills/devel/serve-md-by-mkdocs/scripts/scaffold_docview_service.py \
--work-dir <work_dir> \
--site-name "Reports View" \
--staging-dir _staged \
--default-target .Then run:
bash <work_dir>/refresh-docs-tree.sh
<mkdocs_cmd> serve -f <work_dir>/mkdocs.ymlIf you want a non-default bind address/port, either:
- scaffold with
--dev-addr <addr:port>(bakes it into<work_dir>/mkdocs.yml), or - scaffold with
--public(bakes0.0.0.0:8000into<work_dir>/mkdocs.yml), or - override at runtime:
<mkdocs_cmd> serve -f <work_dir>/mkdocs.yml -a 0.0.0.0:<port>
2) Re-index specific paths/patterns (without re-scaffolding)
Once <work_dir>/refresh-docs-tree.sh exists, you can point it at specific paths:
bash <work_dir>/refresh-docs-tree.sh <docs_dir> <notes_dir>- or set the generated
*_DIRSenv var shown in<work_dir>/README.md - or edit
<work_dir>/docview.ymlto change the default patterns used when you runbash <work_dir>/refresh-docs-tree.shwith no args/env override
Manifest (<work_dir>/docview.yml)
<work_dir>/docview.yml captures your “what should be staged” intent for symlink creation.
Schema:
magic-context/skills/devel/serve-md-by-mkdocs/schemas/docview.schema.json
Key fields:
mkdocs.dev_addr: records the intended bind address/port (and is used to generate<work_dir>/mkdocs.ymlonly when that file is missing)scan.include_globs: glob patterns used to discover Markdown (repo-relative)scan.exclude_globs: glob patterns excluded from Markdown discoveryscan.force_globs: glob patterns to scan even if gitignored (explicit user intent)scan.auto_exclude_generated: if true (default), avoid scanning DocView/MDView workdirs and their generated treesscan.respect_gitignore: defaulttrue(do not scan gitignored dirs/files for Markdown discovery)assets.include_images: defaulttrue(stage local images referenced by selected Markdown)
Example (abridged):
version: 1
scan:
auto_exclude_generated: true
respect_gitignore: true
include_globs: ["**/*.md"]
exclude_globs: ["<big_dir>/**"]
force_globs: ["<gitignored_dir>/**"]
assets:
include_images: trueRules:
- By default, Markdown discovery respects
.gitignoreand usesscan.include_globsfrom the manifest. - By default, discovery excludes any directories that start with
.(controlled byscan.include_hidden: false). - By default, discovery also auto-excludes DocView/MDView workdirs (including their staged trees like
_staged/ordocs/, andsite/) using file/dir-structure heuristics, to avoid self-indexing loops and duplicate pages. - If you explicitly want to scan a gitignored location, add it under
scan.force_globs(or pass it as an explicit arg torefresh-docs-tree.sh, which is treated as strong intent). - Referenced image assets are still staged even if gitignored, as long as the file exists.
Default scan behavior (when you don’t specify scan locations): the scaffolder writes scan.include_globs so the refresh script scans the whole workspace for Markdown (for example **/*.md) while respecting .gitignore.
3) Add Pixi tasks (optional but recommended)
Add three tasks under [tool.pixi.tasks]:
<task_prefix>-refresh:bash <work_dir>/refresh-docs-tree.sh<task_prefix>-serve:bash <work_dir>/refresh-docs-tree.sh && mkdocs serve -f <work_dir>/mkdocs.yml<task_prefix>-build:bash <work_dir>/refresh-docs-tree.sh && mkdocs build -f <work_dir>/mkdocs.yml
Pick a port based on your local context (or rely on MkDocs defaults).
Note: Pixi tasks run inside the project Pixi environment. Only add these tasks if mkdocs (and any referenced theme/plugins/extensions from <work_dir>/mkdocs.yml) are available in that environment.
Verification (required)
After running bash <work_dir>/refresh-docs-tree.sh, verify that all symlinks under the staging directory are valid (no broken links):
find <work_dir>/<staging_dir> -xtype l -printExpected: no output.
<staging_dir> is usually _staged (or whatever you set via --staging-dir; it should match docs_dir in <work_dir>/mkdocs.yml).
If there is output, rerun the refresh and/or check whether the target source files were moved/deleted, or whether your selected paths/patterns (*_DIRS or CLI args) include paths that no longer exist.
Note: refresh may emit warnings like “missing asset referenced by …” when Markdown references images that don’t exist on disk; those files won’t be staged.
Also verify that the work dir contains the scanner script which decides what gets staged (Markdown + referenced image assets):
<work_dir>/scan-files-to-stage.py
Notes / Gotchas
- Git hygiene: by default,
<work_dir>/.gitignoreignores the staging subdir (like_staged/),site/,mkdocs.yml, andrepo-root.txt. Keep or change this based on whether you want staged symlinks tracked. - Gitignore-aware scanning: by default, file discovery respects
.gitignore(gitignored files/dirs won’t be scanned). However, if a selected Markdown page references a gitignored image file, it will still be staged (symlinked) as long as the file exists. - Auto-excluding generated workdirs: by default, the scanner avoids scanning DocView/MDView workdirs (including this one) to prevent recursion/duplication. Set
scan.auto_exclude_generated: falsein<work_dir>/docview.ymlif you intentionally want to index those directories. - Manifest is required:
<work_dir>/docview.ymlis always created by this skill, and<work_dir>/scan-files-to-stage.pytreats a missing manifest as an error. - No-symlink alternative: if you prefer not to stage via symlinks/copies, consider using the
mkdocs-extrafilesplugin to map externalsrcpaths into virtualdestpaths underdocs_dir. - Symlinks: the default implementation uses symlinks. On Windows, symlink creation may require elevated permissions or Developer Mode; if this is a blocker, reimplement the refresh step by copying files instead of linking.
- Mermaid: enable
pymdownx.superfenceswith amermaidfence + Material integration (the scaffolder emits this). - KaTeX (math): the scaffolder also emits
pymdownx.arithmatex+ KaTeX auto-render viaextra_javascript/extra_css(you can swap to MathJax if preferred). - Mermaid/KaTeX init scripts: the scaffolder writes
<work_dir>/javascripts/mermaid-init.jsand<work_dir>/javascripts/katex-init.js, andrefresh-docs-tree.shstages them intodocs_dirso MkDocs can serve them.