pm-team
Use this skill when the user says "sync the team", "who's on the team", "show the roster", "set my skills", "/pm-team", or asks about team members, member skills, or assignee recommendations. Manages the team roster — Linear-synced identity (gitignored cache) paired with a curated checked-in team.md of handle + skills + owns + aliases — merged at read time by handle. The roster is the data source for pm-organize assignee recommendations and pm-notes speaker matching.
What this skill does
# PM Team
The team roster is split across two storage locations that are merged at read time by handle.
- **Curated file (`<repo>/.claude/pm/team.md`, checked in):** non-PII — GitHub/Linear handle, skills, proficiency buckets, owned workstreams, and display aliases. This file is safe to commit.
- **Synced cache (`~/.claude/project-manager/cache/<slug>/team.json`, gitignored):** identity pulled from Linear — name, status, and the userId used for assignee mutations. This file is never committed.
The merge key is `handle` (case-insensitive). Members present in both halves are unified; members present only in the cache are surfaced with empty skill fields; curated handles with no cache match generate an `unmatchedHandles` warning.
## Usage
```
/pm-team sync
/pm-team show
/pm-team edit @handle
```
- **sync** — pull current workspace members from Linear and write them into the per-slug cache.
- **show** — merge the curated file with the cache and render a table of every member with warnings for any mismatches.
- **edit @handle** — open (or create) the curated entry for a handle, update its skill/owns/aliases bullets from operator input, preview the diff, and confirm before writing.
## Storage
### Curated file — `<repo>/.claude/pm/team.md`
Checked in alongside `project.json` and `conventions.md`. Contains only non-PII fields:
```markdown
# Team
## @scoussens
- skills: frontend, auth, billing
- owns: ws:billing, src/auth
- aliases: Seth, SC
## @jdoe
- strong: postgres, migrations
- familiar: frontend
- owns: ws:data
- aliases: John, JD
```
Each `## @handle` section opens a member entry. Bullet lines `- <field>: <comma-separated list>` populate the field. Recognised fields:
| Field | Meaning |
|---|---|
| `skills` | Flat skill list |
| `strong` | Skills the member is strong in (coarse proficiency — pm-proficiency writes these) |
| `familiar` | Skills the member is familiar with |
| `owns` | Owned workstreams or path prefixes used for scoring by pm-organize |
| `aliases` | Display names used by pm-notes speaker matching |
All fields are optional. A member block with no bullets is valid.
**Never put email addresses in team.md.** Email is an identity field that belongs only in the synced cache. If a line in team.md contains what looks like an email, the skill must reject it.
### Synced cache — `~/.claude/project-manager/cache/<slug>/team.json`
Gitignored runtime state written by `pm-cache.js team-sync`. Schema:
```json
{
"version": "<cache-version>",
"syncedAt": "<ISO-8601 timestamp>",
"members": [
{ "handle": "scoussens", "name": "Seth Coussens", "status": "active", "userId": "u1" }
]
}
```
The `members` array contains identity fields sourced from the tracker. This file is never committed; it lives in the user-home cache directory only.
## sync
Resolve the active slug from `project.json`, then run:
```bash
node "$CLAUDE_PLUGIN_ROOT/hooks/bin/pm-cache.js" team-sync \
--slug <slug> --provider linear
```
This query runs against `api.linear.app/graphql` using `LINEAR_API_KEY`. It paginates through all workspace users and writes `team.json` into the per-slug cache directory.
**Linear only.** If the active project uses GitHub as its tracker, stop and tell the operator: team-sync is Linear-only; GitHub does not expose a workspace-members API via the plugin's current GraphQL transport.
After writing, print the member count and `syncedAt` timestamp so the operator can confirm the sync completed.
## show
Read both halves and merge them via the roster library. Render a table of every member with columns: handle · name · status · skills · owns. Surface any `unmatchedHandles` (curated handles with no cache identity) and `unmappedMembers` (cache members not in team.md) as warnings below the table.
Use this one-liner to produce the merged JSON from Bash:
```bash
node -e '
const fs = require("fs");
const r = require(process.env.CLAUDE_PLUGIN_ROOT + "/hooks/lib/team-roster.js");
const cs = require(process.env.CLAUDE_PLUGIN_ROOT + "/hooks/lib/cache-store.js");
const slug = process.argv[1];
const teamMdPath = process.argv[2];
const curated = r.parseTeamMd(fs.existsSync(teamMdPath) ? fs.readFileSync(teamMdPath, "utf8") : "");
const cache = cs.readTeam(slug) || { members: [] };
const { roster, warnings } = r.mergeRoster(curated, cache.members);
process.stdout.write(JSON.stringify({ roster, warnings }, null, 2));
' "<slug>" "<repo>/.claude/pm/team.md"
```
Replace `<slug>` with the active project slug and `<repo>` with the repo root path (from `git rev-parse --show-toplevel`).
If the cache has never been synced (`team.json` missing), render a table from the curated file only and note that `sync` should be run to add identity data.
## edit
1. Resolve the curated file path: `<repo>/.claude/pm/team.md`.
2. If the file does not exist, offer to create it with an empty `# Team` header.
3. Locate the `## @<handle>` section. If it is absent, append a new block at the end of the file.
4. Parse the operator's requested changes — new skills, removed skills, updated owns or aliases.
5. Preview the diff against the current file content.
6. Ask the operator to confirm before writing.
7. Write the updated block.
Reiterate before writing: **never write email addresses into team.md.** If the operator's input contains an email-shaped string, reject it and ask them to use only the non-PII fields (skills, owns, aliases).
## What this skill does NOT do
- **Does not estimate skills from history** — that is pm-proficiency (a future skill). This skill only reads what the operator explicitly writes in team.md.
- **Does not assign issues** — that is pm-organize. This skill provides the roster data; pm-organize calls `rankAssignees` to score candidates.
- **Does not write identity fields (name, email, status, userId) into team.md** — those fields live only in the synced cache. Edits to team.md are curated, non-PII information only.
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.