Claude
Skills
Sign in
Back

pm-report

Included with Lifetime
$97 forever

Use this skill when the user asks for a "status report", "what changed", "what's stuck", "what shipped", "velocity report", "what's next to pick up", "review prs", "open prs", "ready to merge", "is this project on track", "project health", "are projects at risk", "which projects are off track", or any project status summary that should be persisted as a document or sent as email. **Eight profiles** — movement (default — what changed), stuck (what's blocked), throughput (velocity vs prior), next-up (what's ready), exec (one-pager standup), prs (open-PR review), full (legacy daily/weekly behavior), **project-health** (per-project on-track / at-risk / off-track classification with milestone burndown — for project-tier health questions like "is this project on track" or "which projects are at risk"). Produces Markdown plus HTML and/or PDF; optional handoff to resend-cli for delivery.

Web Devscriptsassets

What this skill does


# PM Report

Generate an actionable, profile-driven status report for the active project. Each profile renders only the sections that answer one operator question — no more "show everything by default." Output formats: Markdown (always), HTML, PDF, or both.

If the user asks for a *briefing* in the conversation (no document, no email) — that is `pm-status`'s job, not this skill. Reports here are intended to be persisted and shared.

## When to use this skill

Trigger phrases grouped by the profile they imply:

- **movement** (default): "what changed", "what shipped", "what got done today/this week", "daily movement"
- **stuck**: "what's stuck", "what's blocked", "what's dragging", "anything stalled"
- **throughput**: "velocity report", "are we on track", "pace this week", "throughput vs last week"
- **next-up**: "what's next", "what's ready to pick up", "what should I grab next"
- **exec**: "standup", "status report", "daily report", "weekly report", "one-pager"
- **prs**: "review prs", "open prs", "what prs need attention", "ready to merge", "waiting on me to review"
- **full**: "everything", "full report", legacy `--kind daily|weekly` without `--profile`

Also fires on the `/pm-report` slash command.

## Profiles

Each profile is a composition of lenses (pure functions in `hooks/lib/report-lenses.js`) plus a bundled template.

- **movement** *(default)* — Answers "what changed in the window?" Renders completions, started/reopened, created, and updated-only buckets plus a per-team movement rollup and per-assignee accountability. Use when the operator wants a record of what moved.
  
  When composing narrative for the **movement** profile, each per-team block carries a derived `taxonomy` (the type-relevant labels that team used in the window) and, when the `other` bucket is non-zero, the labels behind it. Use these to read a team's movement in its own terms — e.g. note when a team's large `other` count is because it files most work under a non-canonical label like `Improvement`. Add at most one interpretive line per notable team; never restate or duplicate the deterministic per-team block.
- **stuck** — Answers "where are we blocked?" Renders newly-stale issues (crossed the threshold inside the window), drifting WIP, unassigned-with-priority, blocked-labeled, and awaiting-info-from-operator buckets, plus a WIP-aging distribution. Use when the operator wants an unblock-list.
- **throughput** — Answers "are we moving faster or slower?" Renders completion-rate compare, cycle-time compare, per-team and per-assignee deltas vs the prior equal-length window, and end-of-window WIP aging. Use when the operator wants a velocity readout.
- **next-up** — Answers "what's ready to pick up?" Renders ready-to-work issues (priority + assignee + template-validated title) plus watchouts (close-to-ready with missing signals) and a compact "stuck on the operator's desk" tail. Use when the operator is planning the next slice of work.
- **exec** — One-pager standup. Renders single-line headlines for movement, stuck, and throughput plus top-N changes / top-N stuck. Use when the operator wants something to paste into a stakeholder update or email.

### `prs`

Reports across **open pull requests** rather than issues. Buckets PRs by funnel stage (draft, no_reviewers, awaiting_review, changes_requested, checks_failing, conflicts, approved_pending, ready_to_merge), shows what's waiting on you (to review / push / merge), flags stale and orphan PRs, and **cross-references the issue `stuck` lens** to surface PRs whose merge would directly unstick blocked work. Requires `pull-prs` (or `prs-sync` verb) to populate the `prs.json` cache first. Needs the `gh` CLI installed and authenticated.

- **full** — Legacy "render everything" behavior. Maps to `daily.md` (kind=daily) or `weekly.md` (kind=weekly). Preserved for back-compat with scheduled reports and existing scripts.

