meta-promote
When to Use This Skill
| Use this skill when... |
Use a different skill when... |
Two or more sibling .claude/ scopes hold rules/skills/commands with the same name or topic, and you want to decide whether to lift them up to a shared parent |
You want to copy a project's config into your user-global config (use meta-assimilate) |
A portfolio root (e.g. ~/repos/) has children whose configs overlap and you want to promote the common kernel |
You want to review existing agent configs for security and frontmatter completeness without changing scopes (use meta-audit) |
| You suspect a rule is duplicated across sibling repos and want a structured promotion / extraction / keep-scoped decision per file |
You want to author a brand-new skill from scratch (use custom-agent-definitions) |
Context
- Current directory: !
pwd
- Local
.claude/ tree: !find . -path '*/.claude/*' -maxdepth 4 -type f -name '*.md' -not -path '*/node_modules/*' -not -path '*/.claude/worktrees/*'
- Child
.claude/ trees (one level down): !find . -mindepth 2 -maxdepth 4 -type d -name '.claude' -not -path '*/node_modules/*'
Parameters
Parse $ARGUMENTS:
scope-path (optional, default .) — the directory whose children's .claude/ trees should be evaluated for promotion up to this directory. The skill always treats scope-path as the target scope and its immediate .claude/-bearing children as the source scopes.
Your task
Execute this evaluation and (with approval) apply it. Do not promote anything without explicit per-candidate confirmation — promotion is a write to shared state and easy to get wrong.
1. Build the scope inventory
Walk three layers:
| Layer |
Path |
Role |
| Target |
<scope-path>/.claude/{rules,skills,commands,agents}/ |
Where promoted files would land |
| Sources |
<scope-path>/*/.claude/{rules,skills,commands,agents}/ |
Children whose contents are candidates |
| Upstream |
User-global .claude/rules/ (resolve $HOME/.claude/rules during execution, not in the Context block) and any plugin skills already loaded for this session |
Already-covered material — promotion to the target would just duplicate this |
For the upstream layer, run Glob(pattern="$HOME/.claude/rules/**/*.md") during execution and read filenames + first heading of each match. The plugin-skill list is already in the session prompt — scan it for relevant entries by name.
For each source file, record (scope, kind, name, path) where kind ∈ {rule, skill, command, agent} and name is the filename or skill directory name.
2. Find overlap candidates
Group source files by (kind, name). Three kinds of overlap matter:
- Same-name across sources — the same filename appears in two or more sibling scopes (e.g.
ci-cd-workflows.md in both OrgA/.claude/rules/ and OrgB/.claude/rules/)
- Same-topic across sources — different filenames, related content (e.g.
commits.md and commit-conventions.md)
- Source vs target collision — a file with the same name already exists at the target scope
Files that appear in only one source and have no target-scope sibling are not promotion candidates — they are correctly scoped already.
3. Evaluate each candidate
For each candidate group, read every file and apply this checklist. Every "yes" makes promotion less appropriate:
| Signal |
What to look for |
| Owner-specific identifiers |
Org or user names (OrgA, some-user), GH repo URLs, container registry paths (ghcr.io/<org>/...), GitHub App IDs, secret names, named workspaces (Terraform Cloud, Spacelift) |
| Owner-specific conventions |
Label sets (docs vs documentation), reviewer usernames (@user vs bare user), project-routing tables, CI tool choices (Renovate vs Dependabot) |
| Path-scoped frontmatter that differs |
A paths: glob that genuinely targets a different directory shape per source |
| Tooling assumptions |
Helm chart names, image-updater configurations, deploy-values schemas tied to one stack |
| Already covered upstream |
A user-global rule, a plugin skill, or a friction-findings note already says the same thing — promoting would duplicate, not consolidate |
Then ask the inverse: what's generic about this file? Is there a kernel (a self-review guard, a "use conventional commits" preamble, a generic checklist) that applies regardless of owner?
4. Recommend an action per candidate
Pick exactly one of four:
| Action |
When |
What it does |
| Promote as-is |
All sources have effectively identical content; no owner-specific signals; not already upstream |
git mv one source copy to the target scope; delete siblings |
| Extract kernel |
Sources share a generic core but each carries owner-specific deltas |
Write the generic content as a new file at the target scope; trim each source down to only the deltas, with a one-line link back to the target file |
| Keep scoped |
Content genuinely differs per owner; a unified version would force one set of conventions on the others |
Leave files where they are; optionally add a one-line frontmatter comment explaining the divergence so future readers don't re-evaluate |
| No action (already upstream) |
The user-global rule or a plugin skill already covers this |
Optionally delete the redundant source copies; do not write to the target |
5. Confirm before writing
For each candidate group, present:
- The grouped files (paths)
- The diff between sources (
diff <a> <b> for two-source cases; a 3-way summary for more)
- The recommended action with a one-sentence justification
- The four alternatives via
AskUserQuestion
Only proceed on explicit approval. Do not bundle multiple candidate decisions into one prompt — each gets its own approval round-trip so the user can redirect on any single one.
6. Execute the approved action
| Action |
Mechanics |
| Promote as-is |
git mv <source-1> <target> to preserve history, then rm the other sources. If the source repos are independent (separate .git per scope), use cp + rm instead of git mv. |
| Extract kernel |
Use Write to create the target file with the generic content. Use Edit on each source to remove the now-shared content, replacing it with one line of the form > Generic guidance: see [\`]().` |
| Keep scoped |
Optionally Edit each source to add an HTML comment <!-- intentionally scoped: <reason> --> near the top so the next pass through this skill skips it quickly. |
| No action |
Optionally rm the redundant sources; never write to the target. |
After every write, run git status against each affected repo so the user sees exactly what changed before any commit happens.
7. Report
Emit a final summary table:
| Source files |
Action |
Target |
Notes |
OrgA/.claude/rules/foo.md, OrgB/.claude/rules/foo.md |
Keep scoped |
— |
Org-specific label conventions |
OrgA/.claude/rules/bar.md, OrgB/.claude/rules/bar.md |
Promote as-is |
./.claude/rules/bar.md |
Identical content, no owner signals |
End with the next step the user should take (typically: review git status in each affected repo, then commit per-repo with conventional-commit messages — meta-promote itself does not commit).
Demotion (inverse direction)
Occasionally a rule lives at user-global scope but is genuinely owner- or project-specific. The same evaluation applies in reverse: if a ~/.claude/rules/<x>.md references one org's tooling and would mislead anyone outside that org, propose moving it down to the appropriate <owner>/.claude/rules/. Use the same four-action menu — "Promote" becomes "Demote", "Extract kernel" stays the same.
Anti-patterns to avoid
| Don't |
Do |
| Promote two same-named files just because the names match |
Diff their contents and apply the checklist — same name often hides genuinely different rules |
| Bundle "promote A and B" into one approval prompt |
One candidate, one prompt — the user may agree on A and reject B |
Use rm -rf on a scope's .claude/ to "clean up" after promotion |
Remove only the specific files you're promoting; leave the rest of the scope alone |
| Commit the promotion as part of the skill |
Leave commits to the user — the skill produces a clean working tree the user can review and split into per-repo commits |
| Promote when an upstream rule already covers it |
Recommend "no action" and (with approval) delete the redundant source(s) |
Notes
- This skill reads broadly and writes narrowly. The discovery phase touches every
.claude/ scope under scope-path; the write phase touches only the specific files the user approved.
- When source scopes are in separate git repos, the user must commit in each repo independently. Do not attempt cross-repo atomic operations.
- Pair with
meta-audit for a follow-up sanity check after promotion: meta-audit will catch any frontmatter that broke during the move.
1---
2created: 2026-05-09
3modified: 2026-07-18
4compatibility: claude-code
5reviewed: 2026-05-09
6allowed-tools: Glob, Read, Edit, Write, Bash(git status *), Bash(git diff *), Bash(git mv *), Bash(diff *), Bash(rm *), AskUserQuestion, TodoWrite
7model: opus
8description: Promote rules, skills, or agents from project scope to parent or user-global scope. Use when reorganizing .claude/ directories or when sibling repos hold near-duplicate rules.
9args: "[scope-path]"
10argument-hint: "[scope-path]"
11name: meta-promote
12---
13
14# meta-promote
15
16## When to Use This Skill
17
18| Use this skill when... | Use a different skill when... |
19|---|---|
20| Two or more sibling `.claude/` scopes hold rules/skills/commands with the same name or topic, and you want to decide whether to lift them up to a shared parent | You want to copy a *project's* config into your *user-global* config (use `meta-assimilate`) |
21| A portfolio root (e.g. `~/repos/`) has children whose configs overlap and you want to promote the common kernel | You want to review existing agent configs for security and frontmatter completeness without changing scopes (use `meta-audit`) |
22| You suspect a rule is duplicated across sibling repos and want a structured promotion / extraction / keep-scoped decision per file | You want to author a brand-new skill from scratch (use `custom-agent-definitions`) |
23
24## Context
25
26- Current directory: !`pwd`
27- Local `.claude/` tree: !`find . -path '*/.claude/*' -maxdepth 4 -type f -name '*.md' -not -path '*/node_modules/*' -not -path '*/.claude/worktrees/*'`
28- Child `.claude/` trees (one level down): !`find . -mindepth 2 -maxdepth 4 -type d -name '.claude' -not -path '*/node_modules/*'`
29
30## Parameters
31
32Parse `$ARGUMENTS`:
33
34- `scope-path` (optional, default `.`) — the directory whose children's `.claude/` trees should be evaluated for promotion *up to* this directory. The skill always treats `scope-path` as the **target** scope and its immediate `.claude/`-bearing children as the **source** scopes.
35
36## Your task
37
38Execute this evaluation and (with approval) apply it. **Do not promote anything without explicit per-candidate confirmation** — promotion is a write to shared state and easy to get wrong.
39
40### 1. Build the scope inventory
41
42Walk three layers:
43
44| Layer | Path | Role |
45|---|---|---|
46| Target | `<scope-path>/.claude/{rules,skills,commands,agents}/` | Where promoted files would land |
47| Sources | `<scope-path>/*/.claude/{rules,skills,commands,agents}/` | Children whose contents are candidates |
48| Upstream | User-global `.claude/rules/` (resolve `$HOME/.claude/rules` during execution, not in the Context block) and any plugin skills already loaded for this session | Already-covered material — promotion to the target would just duplicate this |
49
50For the upstream layer, run `Glob(pattern="$HOME/.claude/rules/**/*.md")` during execution and read filenames + first heading of each match. The plugin-skill list is already in the session prompt — scan it for relevant entries by name.
51
52For each source file, record `(scope, kind, name, path)` where `kind ∈ {rule, skill, command, agent}` and `name` is the filename or skill directory name.
53
54### 2. Find overlap candidates
55
56Group source files by `(kind, name)`. Three kinds of overlap matter:
57
58- **Same-name across sources** — the same filename appears in two or more sibling scopes (e.g. `ci-cd-workflows.md` in both `OrgA/.claude/rules/` and `OrgB/.claude/rules/`)
59- **Same-topic across sources** — different filenames, related content (e.g. `commits.md` and `commit-conventions.md`)
60- **Source vs target collision** — a file with the same name already exists at the target scope
61
62Files that appear in only one source and have no target-scope sibling are not promotion candidates — they are correctly scoped already.
63
64### 3. Evaluate each candidate
65
66For each candidate group, read every file and apply this checklist. Every "yes" makes promotion *less* appropriate:
67
68| Signal | What to look for |
69|---|---|
70| Owner-specific identifiers | Org or user names (`OrgA`, `some-user`), GH repo URLs, container registry paths (`ghcr.io/<org>/...`), GitHub App IDs, secret names, named workspaces (Terraform Cloud, Spacelift) |
71| Owner-specific conventions | Label sets (`docs` vs `documentation`), reviewer usernames (`@user` vs bare `user`), project-routing tables, CI tool choices (Renovate vs Dependabot) |
72| Path-scoped frontmatter that differs | A `paths:` glob that genuinely targets a different directory shape per source |
73| Tooling assumptions | Helm chart names, image-updater configurations, deploy-values schemas tied to one stack |
74| Already covered upstream | A user-global rule, a plugin skill, or a friction-findings note already says the same thing — promoting would duplicate, not consolidate |
75
76Then ask the inverse: what's *generic* about this file? Is there a kernel (a self-review guard, a "use conventional commits" preamble, a generic checklist) that applies regardless of owner?
77
78### 4. Recommend an action per candidate
79
80Pick exactly one of four:
81
82| Action | When | What it does |
83|---|---|---|
84| **Promote as-is** | All sources have effectively identical content; no owner-specific signals; not already upstream | `git mv` one source copy to the target scope; delete siblings |
85| **Extract kernel** | Sources share a generic core but each carries owner-specific deltas | Write the generic content as a new file at the target scope; trim each source down to only the deltas, with a one-line link back to the target file |
86| **Keep scoped** | Content genuinely differs per owner; a unified version would force one set of conventions on the others | Leave files where they are; optionally add a one-line frontmatter comment explaining the divergence so future readers don't re-evaluate |
87| **No action (already upstream)** | The user-global rule or a plugin skill already covers this | Optionally delete the redundant source copies; do not write to the target |
88
89### 5. Confirm before writing
90
91For each candidate group, present:
92
931. The grouped files (paths)
942. The diff between sources (`diff <a> <b>` for two-source cases; a 3-way summary for more)
953. The recommended action with a one-sentence justification
964. The four alternatives via `AskUserQuestion`
97
98Only proceed on explicit approval. **Do not bundle multiple candidate decisions into one prompt** — each gets its own approval round-trip so the user can redirect on any single one.
99
100### 6. Execute the approved action
101
102| Action | Mechanics |
103|---|---|
104| Promote as-is | `git mv <source-1> <target>` to preserve history, then `rm` the other sources. If the source repos are independent (separate `.git` per scope), use `cp` + `rm` instead of `git mv`. |
105| Extract kernel | Use `Write` to create the target file with the generic content. Use `Edit` on each source to remove the now-shared content, replacing it with one line of the form `> Generic guidance: see [\`<rel-path-to-target>\`](<rel-path-to-target>).` |
106| Keep scoped | Optionally `Edit` each source to add an HTML comment `<!-- intentionally scoped: <reason> -->` near the top so the next pass through this skill skips it quickly. |
107| No action | Optionally `rm` the redundant sources; never write to the target. |
108
109After every write, run `git status` against each affected repo so the user sees exactly what changed before any commit happens.
110
111### 7. Report
112
113Emit a final summary table:
114
115| Source files | Action | Target | Notes |
116|---|---|---|---|
117| `OrgA/.claude/rules/foo.md`, `OrgB/.claude/rules/foo.md` | Keep scoped | — | Org-specific label conventions |
118| `OrgA/.claude/rules/bar.md`, `OrgB/.claude/rules/bar.md` | Promote as-is | `./.claude/rules/bar.md` | Identical content, no owner signals |
119
120End with the next step the user should take (typically: review `git status` in each affected repo, then commit per-repo with conventional-commit messages — `meta-promote` itself does **not** commit).
121
122## Demotion (inverse direction)
123
124Occasionally a rule lives at user-global scope but is genuinely owner- or project-specific. The same evaluation applies in reverse: if a `~/.claude/rules/<x>.md` references one org's tooling and would mislead anyone outside that org, propose moving it down to the appropriate `<owner>/.claude/rules/`. Use the same four-action menu — "Promote" becomes "Demote", "Extract kernel" stays the same.
125
126## Anti-patterns to avoid
127
128| Don't | Do |
129|---|---|
130| Promote two same-named files just because the names match | Diff their contents and apply the checklist — same name often hides genuinely different rules |
131| Bundle "promote A and B" into one approval prompt | One candidate, one prompt — the user may agree on A and reject B |
132| Use `rm -rf` on a scope's `.claude/` to "clean up" after promotion | Remove only the specific files you're promoting; leave the rest of the scope alone |
133| Commit the promotion as part of the skill | Leave commits to the user — the skill produces a clean working tree the user can review and split into per-repo commits |
134| Promote when an upstream rule already covers it | Recommend "no action" and (with approval) delete the redundant source(s) |
135
136## Notes
137
138- This skill **reads broadly and writes narrowly**. The discovery phase touches every `.claude/` scope under `scope-path`; the write phase touches only the specific files the user approved.
139- When source scopes are in separate git repos, the user must commit in each repo independently. Do not attempt cross-repo atomic operations.
140- Pair with `meta-audit` for a follow-up sanity check after promotion: `meta-audit` will catch any frontmatter that broke during the move.