Install
$ agentstack add skill-wyattjoh-skills-reference-submodules ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Reference Submodules
Manage context repositories as shallow git submodules under .claude/references/, pinned to the matching version tag, so dependency source is available offline and the project's CLAUDE.md "Dependency References" table stays accurate.
Arguments provided: $ARGUMENTS
Requires: git 2.23+ (the workflow uses git submodule set-branch, added in 2.22, and git restore, added in 2.23). gh is optional (used for tag listing on private repos).
This skill manages references. Consuming them (preferring local reference source over web docs) is an always-on rule in global CLAUDE.md, not this skill.
Quick Start
/reference-submodules addto vendor a repo at the matching tag/reference-submodules upgradeto bump an existing reference/reference-submodules syncto populate references after a fresh clone/reference-submodules removeto cleanly remove one
If no argument is given, infer intent from context (a URL implies add; an empty .claude/references/ with .gitmodules entries implies sync).
Preconditions
Check these before any mutating operation. Each is a place the raw git commands fail confusingly:
- Host must be a git repo with at least one commit. Run
git rev-parse --git-dir.
If it fails, stop and offer git init (submodules cannot be added otherwise).
- Already added? Check
.gitmodulesfor the target path. If present, do not
re-add: route to the upgrade flow instead.
Version resolution
Shared by add and upgrade. Follow this order and confirm the resolved ref before mutating .gitmodules.
- Dependency name (for the directory and table):
- Directory name = repo name (last URL segment, strip
.git), e.g.
vercel/next.js -> next.js.
- Table "Dependency" name = the package name if the repo maps to a tracked
project dependency (e.g. npm next), otherwise the repo name.
- Target version, in priority order:
- (a) Match the installed dependency. If the repo is a recognized
dependency, read its resolved version from the project manifest/lockfile (package.json + lockfile, requirements.txt, Cargo.toml, go.mod, etc.). Pin to the tag matching that version.
- (b) Latest release tag. Otherwise use the newest tag.
- (c) Default branch HEAD. If the repo has no tags, pin to the default
branch and record the commit.
- Match the tag naming scheme. List tags with
git ls-remote --tags (or gh api repos///tags for private repos). Find the tag whose normalized version equals the target. Common schemes (a single repo uses one):
v(e.g.v15.1.0) — most common- `
(bare, e.g.15.1.0`) @or@scope/pkg@(monorepos, e.g.turbo@2.0.0)
- Confirm the resolved
{dependency, directory, url, ref}with the user,
then proceed.
Sub-commands
add
- Run the Preconditions checks. If the path already exists in
.gitmodules,
switch to upgrade.
- Run Version resolution, then confirm.
- Add the submodule. Never use
git submodule add -b—-bnames a
branch, and a shallow clone has no history to synthesize a branch from a tag, so it always fails with fatal: '' is not a commit. Clone first, then fetch and check out the tag explicitly:
- With a tag:
``bash git submodule add --depth 1 .claude/references/ cd .claude/references/ git fetch --depth 1 origin tag git checkout cd - git submodule set-branch --branch -- .claude/references/ git add .gitmodules .claude/references/ ``
- No-tag fallback (default branch): add as-is, then record the commit:
``bash git submodule add --depth 1 .claude/references/ ``
- Verify the add landed as a submodule, not a flattened directory tree: run
git ls-files -s .claude/references/ and confirm it shows exactly one 160000 gitlink entry. Many regular-file (100644) entries means the index got corrupted during a retry (see Edge cases) — reset and redo the add before continuing.
- Update the CLAUDE.md table (see below).
- Report the path, pinned ref, and that
.gitmodules+ the gitlink are staged.
Remind the user to commit.
upgrade [version]
Bump an existing reference to a new tag (or the matching installed version).
- Locate the entry in
.gitmodules(path.claude/references/). If
absent, suggest add.
- Resolve the new ref via Version resolution. If
versionwas given, use it
verbatim after confirming the tag exists. Confirm.
- Fetch and check out the new ref, then update the tracked branch:
``bash cd .claude/references/ git fetch --depth 1 origin tag git checkout cd - git submodule set-branch --branch -- .claude/references/ git add .gitmodules .claude/references/ ``
- Update the version cell in the CLAUDE.md table.
- Report old -> new ref. Remind the user to commit.
remove
Submodule removal is multi-step; doing only git rm leaves stale config behind.
- Deinit, then remove from the working tree and
.gitmodules:
``bash git submodule deinit -f .claude/references/ git rm -f .claude/references/ ``
- Clean the stored git module so a future re-add does not collide:
``bash rm -rf .git/modules/.claude/references/ ``
- If that was the last reference,
.gitmodulesis now empty — don't leave an
empty tracked file staged:
- Already committed before this session: stage its deletion with
git rm .gitmodules.
- Newly created earlier in this session (first-ever reference, never
committed): unstage and delete it directly with git restore --staged .gitmodules && rm -f .gitmodules.
- Remove the row from the CLAUDE.md table. If it was the last row, remove the
now-empty "Dependency References" subsection.
- Report what was removed. Remind the user to commit (
git rmalready staged
.gitmodules and the gitlink removal).
sync
Populate or refresh references (e.g. after a fresh clone where .claude/references/ is empty but .gitmodules has entries).
git submodule sync --recursive
git submodule update --init --recursive --depth 1
Read-only with respect to project config (no .gitmodules/table edits). Report which references were initialized.
help
Print the sub-commands above with one-line descriptions. Read-only.
CLAUDE.md table format
Maintain a "Dependency References" subsection in the project root CLAUDE.md:
### Dependency References
| Dependency | Version | Path |
| ---------- | ------- | ----------------------------- |
| next | 15.1.0 | `.claude/references/next.js/` |
Rules when editing:
- If the subsection is absent, create it (a sensible home is a "Dependency
Management" or "Dependencies" area; otherwise append near the end).
- Version cell: the bare version for a tag (
15.1.0, notv15.1.0); for a
no-tag fallback use @ (e.g. main@a1b2c3d).
- Keep rows sorted by Dependency and deduplicated (one row per path).
- On
remove, delete the matching row; drop the subsection if it becomes empty.
Confirmation gate rules
Never execute without showing the plan first:
git submodule add/set-branch,git checkoutof a new refgit submodule deinit,git rm,rm -rf .git/modules/...- Edits to
CLAUDE.md
Always allowed without confirmation (read-only):
git rev-parse,git ls-remote,git config --getgh api .../tags,git submodule statusgit submodule sync/update --init(thesynccommand)
Edge cases
- Not a git repo / no commits: stop, offer
git init(see Preconditions). - Already added: route to
upgrade, never re-add. - Private repo / auth failure: use the URL form the user provided; if HTTPS
auth fails, suggest the SSH URL (git@github.com:org/repo.git). Do not manage credentials. Use gh api for tag listing when git ls-remote is unauthorized.
- No tags found: fall back to default-branch HEAD; record
@in
the table (resolution step 2c).
- Reproducibility: every reference resolves to a fixed tag or commit, never a
moving branch tip without a recorded sha.
- Failed
addleaves partial state: if an add fails partway (bad ref,
interrupted checkout), clean up atomically before retrying — git submodule deinit -f (if registered), git rm -f (if staged), rm -rf .git/modules/, and remove any stray submodule. section from .git/config. Confirm git status --short is clean for that path before retrying. A partial retry without full cleanup can stage the dependency's entire source tree as regular files in the host repo instead of a submodule gitlink — this is why step 4 of add always verifies with git ls-files -s.
- Cleanup
rm -rfblocked by a destructive-command guard: if `rm -rf
.git/modules/ is blocked in the current environment, prefer salvaging over asking the user to run it by hand — a failed tag checkout usually still has the objects fetched, so retry git fetch --depth 1 origin tag and git checkout ` directly inside the existing clone instead of deleting and re-cloning. Only ask the user to run cleanup manually if salvage isn't possible.
- Monorepo tag verification: don't verify a checked-out ref with `git
describe --tags in a repo with multiple co-located scoped tags (e.g. agents@0.16.2 and @cloudflare/think@0.10.0 on the same commit) — it can report an arbitrary sibling tag instead of the one you checked out. Verify by comparing git rev-parse HEAD against the commit resolved from git ls-remote --tags ` instead.
- Don't background the add/upgrade git commands without checking their
captured output: a shallow-clone tag failure can still exit 0 at the top level even though the checkout underneath failed. Confirm the ref actually resolved (the git ls-files -s verification) before reporting success.
- Parallel worktrees adding different references: rebasing one branch onto
another that also ran add can conflict in both .gitmodules and the CLAUDE.md table. Both sides are additive — resolve by keeping both entries (both submodule sections, both table rows), not by picking one side.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: wyattjoh
- Source: wyattjoh/skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.