Skip to content

Shared skills — company repo + bootstrap + onboarding hook

Question 6 (Shared infrastructure): Does the team share skills?

Max-score answer: Repo + bootstrap script + onboarding hook that auto-installs.

Why it matters: Skills are how senior engineers package institutional knowledge. A skill repo turns “knows how to refactor our auth” into a one-liner everyone can run.

The biggest predictor of how much value an engineering org gets from Claude Code, Codex, or Cursor in 2026 isn’t which model you pay for — it’s whether the tacit knowledge in your senior engineers’ heads has been packaged into something a junior (or an agent) can actually run. That’s what skills are for. A SKILL.md is progressively-disclosed procedural knowledge (“here’s how we refactor auth,” “here’s how we ship a Polar webhook fix”) bundled with the scripts, prompts, and references the agent needs.

Anthropic published SKILL.md as an open standard at agentskills.io in late 2025, and by Q2 2026 it works across Claude Code, Codex, Cursor, Gemini CLI, and Copilot. The format won fast because it solved the problem every team hit independently: seniors kept rebuilding the same instructions in Slack threads, in .claude/rules/, in personal notes — and none of it scaled past the person who wrote it.

The Q6 max-score answer closes that gap. One git repo holds every skill. A bootstrap script symlinks the repo’s skills/ directory into each developer’s ~/.claude/skills/ (plus Cursor and Codex equivalents). A SessionStart hook checks the repo version on every new session and auto-pulls when a teammate ships something new. When a senior files a PR with a new skill, every developer’s next session has it loaded — no DM, no announcement, no manual install.

Teams without this setup pay a recurring “explain how we do X” tax. Teams with it close the gap between their top performer and median, because the top performer’s knowledge is now in the repo. A structural advantage that compounds every sprint.

What “max score” actually looks like (repo + bootstrap script + onboarding hook auto-install)

Section titled “What “max score” actually looks like (repo + bootstrap script + onboarding hook auto-install)”

Three components, each doing one job:

1. A company skills repo. A normal git repo (acme/agent-skills) with one folder per skill. Each folder contains a SKILL.md plus supporting scripts, prompts, and references. The repo is versioned, reviewed via PR, and owned by a named team — like your shared lint config or design tokens.

2. A bootstrap script. One command (./bootstrap.sh, npx @acme/agent-skills install) that wires the repo into a developer’s machine. Clone to ~/.acme-agent-skills/ and symlink each skill folder into ~/.claude/skills/, ~/.cursor/skills/, ~/.codex/skills/. Symlinks (not copies) mean one git pull updates every tool simultaneously.

3. An onboarding hook that auto-installs. A SessionStart hook in ~/.claude/settings.json checks on every new session: “is the local skills repo up to date with origin?” If not, it pulls. If the repo isn’t cloned, it clones. The first time a new hire opens Claude Code in your org, they get every company skill without knowing it happened.

The clean version of the file layout:

acme/agent-skills/ # the repo
├── bootstrap.sh # install script (idempotent)
├── version.json # { "version": "2026.05.21", "min_claude": "1.4.0" }
├── README.md # for humans
└── skills/
├── refactor-auth/
│ ├── SKILL.md # the skill itself
│ ├── scripts/migrate.sh
│ └── references/policies.md
├── ship-polar-webhook-fix/
│ └── SKILL.md
├── audit-worker-cost/
│ ├── SKILL.md
│ └── scripts/cost-diff.ts
└── ...

A new hire’s terminal session, end-to-end:

Terminal window
# Day 1, after laptop setup
$ curl -fsSL https://acme.dev/agent-skills/install | bash
$ claude
> /skills
# All 47 company skills already listed.

No “ask Slack which skills to install.” No “wait until your buddy onboards you.” The agent walks in with every piece of institutional knowledge the company has written down.

Skill repo structure (per-skill folder with SKILL.md)

Section titled “Skill repo structure (per-skill folder with SKILL.md)”

