@edpaget/rdm
v0.21.0
Published
CLI for managing project roadmaps, phases, and tasks
Downloads
837
Readme
A tool for managing project roadmaps, phases, and tasks as git-tracked markdown files — designed to be driven by your LLM coding assistant.
Work with your assistant to plan and implement large changes in a structured, repeatable way. You only need to allowlist a single CLI tool or MCP server. Plans are stored in a separate repo to keep your codebase free of planning artifacts.
rdm offers CLI, MCP, and REST interfaces.
Installation
# Quick install (Linux x86_64, macOS aarch64) — downloads a signed release binary
curl -fsSL https://github.com/edpaget/rdm/releases/latest/download/install.sh | sh
# Pin a specific release
curl -fsSL https://github.com/edpaget/rdm/releases/download/v0.18.2/install.sh | sh
# Homebrew (macOS)
brew install edpaget/rdm/rdm-cli
# npm / npx (macOS x64/arm64, Linux x64/arm64) — downloads the matching release binary on install
npx -y @edpaget/rdm mcp # start the MCP server (default entry point for MCP clients)
npx -y @edpaget/rdm --help # run any rdm CLI command without installing globally
npm install -g @edpaget/rdm # or install globally so `rdm` is on PATH
# From source
cargo install --path rdm-cliWire it into your coding assistant
For Claude Code, install the plugin — it is the recommended distribution path and needs no per-project file generation:
claude plugin marketplace add edpaget/rdm
claude plugin install rdm@rdmThis installs 11 skills (rdm:roadmap, rdm:do, rdm:dispatch-phase, …) and 2 workflow engines, namespaced so they cannot collide with your own. The skills invoke the rdm binary you installed above via PATH; see Claude Code Plugin Marketplace for overriding that and for the fallback path.
For other assistants, or if you cannot use the plugin marketplace, ask your assistant to run rdm --help and initialize the tool. Tell it whether you want to use the CLI or MCP server so it installs the correct prompts and configuration.
Manual Initialization
Initialize your plan repo:
rdm initBy default, rdm stores data in ~/.local/share/rdm (the XDG data directory). To use a custom location, pass --root:
rdm --root ~/Projects/my-plans initQuick Start
If you initialized using your coding assistant, it should have prompted you to create a project. The examples below show what happens under the hood — you typically won't need to run these manually.
# Create a project
rdm project create fbm --title "Fantasy Baseball Manager"
# Create a roadmap with phases
rdm roadmap create two-way-players --project fbm --title "Two-Way Player Identity"
rdm phase create two-way-players/core-valuation --project fbm --title "Core valuation layer"
rdm phase create two-way-players/keeper-service --project fbm --title "Keeper service threading"
# Track progress
rdm phase update two-way-players/core-valuation --project fbm --status done
rdm roadmap show two-way-players --project fbm
# One-off work items
rdm task create fix-barrel-nulls --project fbm --title "Fix barrel column NULL for 2024" --priority high
rdm task update fix-barrel-nulls --project fbm --status doneAI Agent Integration
rdm is designed to work with AI coding agents. Instead of granting filesystem access to your plan repo, you allowlist the rdm binary or MCP server and the agent reads and writes roadmaps through the CLI.
Claude Code Plugin Marketplace (Recommended)
Install rdm as a Claude Code plugin for automatic skill and workflow discovery:
# Add the marketplace (if not already configured)
claude plugin marketplace add edpaget/rdm
# Install the plugin
claude plugin install rdm@rdmThis installs 11 skills (rdm:roadmap, rdm:dispatch-phase, rdm:do, etc.) and 2 workflow engines, with automatic namespace prefixing and workflow discovery.
The plugin shims resolve the rdm binary at runtime, using the first of these that resolves:
- an explicitly supplied
--rdm-bin <path>; - the
RDM_BINenvironment variable; - a plain
rdmonPATH.
So a normally installed rdm needs no configuration — the flag and env var are overrides for a non-PATH binary (a repo-local build, say). If none resolves, the shim stops with an actionable error rather than guessing a path.
This is the recommended distribution path for downstream consumers.
CLI Agent Config (Fallback)
For users unable to use the plugin marketplace, generate instructions and skill definitions manually:
# Generate CLAUDE.md instructions for a target project
rdm agent-config claude --project fbm > ~/Projects/fbm/.claude/rdm.md
# Generate Claude Code skill definitions (fallback: raw skills emission)
rdm agent-config claude --skills --project fbm --out ~/Projects/fbm
# Or generate AGENTS.md + skills for the Pi coding agent
rdm agent-config pi --skills --project fbm --out ~/Projects/fbmThe raw skills emission (--skills --out <dir>) is a fallback for environments without plugin marketplace access. It emits the same 11 skills and 2 workflow engines to a target directory, but as 13 loose file copies with no collision protection and no namespace prefixing, and you manage workflow discovery yourself. The emitted shims bake in the --project you passed and invoke a bare rdm, so they assume rdm is on PATH; unlike the plugin shims they carry no --rdm-bin/RDM_BIN resolution section.
rdm ships with Claude Code skills covering the full lifecycle: planning (rdm-roadmap), reviewing a plan before implementation begins (rdm-plan-review), implementation and task work (rdm-do), review (rdm-review), acting on document reviews that request changes (rdm-revise) — which works a submitted review comment by comment, applying edits through rdm and landing each with rdm commit, recording per-comment commit provenance until the review is addressed — documentation generation (rdm-document), autonomous roadmap execution (rdm-autopilot) — which drives one roadmap to reviewed unattended (see docs/autonomous-loop.md) — and landing (rdm-land), which integrates a reviewed item into main with linear history and then prunes its worktree (see docs/landing.md). There is also backlog grooming (rdm-backlog), a propose-only pass that reads rdm backlog report and emits a batched, human-reviewable plan of consolidate/merge/retire/archive actions — each paired with the exact rdm command that would carry it out — without mutating the plan repo. The same skill set is emitted for Pi under .pi/skills/.
For Claude Code, --skills --out <dir> also writes a .claude/workflows/ directory alongside .claude/skills/, containing the Claude Code Workflow-tool scripts (rdm-wf-dispatch-phase.js, rdm-wf-review-refute-fix.js) that back the autonomous rdm-autopilot/rdm-dispatch-phase lane. Both scripts are project- and binary-agnostic: they name no rdm executable and no rdm project of their own, taking an optional rdmBin runtime argument (the exact executable to invoke — an explicit value is used verbatim, and omitting it falls back to a plain rdm on PATH) and an optional project applied only to project-scoped subcommands — the emitted skill shims supply both from the --project you passed at emission time. This is Claude-only (Pi has no Workflow-tool runtime) and only applies with --out (not --user, since the scripts are project-scoped).
Plan-review Stop hook (retired)
rdm agent-config claude/pi --hooks — the Claude Code Stop hook / Pi agent_end extension that reprompted the agent while any item carried the needs-plan-review sentinel tag — has been retired now that plan review runs in-flow on the ephemeral implementation-plan lane (rdm-wf-dispatch-phase, rdm-do). The --hooks flag no longer exists.
That in-flow review is a distinct mechanism from the needs-plan-review tag stamped onto persisted roadmaps/phases/tasks by roadmap create / phase create / task create when plan_review is enabled — it reviews an ephemeral plan draft, not the persisted item, and never touches the tag. With the Stop hook gone, clearing needs-plan-review on items created via rdm-roadmap, ad hoc create commands, or rdm-do side-task filing is manual-only: run the rdm-plan-review skill against the item (--roadmap <slug>, --task <slug>, or <roadmap> <phase>), or periodically sweep with rdm search "" --tag needs-plan-review. Active enforcement is tracked as a follow-up (see wire-active-plan-review-tag-gate in the plan repo).
An earlier auto-review Stop hook / Pi extension pair, which reprompted whenever an item was left in needs-review after implementation, was retired for the same reason: the rdm-do, rdm-wf-dispatch-phase, and autopilot finalize paths now actively run the canonical code review on every finalize, so nothing is left unreviewed for a passive net to catch. See docs/autonomous-loop.md.
Headless / unattended runs
To run the worktree loop unattended, drive Pi in a non-interactive mode (pi -p "<prompt>", or --mode json / --mode rpc for structured I/O) backed by a sandbox (OpenShell, Gondolin, or Docker) so the agent can create worktrees and apply changes without an interactive terminal.
MCP Server
For agents that support Model Context Protocol, rdm exposes all operations as MCP tools — projects, roadmaps, phases, tasks, search, worktrees, and document reviews. The review tools (rdm_review_requests, rdm_review_show, rdm_review_address_comment, rdm_review_complete) close the revision loop: an agent discovers submitted change-request reviews, gets each comment with its anchor resolution and the referenced document bodies in one call, applies edits through the update tools (which only stage — landing each with rdm_commit, whose response reports the resulting commit for provenance), and drives the review to addressed:
# Start the MCP server (stdio transport)
rdm mcp
# Generate MCP-oriented agent instructions (references MCP tool names instead of CLI commands)
rdm agent-config --mcp --project fbm --out ~/Projects/fbm
# Generate MCP-aware Claude Code skills + .mcp.json
rdm agent-config claude --mcp --skills --project fbm --out ~/Projects/fbmPi has no native MCP support, so rdm agent-config pi --mcp is rejected with an actionable error. Use rdm agent-config pi --skills (or omit --mcp for the AGENTS.md integration) instead.
Claude Code / Cursor / MCP Registry
Register rdm with Claude Code (uses the published npm package):
# User-scoped (available in every project)
claude mcp add rdm -- npx -y @edpaget/rdm mcp
# Or project-scoped (writes to .mcp.json in the current repo)
claude mcp add --scope project rdm -- npx -y @edpaget/rdm mcpFor Cursor, add the
following to ~/.cursor/mcp.json (or the project-scoped .cursor/mcp.json):
{
"mcpServers": {
"rdm": {
"command": "npx",
"args": ["-y", "@edpaget/rdm", "mcp"]
}
}
}rdm is also published to the MCP Registry
under the canonical name io.github.edpaget/rdm.
Claude Code web sandbox
Run Claude Code web sessions against your plan repo from a source-repo sandbox. A session-start hook installs rdm, clones the plan repo into the sandbox, and points rdm's global config at it. Drop the template into your source repo:
# From a checkout of the rdm repo:
scripts/install-claude-code-web-template.sh /path/to/your/source-repoSee docs/claude-code-web.md for the full setup, required env vars, and troubleshooting.
Core Workflow: Plan, Implement, Done
rdm is built around a three-step cycle for shipping work incrementally.
Plan
Break work into roadmaps, each containing ordered phases. Phase bodies typically include context, implementation steps, and acceptance criteria — everything someone (or an AI agent) needs to start working.
rdm roadmap create search-feature --project fbm --title "Full-Text Search"
rdm phase create search-feature/indexing --project fbm --title "Build search index"
rdm phase create search-feature/query-api --project fbm --title "Query API endpoint"
rdm commit -m "feat(plan): add search-feature roadmap" # land the roadmap + phasesFor one-off work that doesn't warrant a full roadmap, create a task:
rdm task create fix-edge-case --project fbm --title "Handle empty query gracefully"Implement
Work through phases in order. Read the spec, mark it in-progress, and build:
rdm phase show search-feature/indexing --project fbm
rdm phase update search-feature/indexing --project fbm --status in-progress
rdm commit -m "chore(plan): start indexing phase" # land the status changeIf you discover bugs or side-work during implementation, capture them as tasks rather than fixing inline:
rdm task create unicode-tokenizer --project fbm --title "Tokenizer breaks on CJK characters"Done
When you commit the implementation, include a Done: line in the commit message:
feat(search): build inverted index for full-text search
Done: search-feature/indexingInstall the git hooks in your plan repo and they will automatically mark the phase done and record the commit SHA:
rdm hook installThe hooks parse Done: directives for both phases (Done: <roadmap>/<phase>) and tasks (Done: task/<slug>). This creates a traceable link from every completed item back to the commit that shipped it.
Worktrees
rdm worktree manages git worktrees in your project (code) repo — the git repo you invoke rdm from — keyed to plan items. It lets you (or an agent harness) spin up an isolated checkout per roadmap, phase, or task without depending on the harness's own worktree support. These commands operate on the project repo discovered from the current directory, not the plan repo (RDM_ROOT); running them from inside the plan repo is refused.
# Create (or reuse) one worktree per roadmap, shared by its phases — prints the path
rdm worktree add my-roadmap --project fbm
# Create (or reuse) a worktree for a phase — prints the worktree path
rdm worktree add my-roadmap/phase-1-indexing --project fbm
# Phase numbers are resolved against the plan repo
rdm worktree add my-roadmap/1 --project fbm
# Branch from a specific base instead of the current HEAD
rdm worktree add my-roadmap/1 --base main --project fbm
# Worktrees for standalone tasks
rdm worktree add task/fix-edge-case --project fbm
# List rdm-managed worktrees (item · branch · path · dirty)
rdm worktree list
# Remove a worktree by item or path; refuses a dirty tree without --force
rdm worktree remove my-roadmap/phase-1-indexing
rdm worktree remove my-roadmap/phase-1-indexing --delete-branch
rdm worktree remove /path/to/worktree --forceBranch naming: roadmaps use roadmap/<slug>; phases use phase/<roadmap>/<stem>; tasks use task/<slug>.
Location: worktrees are created as siblings of the project repo under <parent>/<repo-name>__worktrees/<branch-with-slashes-as-dashes> (e.g. ../myrepo__worktrees/phase-my-roadmap-phase-1-indexing).
add is idempotent — re-running it for an existing item prints the existing path instead of erroring. Only worktrees created by rdm (tracked via an internal marker file) are listed or removable; remove refuses worktrees it didn't create.
REST API
For programmatic integrations beyond the CLI, rdm serve starts a REST API that mirrors the CLI commands. See docs/rest-api.md for endpoints, content negotiation, and error format.
rdm serve --port 8400Documentation
- File Formats — plan repo structure, YAML frontmatter reference, and field descriptions
- Architecture — crate layout, Store trait, and design overview
- Architectural Principles — the full set of design principles governing the codebase
- REST API — endpoint reference, content negotiation, and error format
- Bootstrap & Init — detailed guide to initializing and configuring a plan repo
Contributing
rdm uses Conventional Commits, TDD, and cargo nextest run for testing. See CLAUDE.md for development practices and build instructions.
Release prerequisites
The release workflow publishes the @edpaget/rdm npm package via
npm trusted publishing (OIDC),
so no long-lived NPM_TOKEN secret is required. Setup is one-time per
package:
- Create the
@edpagetscope on npmjs.com (only needed once for the whole org). - Bootstrap the package: npm requires a Trusted Publisher to point at
an existing package, so the very first release of
@edpaget/rdmhas to be published manually (npm publish --access public ...) or via a one-off token. Subsequent versions go through OIDC. - On the
@edpaget/rdmpackage settings page → Trusted Publishers, add a publisher pointing atedpaget/rdmwith workflow filerelease.yml, environment left blank.
Once that's in place, tagging a release triggers
.github/workflows/release.yml, which dispatches to
.github/workflows/publish-npm-oidc.yml and publishes with
npm publish --provenance using the GitHub-issued OIDC token. The
publish workflow also injects mcpName: io.github.edpaget/rdm into the
published package.json so the MCP Registry can verify ownership.
Submitting to the MCP Registry
The first release that ships with mcpName in package.json unlocks the
MCP Registry
submission. This is a manual, one-time step (subsequent releases only
need to be re-pushed to the registry if server.json changes):
- Install the publisher CLI:
brew install mcp-publisher - Bump
server.jsonso itsversion(and the matchingpackages[].version) tracks the released npm version. - Authenticate with GitHub (interactive OAuth — claims the
io.github.edpagetnamespace):mcp-publisher login github - From the repo root, push
server.jsonto the registry:mcp-publisher publish
License
This project is licensed under the GNU General Public License v3.0.
