Claude
Skills
Sign in
Back

pm-issues

Included with Lifetime
$97 forever

Use this skill when creating, updating, or closing **an issue** (a bug, feature, task, or spike) in Linear or GitHub; when the user describes a specific untracked **issue** that should be filed; when drafting issue content; or when the user says "create an issue", "log this issue in Linear", "add this issue to Linear", "open a github issue", "file an issue", "create issue

Productivity

What this skill does


# PM Issue Management

## Usage

```
/pm-issues create|update|close  [<issue-id>] [flags…]
```

- `create` — file a new issue via `pm-issue.js create` (needs `--tag`, `--title`, `--draft-file`, `--exec-mode hitl|afk`; optional `--priority 1-4`, `--assignee`, `--parent`, `--project`, `--milestone`, `--dry-run`; gated by the create-gate / template+label validation).
- `update <issue-id>` — change labels/fields/comment via `pm-issue.js update --id <id>` (`--add-label`, `--remove-label`, `--status`, `--assignee`, `--priority`, `--project`, `--milestone`, `--parent`, `--comment`, `--dry-run`). All Linear label writes route through this NTH-511-safe `update` verb — it fetches existing labels and merges add/remove rather than replacing the set.
- `close <issue-id>` — close/cancel (Linear via web UI / PR `Closes <ID>`; GitHub via `gh issue close --reason completed|"not planned"`).
- `<issue-id>` *(issue key e.g. `NTH-12` / GitHub `#123`, required for `update`/`close`)*.

Also: `relate --from --to --type duplicate|related` (link issues) and `dedup-check --slug --draft` (pre-create duplicate scan).

## Listing issues across a scope (v0.21.0+)

When the user asks "what's open in team:X" / "show me everything for project:Y+deps" / "list all open NTH issues", run `scope-briefing` against the workspace cache instead of the legacy per-slug briefing:

```bash
node "$CLAUDE_PLUGIN_ROOT/hooks/bin/pm-cache.js" scope-briefing --scope "<expr>"
```

The returned `issues` array carries every issue matching the scope (filtered by team_key / project_slug predicates), already merged across the touched workspaces. Format it as a table with ID / title / status / assignee / age.

Writes (create / update / close) stay single-issue — scope is for read views only. The create/update/close instructions below are unchanged.

Create, update, and close issues with consistent, clean formatting. Routes by the project's `issue_tracker` field in `<repo>/.claude/pm/project.json`:

- `issue_tracker: "linear"` → Linear GraphQL API (requires `LINEAR_API_KEY` or `project.local.json`)
- `issue_tracker: "github"` → `gh` CLI

Read the active project's tracker before composing — the templates and workflow are the same, only the transport differs.

## Upstream: pm-spec

For spec-driven initiatives (where the user has a markdown spec, brainstorming output, Linear doc, or GitHub issue body and wants reviewers to weigh in *before* the tracker entry exists), the **`pm-spec`** skill is the natural upstream. pm-spec turns the spec into a playground, captures reviewer choices, and writes a `## Settled values from playground` appendix to the spec. By the time the spec lands here, the description includes both the user's intent and the reviewer-confirmed choices — file it directly.

After this skill creates the tracker entry, the operator should run `pm-spec promote --slug <X> --to-id <ID>` to move the playground from `docs/pm/_drafts/` to `docs/pm/<id>/` so the artifact is filed under the same ID as the tracker entry.

## Issue Templates

Templates live in the **`pm-templates`** skill — a tag-keyed registry. Canonical location is the in-repo `<repo>/.claude/pm/templates/`; plugin defaults are the only fallback. Defaults ship with `bug`, `feature`, `task`, and `spike`; projects with an in-repo manifest can drop tags or add new ones.

Resolution (do not inline the templates here):

