/pm:tracker makes PM aware of an external issue tracker. Once configured, PM shapes the sync instructions in your CLAUDE.md rules block — telling your Claude Code agent which epics need issues created and when to transition them. The engine itself never calls the tracker; your agent does, using whatever tooling you have (an MCP server, the GitHub CLI, a REST client).
Detection
PM detects tracker signals before asking — but it is careful not to over-infer. Hosting a repo on GitHub, GitLab, or Bitbucket is NOT a signal. The mere presence of a remote does not mean your team manages work in that platform’s issue tracker. PM treats the following as real signals that a tracker is in active use:- A connected issue-tracker MCP that is in use —
mcp__jira__*,mcp__linear__*, a GitHub Issues/Projects tool, or similar. - Real issue-key conventions in commit or branch history — for example,
PROJ-123or#42. - An explicit statement in
CLAUDE.mdorREADMEthat “we track work in <X>”.
.conductor/state.json and PROJECT.md.
Configuring a tracker
Use theset-tracker subcommand to record or update tracker settings for the repo:
Re-running
set-tracker merges — only the flags you pass change. The CLAUDE.md rules block is refreshed automatically.
statusIntent mapping
--intent maps PM’s lifecycle statuses to semantic goals, not literal workflow-transition names. Your agent resolves the actual transition using its own tooling at sync time. For example, active:in-progress means “when an epic is active, move its linked issue toward an in-progress state” — PM does not care whether your Jira board calls that transition “Start Progress” or “Begin”.
A fully configured tracker block in state.json looks like this:
Bidirectional mirroring (Jira, Linear, etc.)
For any--system other than github-issues, the CLAUDE.md rules block instructs your agent to:
- Create an issue for any epic that lacks an
externalId, then record the returned key: - Transition the issue toward the
statusIntenttarget each time the epic’s status changes — resolving the real workflow transition with your own tooling. - Link child epics to a parent tracker epic when a hierarchy is involved.
GitHub Issues (inward-only)
--system github-issues is a special, inward-facing shape. Instead of mirroring local epics out to GitHub Issues, it pulls open GitHub Issues in as new untriaged epics during /pm:sync — the same pattern PM uses to auto-register OpenSpec changes found on disk.
/pm:sync, your agent:
- Lists open issues with
gh issue list --repo <repo> --state open --json number,title,url,labels. - Checks whether an epic already has that issue number as its
externalId— if so, skips it. - Registers each new issue as an epic:
If the issue carries a
P0/P1/P2/P3label, use that label’s priority instead of theP2default. add-epicitself rejects a duplicate--external-id(exits non-zero, writes nothing) as a second line of defense against a stale local view producing a duplicate.
github-issues does not auto-create GitHub Issues for local epics. That direction is intentionally omitted to avoid silently creating public issues on your behalf.
Primary + secondary trackers
A repo has exactly one primary tracker — everything above — plus, optionally, one or more secondary trackers. Secondary trackers cover a different case: your real dev tracker is Jira, but you also want to watch a GitHub repo for inbound issues, for example from outside contributors, or from another internal repo publishing cross-project notifications (a service filing a GitHub issue in a downstream repo to flag a breaking change). A secondary tracker gets exactly two behaviors:- Inward pull — open issues become untriaged epics, the same shape as the
github-issuesinward sync above, but deduped byexternalUrl(globally unique) rather than bareexternalId(only unique within one tracker/repo — two secondary trackers can each have an issue numbered#42without colliding). - Completion status writeback — when an epic sourced from a secondary tracker reaches
archived, your agent closes the linked issue there too. This is new: even the inward-onlygithub-issuescase above never did this before.
--system plus --repo or --project. Re-running set-tracker --role secondary with a matching system + repo/project merges into the existing entry instead of adding a duplicate. --remove against a key with no match exits non-zero and changes nothing.
Once configured, the CLAUDE.md rules block gains one “Secondary tracker sync” section per entry, in addition to — never instead of — the primary tracker’s own section.
Resyncing after completion
Whenever an inward-pull-capable tracker is configured — agithub-issues primary, or any secondary tracker — the rules block also gains a “Sync after completing tracker-linked work” section: after your agent closes or transitions a tracker-linked issue as part of completing an epic, it re-syncs with your tracker(s) (/pm:sync) right away, since it’s already doing tracker I/O for that epic. The instruction is phrased tracker-count-agnostic — “re-sync with your tracker(s)” — so it reads correctly whether a repo has one tracker configured or several.
The session briefing mirrors this with a one-line, non-blocking nudge whenever any tracker is configured (“N tracker(s) configured — consider /pm:sync this session”). This is only ever a reminder; PM never runs a sync itself, and there’s no lastSyncedAt tracking behind it — just a prompt for your agent to decide whether it’s worth the round trip.
TRACKER SYNC briefing line
In the session briefing, theTRACKER SYNC line lists only epics with an active status that still lack an externalId. PM never fabricates transition state — it cannot see the tracker’s current workflow position and will not guess at it.
Tracker awareness is additive. The conductor always tracks everything locally. A tracker only adds an external mirror — saying no to a tracker prompt changes nothing about local tracking, issue counts, or epic statuses.