## Profile resolution

The skill picks a profile using this decision tree (first match wins):

1. **Explicit flag** — `--profile <name>` is always honored.
2. **Legacy kind** — `--kind daily|weekly` with no `--profile` resolves to `full` (the legacy templates).
3. **Natural-language match** against the operator message:

| Phrase | Profile |
|---|---|
| "stuck" / "blocked" / "dragging" | `stuck` |
| "shipped" / "what got done" / "what changed" | `movement` |
| "velocity" / "pace" / "on track" / "throughput" | `throughput` |
| "ready" / "what's next" / "pick up" | `next-up` |
| "standup" / "status report" / "daily report" / "weekly report" | `exec` |
| "everything" / "full" | `full` |

4. **Fallback** — `movement`.

If the operator message is ambiguous and the cache is empty (cold start), ask once: "Movement (what changed), Stuck (what needs unblocking), or Throughput (velocity)?"

### Legacy single-slug inputs (still supported)

For back-compat, the original per-slug invocation still works: `--slug <slug> --kind daily|weekly` (without `--profile`) reads the slug's cache + snapshots and renders the legacy daily / weekly templates via the `full` profile. Prefer the profile + scope form for new reports.

## Workflow

### Step 1: Resolve the profile

Apply the decision tree above. If the user passes `--profile`, use it. Otherwise pattern-match the message and fall back to `movement`.

### Step 2: Resolve the scope

One of `workspace:<slug>` (default), `team:<KEY>[+subteams]`, `project:<slug>[+deps[:upstream|downstream]]`, `repo:<org/repo>`, or `all`. Ask if not specified: "Scope this report to workspace / team / project / repo / all?"

### Step 3: Resolve the window

`today` (since UTC midnight), `week` (last 7 days), `month` (last 30 days), or `custom <YYYY-MM-DD> <YYYY-MM-DD>`. Ask if not specified.

### Step 4: Render + run the matching pm-script

Each profile has a bundled `pm-script` that refreshes the cache deterministically (`pull-movement`, `pull-stuck`, `pull-throughput`, `pull-next-up`, `pull-exec`). Render the first ~20 lines of the substituted script and ask "Run this?" before executing — unless the caller passes `--auto-pull` (CI / cron). Skip this step entirely if `pm-status` already synced the workspace this session and the profile doesn't need extra snapshots.

### Step 5: Invoke the generator

```bash
node "$CLAUDE_PLUGIN_ROOT/skills/pm-report/scripts/generate-report.js" \
  --profile <movement|stuck|throughput|next-up|exec|full> \
  --scope "<scope-expression>" \
  --from "<YYYY-MM-DD>" --to "<YYYY-MM-DD>" \
  --format both \
  --out "$HOME/.claude/project-manager/reports/<slug>"
```

Key flags:
- `--profile <name>` — movement | stuck | throughput | next-up | exec | full
- `--kind daily|weekly` — back-compat (without `--profile`, maps to `full`)
- `--scope <expr>` — scope grammar (workspace/team/project/repo/all)
- `--from`, `--to` — explicit window endpoints (overrides `--date`)
- `--operator <login>` — needed by the `needs_info_self` reason in the stuck lens
- `--auto-pull` — skip the "Run this?" gate (CI / cron)
- `--format pdf|html|both|md` — default `both` (always also writes `.md`)
- `--out <dir>` — default `~/.claude/project-manager/reports/<slug>`
- `--template <path>` — override the bundled template
- `--date <YYYY-MM-DD>` — override "today" for testing / backfilling

The script prints JSON describing what it wrote:

```json
{ "ok": true, "profile": "movement", "files": ["...md", "...html", "...pdf"], "comparedTo": { "...": "..." }, "lensesUsed": ["movement","accountability","inProgress"] }
```

### Step 6: Show paths + offer delivery

Read the JSON output and tell the operator where each file landed and what it compared against (so they can spot when a snapshot was missing). Then offer delivery via the `resend-cli` skill — only ask if the project has a `.resend.md` configured or the user mentioned sending. If emailing, hand off the HTML file as the body; do not attach the PDF unless the user asks.

### First-time PDF setup (one-time)

PDF rendering uses `md-to-pdf` (Puppeteer + Chromium). On

Related in Web Dev