Skip to content

Feature mx watch command #6

@shm11C3

Description

@shm11C3

Summary

Add a watch command to mx (md-xformer) that monitors input Markdown files (and optionally templates/assets) and re-runs the transform to regenerate HTML outputs automatically during writing.

Motivation

  • Fast feedback loop while editing articles.
  • Reduce manual CLI runs and copy/paste mistakes.
  • Improve author experience for teams writing many posts.

Goals

  • mx watch <input> continuously rebuilds on file changes.
  • It supports watching directories (e.g., articles/) and single files.
  • It can watch templates/CSS as well so styling updates are reflected immediately.
  • It prints clear logs and rebuild status (success/failure).

Non-goals

  • Do not build an interactive TUI.
  • Do not implement a live browser preview server (optional later).
  • Do not implement OS-specific filesystem watchers without a dependency (we will use a library).

CLI UX

Command

  • mx watch <input>

Options

  • -t, --template <name>: template preset or template directory name (same meaning as existing articles command).
  • -o, --out <path>: output file path (single file mode) or output directory (directory mode).
  • --dir <path>: working directory (defaults to .).
  • --include <glob>: additional watch globs (repeatable). Example: --include ".tool-name/**/*.html".
  • --ignore <glob>: ignore patterns (repeatable). Default ignores: node_modules/**, dist/**, .git/**.
  • --debounce <ms>: debounce interval. Default: 200.
  • --once: run a single build then exit (useful for debugging watch config).
  • --verbose: more logging.

Examples

  • Watch all articles:

    mx watch articles -t wordpress -o dist/
    
  • Watch a single file:

    mx watch articles/post.md -t wordpress -o dist/post.html
    
  • Also watch templates and CSS explicitly:

    mx watch articles -t wordpress -o dist/ --include ".tool-name/**/*"
    

Exit codes

  • 0: clean exit (e.g., Ctrl+C)
  • 1: initialization error
  • 2: invalid args

Watch targets

By default, watch should include:

  • The input path:

    • If directory: **/*.md under that directory
    • If file: that file only
  • The config/templates directory (recommended default):

    • .tool-name/templates/**/*.html
    • .tool-name/assets/**/*.css

If the config directory is not present, still watch input files; template watching becomes a no-op.

Output mapping

Directory mode

When <input> is a directory and --out is a directory:

  • For each changed Markdown file articles/foo/bar.md, output to dist/foo/bar.html.
  • Create parent directories automatically.

Single file mode

When <input> is a file and --out is a file:

  • Rebuild only that output.

Mixed cases

If <input> is a directory and --out is a file:

  • Treat as invalid args (exit code 2).

Rebuild behavior

  • Run an initial build immediately upon starting watch.
  • On changes, schedule a rebuild after debounce.
  • Coalesce bursts of changes into a single rebuild.

Error handling

  • If a rebuild fails, log the error but keep watching.
  • Next change triggers another rebuild attempt.

Logging

  • On startup: show watched paths, ignore patterns, debounce value.

  • On rebuild:

    • timestamp
    • changed files (optional in verbose)
    • success/failure and output path(s)
    • elapsed time

Implementation notes

Dependency

Use a cross-platform watcher library.

  • Recommended: chokidar (widely used, stable).

Debounce strategy

  • Implement a debounce timer:

    • On each change, store changed paths in a set.
    • Reset timer.
    • On timer fire, run rebuild and clear the set.

Avoid rebuild loops

  • Ensure output directory (dist/) is ignored by default.
  • Ensure the tool does not watch its own generated outputs.

Integration with existing transformer

  • Reuse the same transform pipeline as mx articles.
  • Extract common “build” logic into a shared function used by both commands.

Tests

  • Unit tests (with filesystem fixtures):

    • initial build is executed
    • changes trigger rebuild (debounced)
    • ignores output directory changes
    • directory mode outputs correct mirrored paths
    • template/CSS changes trigger rebuild
    • failure does not exit watch loop

For watch tests, consider using fake timers and injecting a mock watcher interface, so tests do not rely on real filesystem events.

Acceptance criteria

  • mx watch articles -t wordpress -o dist/ rebuilds when any .md under articles/ changes.
  • mx watch articles/post.md -t wordpress -o dist/post.html rebuilds on that file change.
  • Changing .tool-name/templates/**/*.html or .tool-name/assets/**/*.css triggers rebuild.
  • Output directory is ignored by default to prevent infinite loops.
  • Rebuild errors do not stop watch; subsequent changes retry.

Nice-to-haves (optional)

  • --list to print current watch globs and exits.
  • --poll to force polling mode (for WSL/network drives) with --poll-interval <ms>.
  • --open to open output in default browser (only if you later add a server/preview flow).

Metadata

Metadata

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions