The pathmx command manages, serves, and inspects a project from its package.json root. pmx is the short alias.
pmx [--root <path>] [--no-progress] <command>
| Option | Meaning |
|---|---|
-r, --root <path> | Source root. Defaults to ./paths beside package.json |
--no-progress | Disable animated progress |
The global launcher owns init and update. Project commands delegate to the @pathmx/core version pinned by the selected project's package.json, so pmx --version reports the project release. A positional Source root or --root selects that project consistently for Core, .env, Plugins, and command execution. If both roots are supplied, they must resolve to the same directory.
Inside a repo, prefer its package scripts for everyday work: bun run dev,
bun run check, and bun run start. For the commands below, bun run pmx
uses the installed project CLI without requiring a global launcher. Complete
Install and Quickstart first.
Leave pmx dev or pmx serve running while you use other commands. Commands that
write Sources, admit Events, retry jobs, or drain jobs hand that work to the
running host for the same Source root. The host applies it through its own write
queue and worker and updates the running site. Without a running host, the
command owns the repository until it finishes. Read-only commands inspect the
repository directly. Do not start a second writer against the same state
directory to bypass its lock.
The CLI runs with Bun on macOS, Linux, and Windows. Bun may load .env files
from the calling directory before PathMX starts. PathMX then loads the selected
project's .env without overwriting variables already in the process, including
those loaded by Bun. When selecting another project with --root, values from
the calling directory therefore take precedence over that project's .env.
To let only PathMX load the selected project's .env, invoke the installed entry
with Bun's --no-env-file flag:
bun --no-env-file ./node_modules/@pathmx/core/dist/pathmx.js --root /path/to/project/paths lint
Use the same flag before the TypeScript entrypoint when running Core from source.
Run pmx for a short getting-started workflow, or pmx --help for the full command list. Core command help, such as pmx dev --help, remains available when Plugins are broken or Core dependencies are missing. Top-level help reports unavailable Plugin help separately. pmx help plugins add shows nested command help.
Creates a minimal project with pinned PathMX, TypeScript tooling, and
dev, start, check, and typecheck package scripts.
pmx init [directory] [--no-install]
| Option | Meaning |
|---|---|
directory | Project directory. Defaults to . |
--no-install | Write files without running bun install |
The completion message prints the commands to enter your new project and start it:
pmx init my-course --no-install
cd my-course
bun install
bun run dev
If installation fails after files are created, follow the recovery commands in the error message to finish installing in that directory.
Starts the development server. It watches Sources, rebuilds affected browser bundles, and restarts for engine, Plugin, or Action code changes.
The CLI supervises a separate Bun --watch server process. Explicit Bun runtime
arguments are preserved through project-package delegation and server restarts.
Imported component modules using moduleRef are also watched, including modules
in linked Plugin packages. Correcting a broken module or restoring a deleted
import recovers the failed start. Source edits continue through live updates.
For example, run a test preload in both the CLI and the server:
bun --preload ./mock.ts node_modules/.bin/pmx dev paths --port 3012
Relative preload paths resolve from the original working directory. Keep preloads safe to run in each process and again after a restart. PathMX still controls the server's watch mode and environment-file loading; a preload is not a browser script.
Editing a .js or .mjs file under the Source root reloads connected pages
in that development app. This refreshes the entire browser module graph,
including dynamically imported helpers, and resets in-memory page state.
Markdown and CSS edits continue to update in place. This script-reload policy
does not apply to serve or static publications.
pmx dev [root] [--port <port>] [--verbose] [--admin <actor-source>] [--admin-origin <origin>]
| Option | Meaning |
|---|---|
-p, --port <port> | Port to listen on |
--verbose | Show detailed development logs |
--admin <actor-source> | Admit one Actor Source as the loopback repository admin |
--admin-origin <origin> | Admit the admin only on this HTTPS proxy origin; replaces localhost admission |
After starting an admin session, the compact development strip lets you select a repository user and choose Switch. Switching opens that user's home with their normal permissions and saved state. Repository-admin authority is suspended until you select Repository admin and switch back. End session ends the whole development admin session, including while viewing as another user. The selected user persists across page reloads, Source edits, and automatic code restarts. Stopping the dev command ends its sessions; starting it again requires a new admin session.
The switcher uses the existing loopback or explicitly trusted HTTPS origin and
requires an active development admin session. It is available with dev --admin;
production serve does not enable it. Actions performed while viewing as a user
apply to that user's local data.
Starts the production server and keeps connected browsers in sync as authored Markdown and CSS change.
pmx serve [root] [--port <port>] [--host <hostname>]
| Option | Meaning |
|---|---|
-p, --port <port> | Port. Falls back to PATHMX_PORT, then PORT, then 3000 |
--host <hostname> | Bind address. Falls back to PATHMX_HOST, then 0.0.0.0 |
Set PATHMX_ORIGIN to the one canonical public origin in production. GET /api/runtime/health reports whether the watched Sources are still valid.
Writes the anonymous static publication and its route manifest.
pmx export [root] --origin <url> [--base-path <path>] [--out <path>]
| Option | Meaning |
|---|---|
--origin <url> | Canonical public origin. Required |
--base-path <path> | Public mount path. Defaults to / |
-o, --out <path> | Output directory. Defaults to dist/ in the project root |
The output must not overlap the Source root, including through symlinked parent directories. Files and symlinks cannot be output directories. Export accepts a new or empty directory, or replaces a recognized prior PathMX publication identified by .pathmx/manifest.json. Treat a publication directory as generated output: replacement removes all of its previous contents.
An unrelated nonempty directory is refused. Choose a new or empty directory with --out. The adapter contract lands in .pathmx/manifest.json inside the output.
Lint checks indexed links, declared schemas, compiled Components, and installed Plugin diagnostics. It does not exercise sign-in, Actions, persistence, browser interaction, or a deployment's proxy configuration. Verify those journeys in the running application after authoring checks pass.
Validates Sources, links, compilation, foundation rules, and repository Plugin rules without starting a server. Malformed Source YAML is reported with file coordinates when available; lint continues checking other Sources and exits nonzero when errors remain. Invalid dependencies also identify pages that cannot finish compilation. See Source recovery for development and live-server behavior.
pmx lint [root] [--format text|json]
Run it after every edit. Package and repository Plugins add their own rules to the same report. Text is the default; use JSON for scripts and editors:
pmx lint --format json > lint.json
JSON is a deterministically sorted array of issue records. A clean project returns []. Every record has type and source; the remaining fields depend on the issue:
| Type | Additional fields |
|---|---|
link.unresolved | href, optional label |
source.invalid | plugin, message |
source.warning | message, optional plugin |
[
{
"type": "link.unresolved",
"source": "/index.md",
"href": "./missing.md",
"label": "Missing lesson"
}
]
Lint exits 0 when clean or when only warnings are present, and 1 for unresolved links or authoring errors. If the project cannot load or the command is invalid, stdout has no report; the error goes to stderr with exit code 1.
Plugin authoring issues identify the owning Plugin and Source. Error and warning
records may also include code, hint, block, line, and column. Codes are
scoped to their Plugin; use (plugin, code) to identify a rule rather than matching
message text. block is the Block id. Line and column, when available, are
one-based positions in the complete Source file; column requires line. Missing
location fields mean the producer does not know an exact location.
Text output includes these details and prints hints as Fix: instructions.
Warnings alone exit 0; errors exit 1. Redundant stored Completion keys for
derived targets are warnings because the owning Plugin computes their completion.
Schema and expected compilation failures are collected across Sources, including
invalid component attributes, unknown components, and malformed query fences or
requests. An unexpected Plugin exception names the failing lint hook when
applicable, exits 1, and aborts without a JSON report. Treat this as an incomplete
check, rather than a clean repository.
Plugin authors can contribute diagnostics
with exact locations and recovery hints. This command reads those contributions.
Local authoring commands use development setup, so checking a project with Auth
does not require production email credentials. serve and export keep their
explicit production runtime.
Prints the Source tree with each file's type, Block count, and outgoing and incoming link counts.
pmx tree [root] [--all]
| Option | Meaning |
|---|---|
--all | Include non-Markdown files |
For example, after Quickstart, bun run pmx tree lists index.md, about.md,
and the generated layout/navigation Sources with their types and Block counts.
Add --all to include CSS, JavaScript, and image files too.
Runs the same access-controlled query as a query fence and writes JSON, JSON Lines, or a table.
pmx query <sources|blocks|plugin.name> [options]
| Option | Meaning |
|---|---|
--from <scope> | Canonical or Actor-relative folder scope |
--type <type> | Source or Block type |
--where <field=value> | Scalar equality filter. Repeatable |
--has <prop> | Required registered data prop. Repeatable |
--sort <field[:asc|desc]> | Result ordering. Repeatable |
--limit <number> | Maximum result count |
--links-to <source-or-block> | Sources linking to a Source or Block |
--links-from <source> | Sources linked from a Source |
--no-recursive | Exclude nested folders |
--input <json> | Input for a named plugin.name query |
--request <file> | Complete request as JSON or YAML, or - for stdin |
--as <actor> | Inspect through an Actor's effective access |
--format <format> | json (default), jsonl, or table |
pmx query sources --from /docs --type reference --format table
Shows effective read, write, and execute capabilities for one Source, or every Source one Actor can read.
pmx perms [source] [--as <actor>] [--format text|json]
| Option | Meaning |
|---|---|
source | Source id or path |
--as <actor> | Actor id, such as /users/alice.user |
--format <format> | text (default) or json |
Try bun run pmx perms /about.page in the Quickstart project: it reports the
page's effective capabilities. After Ada's account setup,
compare bun run pmx perms /ada --as /ada.user with the same command without
--as. The Home's owner can read/write personal work; anonymous access is denied.
--as is trusted local inspection. It creates no session and does not impersonate the Actor over HTTP.
Moves a Source, an individual asset, or an entire folder and rewrites authored references.
pmx mv lesson.md lessons/lesson.md --dry-run
pmx mv resources/codex codex --dry-run
pmx mv resources/codex codex
pmx mv work.css studio.css --dry-run
Paths are relative to the configured Source root. A Source destination must end in
.md; an asset destination must remain a non-Markdown file path. A folder destination
must be a new directory location. Existing destinations,
overlapping trees, and paths escaping the Source root are rejected. A folder
containing an index.md still moves as a folder; name the file explicitly to move
only that Source.
An asset move preserves the file's exact bytes and updates indexed references,
including Markdown links/images, [@styles] imports, and writable Plugin relations.
Relative versus absolute paths, query strings and fragments are preserved. The
asset's own contents are unchanged: relative URLs inside CSS or JavaScript imports
are not rewritten. The Bun host supports asset moves, including automatic handoff
to a running dev or production host. Other adapters must implement storage.moveFile.
A folder move carries all authored files, including binary assets, hidden files,
and empty directories. Relative links between moved files retain their spelling.
Inbound Markdown links, reference definitions (including typed layouts), HTML
anchor hrefs, and writable Plugin relations retarget to the new tree. Relative
outbound links to files outside the tree rebase. External URLs stay unchanged.
The query Plugin rewrites explicit from: scopes; omitted scopes continue to
follow the query's containing directory.
--dry-run lists each file move, shows reference diffs and public URL warnings,
and validates the complete plan without writing. --format json includes a
tree inventory for folders and move entries with from and destination path
for folders and individual assets. Asset preview content is null; bytes are not
embedded in the receipt. Apply rechecks the inventory or asset digest, destination,
and Source contents before writing.
When durable storage is active, Bun journals individual asset moves with their reference edits and recovers interrupted work before normal access resumes. Conflicting asset bytes or Source edits stop recovery for inspection. Durable folder moves remain unsupported.
The Bun adapter renames the tree and restores text edits and the original tree if a write fails. This provides recovery from handled I/O failures, not a power-loss journal or a lock against another process editing simultaneously. The browser adapter uses one IndexedDB transaction. Custom storage adapters must provide the folder-move capability.
Symbolic links and trees containing excluded control directories such as .git,
.pathmx, or node_modules are rejected. Scripts and stylesheets travel unchanged;
arbitrary strings in code, frontmatter without a relation contribution, and
dynamically interpolated query scopes are outside the rewrite contract.
Removes a Source and unlinks every reference to it.
pmx rm <path> [--dry-run] [--format text|json]
Leave pmx dev or pmx serve running while using mv or rm. The CLI contacts
that host on the same machine; the same preview and receipt format applies with
or without a host. This local handoff does not require browser sign-in and is not
exposed through the site's HTTP routes. The host must use the same PathMX release
and state directory as the command; otherwise the command asks you to restart the
host or use its PATHMX_DB_DIR. If a handoff fails, the CLI reports the error
without retrying as a standalone writer. A lost response can follow a completed
write: inspect the files before retrying. Restart the host if its local endpoint
is no longer reachable.
For both mv and rm, --dry-run shows the proposed file changes as unified diffs and confirms that no
files changed. Each diff includes three surrounding context lines and one hunk
spanning the changed region. A successful operation reports the distinct
changed-file count. Failed operations do not print a completion message.
pmx mv lesson.md lessons/lesson.md --dry-run
pmx rm lesson.md --dry-run --format json
pmx mv lesson.md lessons/lesson.md --format json
JSON output is one object with version: 1, type, changes, and warnings.
Changes are ordered by Source-root-relative path, with a leading /.
| Result | type | Each change |
|---|---|---|
| Dry run | preview | type, path, before, after |
| Successful write | applied | type, path |
Change types are create, replace, delete, and move. A move also includes from. Preview content is the complete
file text: before is null for creation, and after is null for deletion.
Warnings are strings in the JSON object. Actual writes omit content from their
receipt. A Source move reports deletion of the old path and creation of the new
path; folder and asset moves use move entries. Reference edits use replace.
A preview is informational; rerunning the command recomputes the plan from the
current repository. There is no saved-plan apply command. Failures write an error
to stderr, exit 1, and emit no JSON receipt. A filesystem failure during a
multi-file write can leave some changes applied; inspect the files before retrying.
Manages official @pathmx/* package Plugins. Names accept player or @pathmx/player.
pmx plugins list
pmx plugins add <name...>
pmx plugins remove <name...>
pmx plugins update [name...]
add installs from the CLI's release channel and activates the package in package.json#pathmx.plugins. update with no names updates every installed package.
New activations append after existing Plugins. Repeating add preserves their
order and configuration. Already-installed packages are checked for activation
support before any missing packages are installed. remove changes activation
only after Bun succeeds, preserving other configuration and Bun's manifest edits.
If a package operation or activation fails after installation starts, the error
reports the observed package state and points to pmx plugins list. A dependency
can remain installed when activation fails; inspect that state before retrying.
list shows activated Plugins as active, available but unselected Plugins as
inactive, and supporting packages such as Core, React, and UI as installed.
Supporting packages do not require Plugin activation.
Checks for or installs a newer global CLI from the release channel.
pmx update [--check]
With the optional global launcher installed, run pmx update --check to see
whether the channel matches your installed version or offers a newer release.
This check does not install anything. pmx update installs the newer global CLI
and prints a version-verification step; it does not update a project's pinned
packages. Use bun run pmx plugins update for that project workflow.
Installed Plugins can mount trusted administrator commands beneath their id, such as pmx auth setup, pmx auth doctor, and pmx search <words...>. They appear in pmx --help only when the owning package or repository Plugin is active in the current project.
Search and Auth commands include their own examples. With those Plugins active:
pmx search learning --format json
pmx auth users list --format json
Both commands accept --format table|json|jsonl. JSON returns an array; Auth user records contain name and email, ordered by email. Empty JSON results are [], and empty JSON Lines results write nothing. Table output gives an explicit empty-result message; Auth tables include Email and Name headers.
Inspection results and Source-edit plans go to stdout. CLI logs, export progress, and operation warnings go to stderr, so redirecting output keeps those diagnostics separate. Plugins should use their command context logger for diagnostics and reserve stdout for results.
pmx tree > source-tree.txt
pmx query sources --format json > sources.json
pmx export --origin https://example.com > export.txt 2> export.log
Core command help includes examples and global options. Invalid format flags list the supported choices; ports must be whole numbers from 1 to 65535, and query limits must be nonnegative whole numbers. Missing Source directories report the selected path and commands to select or create a project.
Interactive terminals use a cyan accent for headings and the server URL, with
text labels for status. pmx dev shows the listening URL, version, Source count,
and selected directory. Use pmx dev --verbose for detailed development logs.
Exports show a subtle activity indicator after 350 ms. Fast exports finish without animation. The indicator uses stderr and clears when the operation finishes or fails; warnings remain in scrollback.
pmx export --origin https://example.com --no-progress
NO_COLOR=1 pmx dev
--no-progress disables animation. A nonempty NO_COLOR disables color;
combine both for plain, stationary output. CI, dumb terminals, and redirected
streams receive no color or animation. Each output stream is checked separately,
so redirecting results does not prevent feedback in an interactive stderr.
pmx image optimize --dry-run
pmx image optimize
Inspect authored image uses and generate the sizes those uses request. Dry-run reports planned widths without writing variants. Normal runs reuse the content cache, report byte sizes and failures, and preserve original files. Development and static publishing also generate variants automatically. See Images for supported formats and presentation parameters.
Install @pathmx/deploy to configure and deploy sites to existing SSH/launchd
servers sharing the project's Git repository:
pmx plugins add deploy
pmx deploy init --host user@server --directory /absolute/checkout
pmx deploy --dry-run
pmx deploy
init saves local target configuration. --dry-run checks prerequisites without
changing the server. Deployment coordinates live writers, backs up durable state,
updates the selected revision, and verifies the restarted site. See
Server deployment for setup, maintenance,
checkpoint coordination, and recovery requirements.
Use bun run pmx jobs list, jobs inspect <id>, and jobs operation <id> to
inspect saved work. jobs drain --limit 32 runs due jobs now and
jobs retry <id> requeues compatible blocked or failed work. With pmx dev or
pmx serve running, both go through that host's worker and its effect policy.
Without a host, add --production to drain using production effect policy; with
a host, --production must match the host's mode. See durable jobs.
When Email is installed, email preview, email send, email list,
email inspect, email retry, and email prune manage messages. Sending captures
by default; email send --live explicitly requests one real submission. See
Email for template arguments and credentials.