skills/cmd-local-repo-skills/SKILL.md
Scaffold cross-tool repo-local skills and agent instructions with canonical source in .agents/ and symlinks for Claude, Codex, Gemini, and Codex-home
npx skillsauth add olshansk/agent-skills cmd-local-repo-skillsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Create or refactor repo-local skills and agent instructions that work across Claude, Codex, Gemini, and Codex-home using a single canonical source in .agents/.
repo-root/
├── .agents/
│ ├── AGENTS.md # Canonical agent instructions
│ └── skills/<name>/SKILL.md # Canonical skill source
├── AGENTS.md → .agents/AGENTS.md # Symlink (tools reading repo root)
├── CLAUDE.md → .agents/AGENTS.md # Symlink (Claude reads repo root)
├── .codex/AGENTS.md → ../.agents/AGENTS.md # Symlink
├── .gemini/GEMINI.md → ../.agents/AGENTS.md # Symlink
├── .claude/skills/<name> → ../../.agents/skills/<name> # Per-skill symlink
├── .codex/skills/<name> → ../../.agents/skills/<name> # Per-skill symlink
├── .codex-home/skills/<name> → ../../.agents/skills/<name> # Per-skill symlink
└── .gitignore # Whitelist entries for all paths
Key rules:
.agents/ is the single source of truth for both agent instructions and skills.agents/AGENTS.md is the canonical agent instruction file — all tool-specific files are symlinksnpx skills add) coexist without conflict.gitignore uses a base skills/ ignore rule, then whitelists specific pathsevals/ directory inside .agents/skills/<name>/ is always gitignored.claude/skills/<name>/, .codex/skills/<name>/, .codex-home/skills/<name>/). Per-tool dirs contain only symlinks. Canonical source is always .agents/skills/<name>/ — this keeps skills cross-tool and prevents silent Claude-only (or Codex-only, etc.) driftBefore asking questions, run discovery:
ls .agents/ 2>/dev/null
ls .agents/skills/ 2>/dev/null
ls .claude/commands/ 2>/dev/null
cat CLAUDE.md 2>/dev/null | head -5
cat AGENTS.md 2>/dev/null | head -5
grep -n "^skills/" .gitignore 2>/dev/null
Also run the cross-tool audit (see Audit commands for the copy-paste block). Detect:
.claude/skills/, .codex/skills/, or .codex-home/skills/ that is a real directory (not a symlink). These violate the cross-tool rule and must be promoted..agents/skills/ — any skill in .agents/skills/ that is missing a symlink in one or more per-tool dirs. These are reachable from some tools but not others.Present all findings (shared-context reads + audit output), then use AskUserQuestion with these questions (max 4 per call):
.claude/commands/ file into the cross-tool skill structure, (c) just set up agent instructions (no skill), (d) promote an existing tool-specific real-dir skill into the cross-tool layout, or (e) repair an orphan .agents/skills/ skill by creating missing per-tool symlinks?"grove-api-review)".claude/commands/)If the audit surfaced violations or orphans, lead with those — it's almost always the right next action before scaffolding anything new.
Set up .agents/AGENTS.md as the canonical agent instruction file with symlinks for every tool.
Step 1 — Create or migrate the canonical file:
mkdir -p .agents
AGENTS.md exists at repo root and is a regular file, move it: mv AGENTS.md .agents/AGENTS.mdCLAUDE.md exists at repo root and is a regular file (not a symlink), move it: mv CLAUDE.md .agents/AGENTS.md.agents/AGENTS.md with a minimal skeleton.agents/AGENTS.md (prefer AGENTS.md content, append unique CLAUDE.md content)Step 2 — Create symlinks:
ln -sf .agents/AGENTS.md AGENTS.md
ln -sf .agents/AGENTS.md CLAUDE.md
mkdir -p .codex .gemini
ln -sf ../.agents/AGENTS.md .codex/AGENTS.md
ln -sf ../.agents/AGENTS.md .gemini/GEMINI.md
Step 3 — Verify all symlinks resolve:
readlink AGENTS.md
readlink CLAUDE.md
readlink .codex/AGENTS.md
readlink .gemini/GEMINI.md
head -3 CLAUDE.md
Step 4 — Update .gitignore:
Check if entries already exist, then add as needed:
grep -n "AGENTS.md\|CLAUDE.md\|GEMINI.md" .gitignore 2>/dev/null
Append the agent instructions block from the gitignore template if not present.
Skip this phase if the user chose mode (c) in Phase 1. Modes (a), (b), (d), and (e) all share the same symlink + gitignore steps — they only differ in how the canonical source is produced.
Create the canonical directory:
mkdir -p .agents/skills/<name>
If creating new (mode a):
Create .agents/skills/<name>/SKILL.md with frontmatter and a minimal skeleton. Ask the user to provide or iterate on the skill content.
If refactoring from .claude/commands/ (mode b):
.claude/commands/<name>.md).agents/skills/<name>/SKILL.md with YAML frontmatter added<!-- omit in toc -->If promoting an existing tool-specific real-dir skill (mode d):
The skill currently lives as a real directory under a per-tool path (e.g., .claude/skills/<name>/ with a real SKILL.md inside). Move it to the canonical location:
mv .claude/skills/<name> .agents/skills/<name>
If the violation is under .codex/skills/ or .codex-home/skills/ instead, mv from there. Then proceed to Create symlinks — a symlink must be re-added to the per-tool dir the skill was promoted from (since the mv removed it), and to the other two per-tool dirs.
If repairing an orphan (mode e):
The skill already lives at .agents/skills/<name>/ but is missing one or more per-tool symlinks. Skip directly to Create symlinks — the canonical source is untouched; only the symlinks need to be (re-)created.
Each skill needs a symlink in every tool's skills directory. This approach allows external skills (e.g. from npx skills add) to coexist.
mkdir -p .claude/skills .codex/skills .codex-home/skills
ln -sf ../../.agents/skills/<name> .claude/skills/<name>
ln -sf ../../.agents/skills/<name> .codex/skills/<name>
ln -sf ../../.agents/skills/<name> .codex-home/skills/<name>
Check that the symlinks resolve correctly:
test -f .claude/skills/<name>/SKILL.md && echo "OK" || echo "BROKEN"
Two legacy layouts require normalization before this loop runs cleanly:
Legacy — directory-level symlink (.claude/skills → ../.agents/skills). Replace with per-skill symlinks:
for tool in .claude .codex .codex-home; do
[ -L "$tool/skills" ] && rm "$tool/skills"
mkdir -p "$tool/skills"
done
Legacy — tool-specific real-dir skill (a real .claude/skills/<name>/ or .codex/skills/<name>/ dir, not a symlink). Promote to canonical first:
for tool in .claude .codex .codex-home; do
for d in "$tool"/skills/*/; do
[ -d "$d" ] && [ ! -L "${d%/}" ] || continue
name=$(basename "${d%/}")
# Skip if a canonical source already exists (manual conflict resolution needed)
[ -d ".agents/skills/$name" ] && { echo "CONFLICT: .agents/skills/$name already exists; resolve manually"; continue; }
mv "${d%/}" ".agents/skills/$name"
done
done
After either normalization, populate all three per-tool dirs with per-skill symlinks:
mkdir -p .claude/skills .codex/skills .codex-home/skills
for skill in .agents/skills/*/; do
name=$(basename "$skill")
ln -sf "../../.agents/skills/$name" ".claude/skills/$name"
ln -sf "../../.agents/skills/$name" ".codex/skills/$name"
ln -sf "../../.agents/skills/$name" ".codex-home/skills/$name"
done
ln -sf makes this idempotent — safe to re-run on a partially-configured repo (mode e).
The gitignore must be updated carefully to preserve existing entries.
Step 1 — Check if the base skills/ rule exists:
grep -n "^skills/" .gitignore
Step 2 — Check if entries for this skill already exist:
grep "<name>" .gitignore
Step 3 — Append or insert the whitelist block.
If NO skills/ section exists, append the full block from the gitignore template.
If a skills/ section already exists (adding a 2nd+ skill), only add the NEW skill-specific lines. The base rules (skills/, !.agents/skills/, !.claude/skills, !.codex/skills, !.codex-home/skills) already exist — do NOT duplicate them. Insert the new lines after the last entry:
!.agents/skills/<name>/
!.agents/skills/<name>/SKILL.md
.agents/skills/<name>/evals/
Never duplicate a line that already exists in .gitignore.
Run these checks and report results:
# Verify agent instruction symlinks
readlink AGENTS.md
readlink CLAUDE.md
readlink .codex/AGENTS.md
readlink .gemini/GEMINI.md
head -1 CLAUDE.md
If skills were scaffolded, promoted, or repaired:
# Verify per-skill symlinks resolve correctly
readlink .claude/skills/<name>
readlink .codex/skills/<name>
readlink .codex-home/skills/<name>
# Verify skill content is accessible through each symlink
head -3 .claude/skills/<name>/SKILL.md
head -3 .codex/skills/<name>/SKILL.md
head -3 .codex-home/skills/<name>/SKILL.md
# Verify git tracks the canonical skill file
git status .agents/skills/<name>/SKILL.md
# Lint: all three per-tool symlink entries must be whitelisted in .gitignore
for tool in .claude .codex .codex-home; do
grep -q "^!$tool/skills/<name>$" .gitignore \
|| echo "FAIL: .gitignore missing '!$tool/skills/<name>'"
done
# Lint: no real-dir skills should remain under any per-tool path
for tool in .claude .codex .codex-home; do
find "$tool/skills" -mindepth 1 -maxdepth 1 -type d -not -name skills \
| while read d; do echo "FAIL: real-dir skill at $d (should be a symlink)"; done
done
If refactoring, ask: "The original command file at .claude/commands/<file> still exists. Should I delete it now that the skill has been migrated?"
Present summary:
Agent instructions:
Canonical: .agents/AGENTS.md
AGENTS.md → .agents/AGENTS.md → ✅
CLAUDE.md → .agents/AGENTS.md → ✅
.codex/AGENTS.md → ../.agents/AGENTS.md → ✅
.gemini/GEMINI.md → ../.agents/AGENTS.md → ✅
Skill: <name>
Canonical: .agents/skills/<name>/SKILL.md
.claude/skills/<name> → ../../.agents/skills/<name> → ✅
.codex/skills/<name> → ../../.agents/skills/<name> → ✅
.codex-home/skills/<name> → ../../.agents/skills/<name> → ✅
Gitignore: ✅ updated
---
name: <skill-name>
description: <one-line description>
disable-model-invocation: false
---
# Skill Title <!-- omit in toc -->
# AGENTS.md <!-- omit in toc -->
## Project Overview
- Brief description of the project
## Development
- Key commands and workflows
Full block for agent instructions (add once per repo):
# Agent instructions
# Canonical source: .agents/AGENTS.md — tool-specific files are symlinks
!.agents/
!.agents/AGENTS.md
Full block for the first skill in a repo (replace <name> with the skill name):
# Skills
# Default: ignore generic skills/ trees from external skill repos.
# Exception: keep repo-local cross-tool skills tracked via per-skill symlinks.
skills/
!.agents/skills/
!.agents/skills/<name>/
!.agents/skills/<name>/SKILL.md
.agents/skills/<name>/evals/
# Per-skill symlinks — track each symlink so all tools discover the skill
!.claude/skills/
!.claude/skills/<name>
!.codex/skills/
!.codex/skills/<name>
!.codex-home/skills/
!.codex-home/skills/<name>
For additional skills, append only the new skill-specific lines:
!.agents/skills/<name>/
!.agents/skills/<name>/SKILL.md
.agents/skills/<name>/evals/
!.claude/skills/<name>
!.codex/skills/<name>
!.codex-home/skills/<name>
Use these during Phase 1 to surface cross-tool drift before scaffolding anything new.
Detect tool-specific real-dir skills (violations — a skill that exists under a per-tool path as a real directory, not a symlink):
for tool in .claude .codex .codex-home; do
[ -d "$tool/skills" ] || continue
find "$tool/skills" -mindepth 1 -maxdepth 1 -type d -not -name skills 2>/dev/null \
| while read d; do echo "VIOLATION: real-dir skill at $d"; done
done
Detect orphans (skill exists in .agents/skills/ but is missing a symlink in one or more per-tool dirs):
[ -d .agents/skills ] && for skill in .agents/skills/*/; do
name=$(basename "${skill%/}")
for tool in .claude .codex .codex-home; do
[ -L "$tool/skills/$name" ] || echo "ORPHAN: .agents/skills/$name missing $tool/skills/$name"
done
done
Detect broken symlinks (target missing):
for tool in .claude .codex .codex-home; do
[ -d "$tool/skills" ] || continue
find "$tool/skills" -maxdepth 1 -type l -exec test ! -e {} \; -print \
| while read l; do echo "BROKEN: $l"; done
done
Empty output from all three = healthy cross-tool layout.
Agent instructions setup (run once per repo):
mkdir -p .agents .codex .gemini
ln -sf .agents/AGENTS.md AGENTS.md
ln -sf .agents/AGENTS.md CLAUDE.md
ln -sf ../.agents/AGENTS.md .codex/AGENTS.md
ln -sf ../.agents/AGENTS.md .gemini/GEMINI.md
Per-skill setup (run for each new skill):
mkdir -p .agents/skills/<name> .claude/skills .codex/skills .codex-home/skills
ln -sf ../../.agents/skills/<name> .claude/skills/<name>
ln -sf ../../.agents/skills/<name> .codex/skills/<name>
ln -sf ../../.agents/skills/<name> .codex-home/skills/<name>
testing
Ask the agent whether it finished everything or has more to do — a lightweight completeness gate for the end of any task
development
Audit personal skills for redundancy, verbosity, weak triggers, and overlap. Runs a Claude→Codex review loop, presents per-item approval checkboxes, then applies approved edits and updates README and agent metadata. Use when asked to "review my skills", "audit my skills", "revisit my skills", or "clean up my skills". Accepts an optional skill name to scope the review to a single skill.
development
Set up or extend golden/snapshot tests for a project. Covers fixture design, Makefile targets, snapshot storage, diff workflow, and update protocol.
development
Proofread posts before publishing for spelling, grammar, repetition, logic, weak arguments, broken links, and optionally reformat for skimmability or shape the writing vibe toward a known author's style