This guide is for a maintainer or fork owner setting up pm-dispatch on a new machine.
It assumes you already want to treat this repository as a personal bootstrap, not a public
collaboration portal.
If you want to understand the design shape first, read docs/CONCEPTS.md before continuing.
Before cloning or running anything, confirm the host has:
- Claude Code installed and launched on your machine.
jqonPATH(required by hooks and install checks).- GNU
realpathequivalent onPATH(or a shell that provides equivalent behavior). - Optional: Codex CLI (
codex) if you want the defaultfullinstall profile.
ShellCheck is deliberately not an installation/runtime prerequisite. It is needed only by maintainers or fork owners who run lint or the authoritative full test suite; see CONTRIBUTING.md.
You can verify the minimum tooling quickly:
command -v claude
command -v jq
command -v realpathIf codex is present and later discoverable from your shell, the installer may default to the full profile.
command -v codex && echo "codex detected" || echo "no codex detected"Start from your fork root (or the upstream branch you want to adapt):
git clone <repo-url> ${PM_DISPATCH_REPO}
cd ${PM_DISPATCH_REPO}If you cloned from an existing personal fork, define the placeholder once:
export PM_DISPATCH_REPO="$(pwd)"Use any absolute path for ${PM_DISPATCH_REPO}; that convention is used by several scripts and docs.
Run the installer dry run before applying:
cd ${PM_DISPATCH_REPO}
bash install.sh --dry-runThen apply:
bash install.shinstall.sh has two explicit profiles and one auto-detected mode:
--profile full— wires adapter bash guards (manifest-driven vianeeds_bash_guard). No adapter ships a bash guard today, sofullandminimalcurrently wire the same hook set; the flag is retained for forward compatibility.--profile minimal— skips registering adapter bash guards; other hooks (pm-write-guard, inject-memory, save-rate-limits) stay wired in both profiles.--profileomitted (default) — auto-detects profile fromcommand -v codex.
Auto-detect is a simple presence check:
if command -v codex >/dev/null 2>&1; then
echo "full profile"
else
echo "minimal profile"
fiWhen codex is intentionally absent, you can still run the full stack as a lightweight personal setup using
bash install.sh --profile minimal.
To select a host lifecycle explicitly, repeat --host. A selected non-Claude
host never creates or requires ~/.claude:
bash install.sh --host codex
bash install.sh --host opencode
bash install.sh --host claude --host codexWith no --host, the existing Claude installation remains the compatibility
default. --enable-host <name> is retained as a compatibility form that adds
the named host to that default; do not combine it with explicit --host
selection. The host selection is independent of
--profile, which controls the executor axis. OpenCode installation adds a
native /pm command and a catch-all Bash deny with an allow rule for this
checkout's pmctl; it fails without changing the file when an existing
user-owned permission.bash policy is present. Uninstall the matching
host-owned configuration with the same selector, for example
bash uninstall.sh --host codex.
A Codex-only or OpenCode-only selection deliberately wires only that host's
manifest-owned configuration. It does not install the product pmctl CLI or
Claude dispatch allowlist; use the default Claude-compatible install (or add
--host claude) when those product assets are required.
Run the built-in health check:
bash runtime/bin/doctor.shdoctor.sh checks that claude and jq are on PATH, hooks are wired in
~/.claude/settings.json, the memory directory is present, scripts are
executable, tracked files use LF line endings, and frontmatter passes lint.
Each failing check prints a concrete remediation command. Its --fix mode is
limited to two idempotent, reversible repairs: restoring executable modes on
managed scripts, and stripping stray CR bytes from a CRLF working copy — the
latter only when the file differs from the index by line endings alone, so a
file that also carries local edits is reported, never rewritten.
If you want to see what was linked rather than just whether it is healthy:
readlink -f "$HOME/.claude/commands/pm.md"
readlink -f "$HOME/.claude/agents/project-pm.md"
readlink -f "$HOME/.claude/.pm"For a quick direct-impact iteration check:
bash tests/bin/run-tests.sh --base origin/mainFor the authoritative full regression sweep, run the compatibility entry point outside the PR-gate lifecycle (the complete suite can be long-running):
bash tests/bin/run-all-tests.shIn normal docs-first workflows, passing doctor.sh alone is sufficient before
your first /pm run. If needed, doctor.sh --fix has the narrow scope of
restoring managed-script executable modes and LF line endings only.
pmctl context keeps its repository index alongside the repo at
<repo-root>/.pm-dispatch/ctx/context.db — repo-local by default, created on
your first index run:
pmctl context index "$PM_DISPATCH_REPO"The path is fixed per repo and is not affected by PM_DISPATCH_STATE_ROOT
(that variable governs the state partition, not the context DB). The
.pm-dispatch/ directory is gitignored automatically, so the database file is
never committed. The context indexer also excludes that directory from file
discovery, so generated packs and database artifacts are not self-indexed. See
docs/context-retrieval.md
for the full convention and available subcommands.
After the checks are green, open a Claude Code session in the repo and send a concrete request:
/pm draft a minimal onboarding change plan for this repo and list the exact command sequence to validate it
Expected flow:
/pmcalls theproject-pmsubagent with your request and working context.- PM composes a brief against the dispatch schema.
- If PM chooses codex/Claude execution, it routes through the accepted executor path.
- The brief is run only against the declared file paths.
- The executor returns with concrete outputs and a summary.
In a stable first run, you should see:
- A brief summary that names the edited targets.
- A test/reference plan in the executor report.
- A clean status against the accepted scope.
If you use a non-destructive request for this walkthrough, run:
/pm review the current `/pm` onboarding docs and suggest one follow-up cleanup task
That gives the full PM + dispatch chain without requiring immediate code changes.
After you finish the first /pm cycle, keep these in sync:
docs/CONCEPTS.mddocs/memory-system.mddocs/dispatch-brief.mddocs/executor-contract.mddocs/context-retrieval.md— query the repo index before authoring a briefdocs/pmctl-task.md— full task lifecycle commandsdocs/platform-support.md
If a fork user path differs from yours, keep your edits small and local; this repo is designed to be copied and adapted.