The 2026 convention, set by Anthropic’s reference and reinforced by openai/skills and VoltAgent awesome-agent-skills, is one folder per skill, one SKILL.md per folder. The file uses YAML frontmatter (name, description, when_to_use) followed by the body. The agent’s loader scans the directory, reads the frontmatter, and only loads the full body when the skill matches the user’s intent — that’s the “progressive disclosure” that keeps skills from blowing up the context window.

A minimal company skill:

---
name: refactor-auth
description: Refactor a BetterAuth + Polar.sh handler. Use when the user
asks to "refactor auth", "fix auth", "rework signin", or modifies any
file in src/lib/auth/** or src/pages/api/auth/**.
---
# Refactor auth (Acme)
## Mental model
- BetterAuth owns sessions and the OTP flow.
- Polar.sh owns subscription state, written by webhook into
`subscription_access_tokens`.
- A signed-in user with no active subscription gets a 402 from gated routes.
## Steps
1. Read `src/lib/auth/config.ts`; confirm the BetterAuth options.
2. Run `npm run db:check-migrations` before any schema change.
3. Every gated handler's first line: `await auth.api.getSession({ headers })`.
4. After changes, run `./scripts/auth-smoke.sh` (in this skill folder).
## Common traps
- Polar webhook bridge is async — don't check subscription state immediately
after checkout; poll with backoff.
- Don't roll your own session checks. Always go through `auth.api.*`.

Every skill is reviewable. PRs that add or change a skill go through the same code review as any other change. That’s the point — institutional knowledge becomes a first-class artifact.

Section titled “Bootstrap script approach (symlink ~/.claude/skills/* to repo clone)”

The bootstrap pattern that stuck across community templates (netresearch/skill-repo-skill, Anthropic Skill-Creator) is:

acme/agent-skills/bootstrap.sh
#!/usr/bin/env bash
set -euo pipefail
REPO_DIR="${HOME}/.acme-agent-skills"
SKILLS_DIR="${REPO_DIR}/skills"
# 1. Clone or update the repo
if [ ! -d "${REPO_DIR}" ]; then
git clone https://github.com/acme/agent-skills "${REPO_DIR}"
else
git -C "${REPO_DIR}" pull --ff-only
fi
# 2. Make sure target dirs exist
mkdir -p ~/.claude/skills ~/.cursor/skills ~/.codex/skills
# 3. Symlink every skill into every tool's skills dir
for skill in "${SKILLS_DIR}"/*/; do
name="$(basename "${skill}")"
ln -sfn "${skill}" ~/.claude/skills/"${name}"
ln -sfn "${skill}" ~/.cursor/skills/"${name}"
ln -sfn "${skill}" ~/.codex/skills/"${name}"
done
# 4. Register a SessionStart hook (only on first run)
HOOK_FILE="${HOME}/.claude/hooks/acme-skill-sync.sh"
if [ ! -f "${HOOK_FILE}" ]; then
mkdir -p "${HOME}/.claude/hooks"
cat > "${HOOK_FILE}" <<'EOF'
#!/usr/bin/env bash
git -C "${HOME}/.acme-agent-skills" fetch --quiet origin main || exit 0
LOCAL="$(git -C "${HOME}/.acme-agent-skills" rev-parse HEAD)"
REMOTE="$(git -C "${HOME}/.acme-agent-skills" rev-parse origin/main)"
[ "$LOCAL" != "$REMOTE" ] && "${HOME}/.acme-agent-skills/bootstrap.sh" >/dev/null
EOF
chmod +x "${HOOK_FILE}"
# Register the hook in settings.json (see step 4 in the next section).
fi
echo "Installed $(ls "${SKILLS_DIR}" | wc -l) skills."

