Project Capabilities - inventory what is installed, generate the awareness rule
Every project trims the stack differently - skills commented out of the manifest, MCPs dropped (memory in a standalone project, angular-cli outside Angular), seats it never installed. A predefined list would name capabilities the project does not have; this skill reads the REAL inventory and generates the rule from it, so every session knows exactly what this project can do - and never gets steered at a capability that is not there.
The run - inventory, then generate
1. INVENTORY - read what is actually on disk
- Skills: Glob
.claude/skills/*/SKILL.md, read each frontmatter - collectname, the first sentence ofdescription, and whetherdisable-model-invocation: true(those are the slash-only orchestration skills; the rest self-trigger and need no listing - one deliberate exception:project-architecture-analyzercarries no flag so the architecture loop can invoke it, yet it is still an orchestration skill - list it with that set, marked model-invocable-by-design). - Seats: Glob
.claude/agents/*.md- collect the names (the dispatch surface; their own descriptions say when each applies). - MCP servers: read
.mcp.json- the registered server names. - Plugins: best-effort
claude plugin listvia Bash; if the CLI is absent, omit the plugins line rather than guess.
Inventory only - nothing is judged, nothing is read beyond frontmatter and config. No dispatch; the whole run is in-session and cheap. Any Bash in this step uses absolute paths or a subshell ((cd .claude && ...)) - a bare cd persists into the session's later commands (measured: an inventory's bare cd .claude left the shell there for ~7 minutes of follow-on commands until the user redirected).
2. GENERATE - write .claude/rules/baseline-project-agent-capabilities.md
A valid PATHLESS rule (frontmatter with a description: marking it generated, NO paths:), regenerated WHOLESALE each run - it is fully derived, so no upsert, no hand edits to preserve. Wholesale is mechanical, not a mood: DELETE the existing rule file first, then write the new one from scratch - an edit-in-place keeps stale policy wording the skill has since changed (measured: an upsert run silently missed a new usage-policy bullet). This skill was renamed from project-capabilities: when a legacy .claude/rules/baseline-project-capabilities.md exists, delete it in the same run - this rule supersedes it, and nothing else ever prunes generated rules. Keep it lean (always-on tokens are paid every session and subagent); the shape:
---
description: Project capabilities awareness - generated by /project-agent-capabilities; edit via a re-run, not by hand.
---
# This project's capabilities
## Usage policy (fixed - stamped verbatim, every run)
- Load a skill for the work at hand - a file you're about to edit, a command you're about
to run, a diff you're about to show - never to answer a question. Over-loading a simple
turn is the failure to avoid.
- One home per rule: route in the project's CLAUDE.md only what an auto-injected
description does not already cover. Path-scoped rules own per-file-type routing; hooks
own deterministic gates and announce their own blocks - add a new gate as a hook, not prose.
- Subagent dispatch is explicit, never automatic: a user @agent-<name> mention, an
orchestration skill routing to it, or a path-scoped repair-loop rule naming its resolver.
Never self-delegate off a description match. When a task calls for multi-agent work,
suggest the matching orchestration skill from the inventory below - never one this
project does not carry.
- Memory recall is historical, not current: the assistant's per-project auto-memory
persists across installs and roster changes. Validate any seat, skill, or command a
recalled memory names against this rule's inventory before acting on it - a recall
can name a capability this project no longer carries.
- A slash-only skill or plugin command (`disable-model-invocation` - the ones listed
below) is the USER's to type. The harness BLOCKS the Skill call, so never attempt one,
and never spend the turn explaining that you cannot or weighing whether to: name the
command, say in one line what it will do, hand the turn back.
- A deliberate orchestration skill (a capture, a quality loop, a build flow) starts in a
fresh session when this one already carries another skill run's history. This is
MECHANIZED, not advice: `guard-fresh-session-start.js` blocks the Skill call past the
per-tier trigger (150,000 tokens on a 200k window, 400,000 above it) and the block is answered
with one AskUserQuestion (fresh session, recommended, ending the turn with the resume
block - or continue here with the cost stated). Do not restate the rule as a reminder to
'name the route' - the prose form of it lost in 4 of 4 audited sessions, one of which
named the route and continued anyway to 380k per message where the same step cost 134k
run fresh.
- Every doc the assistant creates lands under the docs root (`<docs-path>`), in its owned
folder: `architecture/`, `test-coverage/`, `loops/` - and `related-context/` for anything
tied to a sibling repo (the orientation doc `related-context/PROJECT-RELATED-CONTEXT.md`
plus cross-repo plans, change requests, issue notes, run recipes; look there before
re-deriving sibling state). A doc outside the root takes the user's approval, asked
first - never silently.
## Orchestration skills (slash-only - invisible until invoked)
<one line per detected disable-model-invocation skill: /name - the first sentence of its description>
## Subagent seats
<one line: the installed seat names, comma-separated - dispatch is explicit only (@agent-, an
orchestration skill, or a repair-loop rule); each seat's description says when it applies>
## MCP routing
<one row per REGISTERED server only, from the house routing map below - a server absent from
.mcp.json gets no row, and an unknown server gets its name + 'routing: see project docs'>
The house routing map the MCP rows are stamped from (only for servers actually present):
serena- default symbol navigator + symbol-level editor;find_symbol/find_referencing_symbolsbefore any whole-file Read; also holds the per-project handoff memory (.serena/memories/).context7- up-to-date docs for any API you don't own; resolve + query before writing against a third-party or version-sensitive surface, never from recall.memory- cross-project recall only; search when this project's context is thin, store significant cross-project outcomes at task end.playwright- drive a browser for visual checks / large HTML reports - don't text-read them. Screenshots: omitfilename(auto-names land in the registered output dir,.playwright/output/), or prefix an explicit name with.playwright/output/- the server resolves explicit filenames against the repo ROOT, so a bare name litters the repo. Readback discipline: verify UI state viabrowser_snapshot/browser_evaluate(DOM assertions), or atarget-scoped screenshot for a localized visual check - a full-page PNG Read is for the FINAL accepted state only, never the iteration loop (measured: two sessions Read ~260k tokens of full-page PNGs while iterating styling, then re-paid them as cache-read every turn after; the evaluate/snapshot sessions verified the same class of change for under 10k each, and a target-scoped read cost 0.6k where the full page cost 22k).angular-cli- the framework CLI's own docs / commands.chrome-devtools/appium-mcp- browser / native-mobile debug, only for those targets.sentry- production error monitoring; pull the reported issue / event detail before diagnosing a production error, never from the stack trace alone.- an issue-tracker connector - tracker read-write; ticket skills write the content, the connector files it - confirm before filing.
The usage-policy section is the house skill/agent policy's ONE home - it ships verbatim from this skill (a policy wording change lands here and reaches projects on their next re-run). Like every generated baseline-project-*.md rule it stays out of the installer's fetch manifest, so a stack update cannot overwrite it.
3. REPORT
Confirm the rule (created/refreshed) and the counts per section (orchestration skills / seats / MCP servers / plugins). When this run was NOT the session's first act - other skill runs or real work already sit in context - say plainly that the just-written rule cannot protect THIS session (an always-on rule loads at session start, not retroactively) and that its fresh-session-per-orchestration-run guidance starts applying at the next /clear; recommend the fresh session before the next deliberate skill by name (measured: a session wrote the rule at minute 2, then chained three more orchestration runs the rule's own text warns against, every context spike landing above 320k - the warning existed only in a file the session never re-read). Flag anything odd worth the user's eye: a slash-only skill whose seats are not installed, an MCP registered but its native deps known-heavy (chrome-devtools, appium-mcp), a seat family with no matching convention rule. State observed facts plainly ('typescript-lsp: listed disabled') - never assert WHY something is installed or disabled without checking the per-project plugin records first: claude plugin list is machine-global, and install-scope causation inferred from it is the measured failure (a 'rides the stack closure, inert' claim was confidently wrong - the plugin belonged to a sibling repo - and cost a user challenge plus 5 corrective calls). The rule is a committed file - it ships with the repo.
Don't game it
The rule lists what the inventory proved, nothing else - no capability is assumed from the house defaults, no row survives for a server or skill the project dropped, and an unreadable source (a malformed frontmatter, a missing .mcp.json) is reported as unreadable, not filled from memory. If the inventory looks wrong (an empty skills dir in a stack-installed project), say so and stop rather than generate an empty rule over a good one.