🧠 Add brain-dump docs for skill adaptation
Add exploratory and design docs for porting dirigent skills to reliquary, including: - Explore port options for the gitea skill (in-plugin vs vendored) - Document activation mechanics across Claude Code and cross-tools - Include an orchestration comparison between dirigent and reliquary approaches - Add research on glob negation and flag-file activation patterns - Create uv-detection goals and skill-engines cross-tool reports - Provide a research plan for future porting work and risk notes
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# Skill activation mechanics in Claude Code
|
||||
|
||||
Date: 2026-05-11
|
||||
Scope: How Claude Code decides when to activate a plugin skill, with focus on file-presence / glob triggers and negation.
|
||||
|
||||
## Bottom line for the flag-file design
|
||||
|
||||
The user's design — sibling skills selected by which flag-files are present, with one skill keyed on "pyproject.toml AND NOT (Justfile|Makefile|mise.toml)" — is **partially supported, with no native negation**.
|
||||
|
||||
- File-glob activation IS a documented feature: SKILL.md frontmatter accepts a `paths:` field (glob patterns) that limits when Claude auto-loads the skill. So "activate only when pyproject.toml is present in the working file set" is expressible.
|
||||
- Glob negation (`!Justfile`, `!**/Makefile`) is **not documented and not known to work**. The `paths:` syntax is the same as `.claude/rules/` path-specific rules, which document positive patterns and brace expansion only — no exclude/negate operator.
|
||||
- Activation is path-driven, not literally "file-exists-in-repo" driven: `paths` triggers when Claude is *working with* (reading/writing) a matching file in this turn, not at session start based on repo contents. This is an important distinction for the flag-file model.
|
||||
- There is no priority / specificity / tie-break field. Ordering is left to the model.
|
||||
|
||||
Workarounds for the "bare pyproject" case:
|
||||
1. Encode negation in the `description` text ("Use only when there is no Justfile, Makefile, or mise.toml") and rely on the model. Unreliable but cheap.
|
||||
2. Use a single skill with `paths: ["pyproject.toml", "Justfile", "Makefile", "mise.toml"]` and let the SKILL.md body branch on what it finds (via dynamic context injection `` !`ls` ``). This consolidates the decision into one skill body and is the most robust option today.
|
||||
3. Wrap activation in a hook (`InstructionsLoaded` / SessionStart) that injects different CLAUDE.md content based on flag files. Hooks have full shell access, so arbitrary boolean logic is trivial — but this is hook-land, not skill-land.
|
||||
|
||||
## Question-by-question findings
|
||||
|
||||
### 1. Activation mechanism
|
||||
|
||||
Activation is primarily model-driven from `description`, **and** there is one declarative file-trigger field: `paths`.
|
||||
|
||||
From the official frontmatter reference table on the Skills docs page:
|
||||
|
||||
> **`paths`** — Glob patterns that limit when this skill is activated. Accepts a comma-separated string or a YAML list. When set, Claude loads the skill automatically only when working with files matching the patterns. Uses the same format as path-specific rules.
|
||||
|
||||
So in the default case (no `paths`), the model decides based on the description that lives in the system prompt. With `paths` set, automatic loading is gated by glob match on the files Claude is working with.
|
||||
|
||||
`allowed-tools` is a permission/pre-approval field, not an activation field — it only affects what tools the skill may use once active. `disable-model-invocation: true` disables auto-activation entirely (only the user can `/invoke` it). `user-invocable: false` does the inverse (only the model can invoke it, hidden from `/` menu).
|
||||
|
||||
### 2. Glob negation
|
||||
|
||||
**No documented negation syntax.** The `paths` field uses the same glob format as `.claude/rules/` path-specific rules, which the memory docs describe as:
|
||||
|
||||
> Use glob patterns in the `paths` field to match files by extension, directory, or any combination... You can specify multiple patterns and use brace expansion to match multiple extensions in one pattern.
|
||||
|
||||
The documented patterns are all positive (`**/*.ts`, `src/**/*`, `src/**/*.{ts,tsx}`). Brace expansion works. No `!pattern` exclude syntax is documented anywhere in the Skills, Plugins-reference, or Memory pages.
|
||||
|
||||
Empirical evidence from the issue tracker corroborates this:
|
||||
- anthropics/claude-code#17204 lists every syntax that does and does not work for `paths`/`globs`. None of the tested forms involve negation. The author would surely have tried it if it were a feature.
|
||||
- Multiple open bugs (#21858, #23478, #23569, #16853) discuss the field still failing in mundane cases (user-level rules, Write tool, worktrees). The feature is not mature enough to expect undocumented negation to work even if hand-rolled.
|
||||
|
||||
Conclusion: glob negation in `paths` is not supported today. Expressing "X present AND Y absent" requires a workaround.
|
||||
|
||||
### 3. Manifest fields
|
||||
|
||||
**SKILL.md frontmatter (official, from the Skills doc table):**
|
||||
|
||||
| Field | Purpose |
|
||||
|---|---|
|
||||
| `name` | Display name. Defaults to directory name. Lowercase, hyphens, max 64 chars. |
|
||||
| `description` | What the skill does and when to use it. Drives model-based activation. Up to 1024 chars. |
|
||||
| `when_to_use` | Extra trigger phrases. Appended to description, counts toward the 1,536-char listing cap. |
|
||||
| `argument-hint` | Autocomplete hint. |
|
||||
| `arguments` | Named positional args for `$name` substitution. |
|
||||
| `disable-model-invocation` | If true, only the user can invoke. |
|
||||
| `user-invocable` | If false, hide from `/` menu. |
|
||||
| `allowed-tools` | Tools pre-approved for this skill. |
|
||||
| `model` | Model override for this turn. |
|
||||
| `effort` | Effort-level override. |
|
||||
| `context` | Set to `fork` to run in a subagent. |
|
||||
| `agent` | Subagent type when `context: fork`. |
|
||||
| `hooks` | Skill-scoped lifecycle hooks. |
|
||||
| `paths` | **Glob patterns gating auto-activation.** |
|
||||
| `shell` | `bash` or `powershell` for `` !`...` `` injection. |
|
||||
|
||||
**plugin.json / marketplace.json:** Per the Plugins reference, neither has activation-condition keys for skills. Skills are auto-discovered from the plugin's `skills/` directory and gated only by whether the plugin is enabled. Activation logic lives in SKILL.md, not at the manifest level.
|
||||
|
||||
### 4. Priority / specificity
|
||||
|
||||
**No priority field exists.** When skills share a name across scopes there is a fixed override order (enterprise > personal > project; plugin skills are namespaced and don't conflict). Beyond name-conflict resolution there is no documented mechanism for declaring one sibling skill more specific than another. The model chooses among eligible skills based on description match. If `paths` filters narrow the eligible set, that narrowing is the only "specificity" lever available.
|
||||
|
||||
For listing-budget pressure, `skillOverrides` and `skillListingBudgetFraction` can drop or shorten descriptions of low-priority skills, but that's about token budget, not activation priority.
|
||||
|
||||
## First-party skills using non-description signals
|
||||
|
||||
Searched anthropics/skills and anthropics/claude-plugins-official. The publicly indexed first-party skills (PDF, Excel, DOCX, PPTX, etc.) rely on description-based activation. I did not find a first-party SKILL.md using `paths` in the public repos within the time budget for this research. Plenty of community/third-party skills exist, but I cannot confirm any well-known one using `paths` from authoritative sources. **Treat `paths` as a real but under-exercised feature** — the open bug list (#17204, #21858, #23478, #23569, #16853) confirms it ships and is being used, but adoption is limited.
|
||||
|
||||
## Citations
|
||||
|
||||
- [Extend Claude with skills — Claude Code docs](https://code.claude.com/docs/en/skills) — full frontmatter table including `paths`.
|
||||
- [Skill authoring best practices — Claude API docs](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices) — frontmatter requirements, description guidance.
|
||||
- [How Claude remembers your project — Memory docs](https://code.claude.com/docs/en/memory) — `paths` glob syntax via `.claude/rules/` (the format `paths` reuses). Documents positive patterns and brace expansion; no negation.
|
||||
- [Plugins reference — Claude Code docs](https://code.claude.com/docs/en/plugins-reference) — plugin.json/marketplace.json schemas; no skill-activation keys at manifest level.
|
||||
- [anthropics/claude-code#17204](https://github.com/anthropics/claude-code/issues/17204) — `paths` vs `globs` working/non-working forms; confirms no negation tested or supported.
|
||||
- [anthropics/claude-code#21858](https://github.com/anthropics/claude-code/issues/21858) — `paths` ignored at user level.
|
||||
- [anthropics/claude-code#23478](https://github.com/anthropics/claude-code/issues/23478) — `paths` not triggered on Write tool, only Read.
|
||||
- [anthropics/claude-code#23569](https://github.com/anthropics/claude-code/issues/23569) — `paths` ignored under worktree path resolution.
|
||||
- [anthropics/claude-code#16853](https://github.com/anthropics/claude-code/issues/16853) — `paths` not auto-loading on matching file work.
|
||||
- [paddo.dev — Claude Code Path-Specific Rules](https://paddo.dev/blog/claude-rules-path-specific-native/) — third-party walk-through of the `.claude/rules/` `paths` feature introduced in 2.0.64.
|
||||
- [anthropics/skills repo](https://github.com/anthropics/skills/) and [anthropics/claude-plugins-official](https://github.com/anthropics/claude-plugins-official) — reviewed for non-description activation; none confirmed.
|
||||
Reference in New Issue
Block a user