Three properties matter:

  • Idempotent. Run it five times in a row, nothing breaks. Symlinks re-created, git pull is fast-forward-only, the hook is written only if missing.
  • Multi-tool. Symlinks fan out from one source to every tool the team uses. A skill written once shows up everywhere.
  • Read-only on the developer’s side. Developers never edit files in ~/.claude/skills/ directly — they edit in the repo, file a PR, the symlink picks up the change. This kills the “drift” failure mode where every developer has a slightly different copy.

Auto-install onboarding hook (SessionStart hook checking version)

Section titled “Auto-install onboarding hook (SessionStart hook checking version)”

Claude Code’s SessionStart hook (with equivalents in Cursor and Codex) runs a script every time a new agent session starts. The hook is the secret sauce — without it, a senior shipping a new skill at 4pm reaches the team only after every other developer manually pulls. With it, the next session every developer opens auto-syncs.

The pattern in ~/.claude/settings.json:

{
"hooks": {
"SessionStart": [
{
"matcher": ".*",
"hooks": [
{ "type": "command", "command": "~/.claude/hooks/acme-skill-sync.sh" }
]
}
]
}
}

The hook should be fast (under a second) and silent on the happy path. It only logs if it actually pulled — a one-line “Updated to 2026.05.21 (3 skills changed)” notice tells the developer what’s new without interrupting flow.

Some teams add a soft version check: the hook reads version.json from the repo and compares it to a min_skills_version in the project’s AGENTS.md. If the repo is older than the project requires, the hook nags the developer to update — so a project that depends on a newer skill never silently fails on a stale dev machine.

Two operational problems show up once skills exist: discovery (“does a skill for this exist?”) and versioning (“when this skill changed, did anyone notice?”).

Discovery. Claude Code’s /skills command lists every loaded skill with its frontmatter description. Enough for most teams, but the high-functioning ones also publish an internal index — a Notion page, a README.md in the repo, or a Backstage entry — grouped by domain (auth/, infra/, payments/, frontend/) with an owner per entry.

Versioning. Two tactics that work in 2026: semantic versioning on the repo (tagged releases like v2026.05.21) so the bootstrap can pin or track main, and a CHANGELOG.md updated by every PR so seniors catch overlapping or breaking changes. Pair with a CI job that pings the listed owner on PRs touching skills/<name>/SKILL.md and a skill never silently changes behavior under its owner.

Step-by-step: rolling out a company skills repo

