> ## Documentation Index
> Fetch the complete documentation index at: https://onvex-ai-admin-mcp-release-0-24-0-7b1e713.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# /pm:tracker — Connect an External Tracker to Your Repo

> Mirror epics to Jira, Linear, GitHub Issues, or any tracker. PM shapes the sync instructions; your agent executes them using your existing tooling.

`/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-123` or `#42`.
* An explicit statement in `CLAUDE.md` or `README` that "we track work in \<X>".

When a signal is found, PM offers the connection as a choice — it never assumes. Saying no changes nothing about local tracking; the conductor still records every epic, status, priority, and story in `.conductor/state.json` and `PROJECT.md`.

## Configuring a tracker

Use the `set-tracker` subcommand to record or update tracker settings for the repo:

```bash theme={null}
conductor.mjs set-tracker \
  --system jira \
  --instance your-company \
  --project PROJ \
  --mechanism mcp \
  --intent active:in-progress \
  --intent paused:todo \
  --intent archived:done
```

| Flag          | Description                                                                                        |
| ------------- | -------------------------------------------------------------------------------------------------- |
| `--system`    | Any string identifying the tracker — `jira`, `linear`, `github-issues`, `gitlab`, etc.             |
| `--instance`  | Your tracker's hostname or workspace slug (e.g., `your-company` for `your-company.atlassian.net`). |
| `--project`   | The project key your epics belong to, such as `PROJ` or `JOB`.                                     |
| `--mechanism` | How your agent calls the tracker — `mcp`, `cli`, `api`, or any other label.                        |
| `--intent`    | Repeatable. Maps a PM lifecycle status to a semantic tracker target (see below).                   |

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:

```json theme={null}
{
  "tracker": {
    "system": "jira",
    "instance": "your-company",
    "project": "PROJ",
    "mechanism": "mcp",
    "statusIntent": {
      "active": "in-progress",
      "paused": "todo",
      "archived": "done"
    }
  }
}
```

## Bidirectional mirroring (Jira, Linear, etc.)

For any `--system` other than `github-issues`, the `CLAUDE.md` rules block instructs your agent to:

1. **Create an issue** for any epic that lacks an `externalId`, then record the returned key:
   ```bash theme={null}
   conductor.mjs update-epic <id> --external-id PROJ-123 --external-url https://...
   ```
2. **Transition the issue** toward the `statusIntent` target each time the epic's status changes — resolving the real workflow transition with your own tooling.
3. **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.

```bash theme={null}
conductor.mjs set-tracker --system github-issues --repo owner/name
```

During `/pm:sync`, your agent:

1. Lists open issues with `gh issue list --repo <repo> --state open --json number,title,url,labels`.
2. Checks whether an epic already has that issue number as its `externalId` — if so, skips it.
3. Registers each new issue as an epic:
   ```bash theme={null}
   conductor.mjs add-epic --status untriaged \
     --external-id <issue-number> \
     --external-url <issue-url> \
     --lane claude-code \
     --title "<issue-title>" \
     --priority P2
   ```
   If the issue carries a `P0`/`P1`/`P2`/`P3` label, use that label's priority instead of the `P2` default.
4. `add-epic` itself 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:

1. **Inward pull** — open issues become untriaged epics, the same shape as the `github-issues` inward sync above, but deduped by `externalUrl` (globally unique) rather than bare `externalId` (only unique within one tracker/repo — two secondary trackers can each have an issue numbered `#42` without colliding).
2. **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-only `github-issues` case above never did this before.

A secondary tracker **never** gets outward-created issues. That direction stays exclusive to the primary tracker.

```bash theme={null}
# Add a secondary tracker
conductor.mjs set-tracker --role secondary --system github-issues --repo acme/market-intelligence

# A repo can have more than one
conductor.mjs set-tracker --role secondary --system github-issues --repo acme/risk-engine

# Remove one that's gone stale
conductor.mjs set-tracker --role secondary --system github-issues --repo acme/decommissioned-repo --remove
```

Identify a secondary entry the same way you'd identify the primary tracker — `--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 — a `github-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, the `TRACKER 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.

<Info>
  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.
</Info>