```bash
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)

# 1. Resolve which manifest is active (in-repo fully replaces plugin if present)
if [ -f "$REPO_ROOT/.claude/pm/templates/_manifest.json" ]; then
  MANIFEST="$REPO_ROOT/.claude/pm/templates/_manifest.json"
else
  MANIFEST="${CLAUDE_PLUGIN_ROOT}/skills/pm-templates/templates/_manifest.json"
fi
cat "$MANIFEST"

# 2. Resolve the body for a given tag (in-repo wins, plugin default falls through)
TAG=bug   # or whichever tag the manifest defines
for path in \
  "$REPO_ROOT/.claude/pm/templates/${TAG}.md" \
  "${CLAUDE_PLUGIN_ROOT}/skills/pm-templates/templates/${TAG}.md"
do
  [ -f "$path" ] && cat "$path" && break
done
```

If a project asks for a tag not in the active manifest, do not invent a generic template — surface the unknown tag and offer to register it via `pm-templates` (which will edit the in-repo manifest if one exists, or bootstrap one from the plugin defaults).

## Conventions

If `<repo>/.claude/pm/conventions.md` exists, load it before drafting (see `pm-conventions`). The relevant sections for this skill are `## Issue titles` and `## Issue labels`. Apply rules over the plugin's baked-in heuristics when they differ; when applying a rule changes the output materially, mention it in your draft summary so the operator sees the rule firing.

## Creating an Issue

### Step 1: Classify the issue type
Apply `pm-templates`' classifier — explicit `[tag]` prefix in the title → tracker label match → inferred from body. If inferred, surface that to the operator and confirm before treating it as classified.

### Step 2: Draft content using the resolved template
Fill in the template body resolved above. Ask clarifying questions only if the problem statement or acceptance criteria are unclear.

**Quality checklist before creating:**
- [ ] Problem statement is one sentence, specific, and includes impact
- [ ] Acceptance criteria are testable and unambiguous
- [ ] No vague language ("improve", "enhance", "handle edge cases" without specifics)
- [ ] Issue is scoped to one PR's worth of work — if it needs 2+ PRs, decompose into a parent with sub-issues

**Scoping rule:** Each issue should be completable in a single PR. If the user describes a large feature (e.g., "add auth system"), suggest decomposing it into a parent issue with sub-issues (e.g., "add middleware", "add token refresh", "add logout"). The parent issue needs no PR — it closes when all sub-issues close.

### Step 2b: Tag HITL or AFK

Every issue carries one of two execution-mode labels:

- **`hitl`** (human-in-the-loop) — the work needs a human at the wheel: design decisions, manual verification, UX judgment, decisions that can't be tested mechanically.
- **`afk`** (away-from-keyboard) — the work is well-enough specified that an agent can grind through it end-to-end: refactors with passing tests, dep bumps, docs cleanup, mechanical migrations.

**Don't skip this — it's a load-bearing distinction.** When the plugin is used to feed work to agents, the difference between "this needs me" and "this can run while I sleep" is the difference between productive parallelism and shipping bad code.

**Default from the manifest hint.** Read `hitl_default_hint` from the tag's manifest entry: most `bug`/`feature`/`spike` issues default to `hitl`; `task` defaults to `afk`. Pre-fill that as the suggestion, then ask the operator:

> "This `<tag>` will be filed as **HITL** by default — agent will draft, but you'll be in the loop. Confirm or switch to AFK?"

The operator's answer becomes a label applied at create time alongside the type-tag label.

### Step 3: Validate and create — `pm-issue.js create`

All issue creation funnels through one verb. **Do not call `linear issue create`, `gh issue create`, or the `save_issue` MCP tool directly** — `pm-issue.js create` validates the draft against the tag's template and labels before it writes, and is the only sanctioned create path. The verb resolves the tracker, team, and project from `.claude/pm/project.json`, so those are never passed as flags.

Team selection goes through the **shared team resolver** (`hooks/lib/team-resolver.js`):
- Explicit `--team` in the request → use it.
- Otherwise → fall back to `.linear.toml` `team_id` (via `linear_team_key` in `project.json`).

This is the same resolver the project-tier skills use, so any audit / convention
that applies to one applies to the other.

1. Write the filled template body to a temp file:

   ```bash
   DRAFT=$(mktemp --suffix=.md)
   cat > "$DRAFT" <<'EOF'
   <filled template body — every required section, real content, no placeho

Related in Productivity