Section titled “Step-by-step: rolling out a company skills repo”
  1. Create the repo and seed three skills you can ship today.

    Pick three pieces of institutional knowledge you currently re-explain in Slack at least once a sprint — “how we refactor a route handler,” “how we add a D1 migration,” “how we ship a Polar webhook fix.” Write each as skills/<name>/SKILL.md with frontmatter, mental model, steps, and traps. Three is enough to prove the format; the rest will follow.

  2. Write the bootstrap script and dogfood it yourself first.

    Run it on your own laptop, open Claude Code, type /skills, confirm your three seed skills show up. Then break something on purpose — delete a symlink, edit a file directly — and re-run. If it doesn’t fix state idempotently, fix that before handing it to anyone else.

  3. Add the SessionStart hook and verify auto-sync.

    Register the hook in ~/.claude/settings.json, push a tiny change to the repo from a different machine, open a new Claude Code session, confirm the hook ran and the local checkout updated. Seeing “Updated to 2026.05.21” appear on its own is when the system feels real.

  4. Roll out to one team first, not the whole org.

    Pick five to ten engineers and sit with them while they run bootstrap.sh. Watch what breaks — corporate dotfiles managers, fish vs. zsh, non-default ~/.claude/ locations. Fix the bootstrap until it’s turnkey for that team. Only then expand.

  5. Promote at least one skill per sprint from “tribal” to “repo’d.”

    When a senior answers a question that’s been asked before, the answer becomes a skill PR by end of day. Enforce in retros: “we explained X three times — whose name is on the PR to skill-ify it?” Velocity beats polish. A scrappy skill that exists beats a perfect skill that doesn’t.

  6. Add discovery and ownership metadata.

    After a dozen skills, add a README.md grouped by domain with owners, plus CODEOWNERS so PRs to skills/auth/** auto-request review from the auth team. Without ownership, skills decay fast.

  7. Wire the bootstrap into your onboarding doc.

    The new-hire setup script (Homebrew, SSH keys, monorepo clone) should also run curl -fsSL .../agent-skills/install | bash. That’s the moment you cross from “we have a skill repo” to “every new hire walks in with every skill loaded” — the Q6 max-score state.

  8. Review quarterly.

    Every quarter, audit the repo. Delete skills nobody uses (Claude Code logs loads — pull the numbers). Merge near-duplicates. Promote skills that should be project-level rules into .claude/rules/. The repo is living code, not a dumping ground.

Skills written by one person, never used by anyone else. The classic failure mode. A senior writes a skill, ships it, assumes the team is using it — but nobody knows it exists, or the frontmatter description is so vague the agent never loads it. Fix is two-sided: ruthless description: fields that mirror how a teammate actually asks (“when the user says ‘fix auth’ or ‘refactor signin’”), plus a discovery pass at standup (“we shipped these three skills this sprint, here’s what they do”).

No versioning, no review. A repo with no CHANGELOG, no PR review, and no owners decays into chaos within a quarter. Skills overlap, contradict, and reference scripts that no longer exist. Treat it like any other production artifact — PRs, CODEOWNERS, CI checks. If “anyone can push to main” is the rule, seniors stop writing skills because they can’t trust the state.

Copying instead of symlinking. Some teams copy into ~/.claude/skills/ instead of symlinking. The first update never reaches anyone. Always symlink (or use Stow). The whole point is one git pull updates every tool.

No SessionStart hook. Without the auto-install hook, you’re back to “remember to pull the skills repo” — which means nobody does. The hook turns this from “a thing the team has” into “a thing the team uses without thinking about it.”

Skills that should be rules. A short “use double quotes in JSON, not single” rule belongs in .claude/rules/style.md, not in its own skill. Skills are for procedural, multi-step, “how do we do X” knowledge. Rules are for always-on conventions. Mixing them bloats the skill discovery surface.

Skills that depend on local state. A skill that says “first, cd to your monorepo” is brittle. One that runs git rev-parse --show-toplevel and works from anywhere is robust. Write skills as if they’ll run on a freshly-onboarded machine — with the SessionStart hook, they often will.

Personal skills mixed with company skills. Developers write their own (~/.claude/skills/<my-skill>/). Namespace the company repo’s symlinks (e.g., ~/.claude/skills/acme-<name>/) so a personal experiment can never overwrite a company skill, and vice versa.

Letting the repo sprawl. 200 skills is worse than 20. Most won’t be used; the ones that are will be buried. Set a quarterly cull as a real calendar event. Skills not loaded in two quarters get archived (moved to skills/.archive/, not deleted).

  • A company agent-skills repo exists with at least 5 production-quality skills.
  • Each skill folder has a SKILL.md with frontmatter (name, description, when_to_use).
  • The repo has CODEOWNERS and a CHANGELOG.md updated on every change.
  • A bootstrap.sh clones/updates the repo and symlinks every skill into ~/.claude/skills/, ~/.cursor/skills/, ~/.codex/skills/.
  • The bootstrap is idempotent — running it five times produces the same end state.
  • A SessionStart hook in ~/.claude/settings.json runs the sync on every new session.
  • A new hire’s day-1 setup script invokes the bootstrap automatically.
  • An internal index (Notion, Backstage, or README.md) lists every skill grouped by domain with an owner per entry.
  • Seniors ship at least one new skill per sprint; “this came up three times — file the skill” is normalized.
  • A quarterly audit removes or archives skills that haven’t been loaded.
  • Open a fresh Claude Code session, type /skills, every company skill shows up — without running anything manually.