Plugin configuration

Configure a reusable Plugin for each project. Package a greeting command and set its options to print Welcome.

Define a configurable package

Start with a working PathMX project.

A package can export a schema-validated factory using definePlugin. Core reads its options from package.json under pathmx.plugins[packageName], validates them, and constructs an ordinary Plugin. Options are inferred from the schema, including defaults.

Create a sibling directory named greeting beside your project. In that directory, create package.json:

{
  "name": "@example/greeting",
  "version": "1.0.0",
  "type": "module",
  "exports": { ".": "./plugin.ts" },
  "pathmx": { "plugin": "." },
  "peerDependencies": { "@pathmx/core": "^0.6.0" },
  "dependencies": { "zod": "^4.4.3" }
}

The exports entry exposes the factory; pathmx.plugin identifies that export as the package Plugin. Create greeting/plugin.ts:

import { definePlugin } from "@pathmx/core"
import * as z from "zod/mini"

export default definePlugin({
  config: z.strictObject({
    label: z._default(z.string(), "Hello"),
  }),
  create(config) {
    return {
      id: "greeting",
      commands(group) {
        group.command("hello").action(() => console.log(config.label))
      },
    }
  },
})

Install, configure, and run

From your consuming project root, install the local package:

bun add ../greeting

Add its activation and options to your project's package.json, preserving the existing dependencies and scripts:

{
  "pathmx": {
    "plugins": {
      "@example/greeting": { "label": "Welcome" }
    }
  }
}

Run the command from that project root:

bun run pmx greeting hello

It prints Welcome. Change label to change the greeting; use {} for the default Hello. A number instead of a string reports the invalid manifest option path.

Configure in a repository Plugin

The same exported factory is callable in plugins/greeting.plugin.ts:

import GreetingPlugin from "@example/greeting"
export default GreetingPlugin({ label: "Welcome" })

Both paths validate the options. Calling without arguments validates {}; required options still fail. Direct overrides do not merge manifest settings automatically. Ordinary Plugins and presets without a configuration schema accept only {}. A configured factory's create(config) may return a Plugin, a factory, or an ordered Plugin preset. For example, Analytics composes its collector and page Event namespace through the same configured factory:

import Analytics from "@pathmx/analytics"

export default Analytics({ retainDays: 90, actors: false })

Save this as plugins/analytics.plugin.ts when configuring Analytics programmatically; choose either this entrypoint or its manifest activation.

Manifest options are JSON data. Runtime services and callbacks belong in programmatic composition. Configuration is resolved during construction and is not a mutable global registry. Browser publication currently rejects nonempty manifest options rather than implicitly publishing them or reconstructing different defaults. For a browser publication, omit this package from pathmx.plugins and use the repository Plugin above to explicitly compose its options. Keep it installed as a dependency. Repository Plugin code and its options are bundled for the browser, so include only public values and browser-compatible behavior; credentials and server-only services stay on the server.