Skip to content

Commit df17b88

Browse files
authored
feat(skills): add skills (#16)
* feat(skills): add skills * ref(skills): update skills after testing * fix(pub): update files * fix(pub): update plugin.json * fix(pub): remove plugin * feat(skills): run tanstack intent * feat(skills): update instructions * Revise skills description and installation steps Updated the description for coding agent skills and installation instructions.
1 parent 3a5c501 commit df17b88

File tree

19 files changed

+2446
-8
lines changed

19 files changed

+2446
-8
lines changed

.changeset/thirty-jeans-retire.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@bomb.sh/tools": minor
3+
---
4+
5+
Adds skills for coding agents. Eight skills cover the full `bsh` toolchain — lifecycle, lint, build, test, format, dev, init, and migration for onboarding an existing project.
6+
7+
If you use an AI coding agent, run `pnpm add -D @bomb.sh/tools` then have your agent run `pnpm dlx @tanstack/intent@latest install` to load project-specific skills for `@bomb.sh/tools`.

.github/workflows/check-skills.yml

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# check-skills.yml — Drop this into your library repo's .github/workflows/
2+
#
3+
# Checks for stale intent skills after a release and opens a review PR
4+
# if any skills need attention. The PR body includes a prompt you can
5+
# paste into Claude Code, Cursor, or any coding agent to update them.
6+
#
7+
# Triggers: new release published, or manual workflow_dispatch.
8+
#
9+
# Template variables (replaced by `intent setup`):
10+
# @bomb.sh/tools — e.g. @tanstack/query or my-workspace workspace
11+
12+
name: Check Skills
13+
14+
on:
15+
release:
16+
types: [published]
17+
workflow_dispatch: {}
18+
19+
permissions:
20+
contents: write
21+
pull-requests: write
22+
23+
jobs:
24+
check:
25+
name: Check for stale skills
26+
runs-on: ubuntu-latest
27+
steps:
28+
- name: Checkout
29+
uses: actions/checkout@v4
30+
with:
31+
fetch-depth: 0
32+
33+
- name: Setup Node
34+
uses: actions/setup-node@v4
35+
with:
36+
node-version: 20
37+
38+
- name: Install intent
39+
run: npm install -g @tanstack/intent
40+
41+
- name: Check staleness
42+
id: stale
43+
run: |
44+
OUTPUT=$(intent stale --json 2>&1) || true
45+
echo "$OUTPUT"
46+
47+
# Check if any skills need review
48+
NEEDS_REVIEW=$(echo "$OUTPUT" | node -e "
49+
const input = require('fs').readFileSync('/dev/stdin','utf8');
50+
try {
51+
const reports = JSON.parse(input);
52+
const stale = reports.flatMap(r =>
53+
r.skills.filter(s => s.needsReview).map(s => ({ library: r.library, skill: s.name, reasons: s.reasons }))
54+
);
55+
if (stale.length > 0) {
56+
console.log(JSON.stringify(stale));
57+
}
58+
} catch {}
59+
")
60+
61+
if [ -z "$NEEDS_REVIEW" ]; then
62+
echo "has_stale=false" >> "$GITHUB_OUTPUT"
63+
else
64+
echo "has_stale=true" >> "$GITHUB_OUTPUT"
65+
# Escape for multiline GH output
66+
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
67+
echo "stale_json<<$EOF" >> "$GITHUB_OUTPUT"
68+
echo "$NEEDS_REVIEW" >> "$GITHUB_OUTPUT"
69+
echo "$EOF" >> "$GITHUB_OUTPUT"
70+
fi
71+
72+
- name: Build summary
73+
if: steps.stale.outputs.has_stale == 'true'
74+
id: summary
75+
run: |
76+
node -e "
77+
const stale = JSON.parse(process.env.STALE_JSON);
78+
const lines = stale.map(s =>
79+
'- **' + s.skill + '** (' + s.library + '): ' + s.reasons.join(', ')
80+
);
81+
const summary = lines.join('\n');
82+
83+
const prompt = [
84+
'Review and update the following stale intent skills for @bomb.sh/tools:',
85+
'',
86+
...stale.map(s => '- ' + s.skill + ': ' + s.reasons.join(', ')),
87+
'',
88+
'For each stale skill:',
89+
'1. Read the current SKILL.md file',
90+
'2. Check what changed in the library since the skill was last updated',
91+
'3. Update the skill content to reflect current APIs and behavior',
92+
'4. Run \`npx @tanstack/intent validate\` to verify the updated skill',
93+
].join('\n');
94+
95+
// Write outputs
96+
const fs = require('fs');
97+
const env = fs.readFileSync(process.env.GITHUB_OUTPUT, 'utf8');
98+
const eof = require('crypto').randomBytes(15).toString('base64');
99+
fs.appendFileSync(process.env.GITHUB_OUTPUT,
100+
'summary<<' + eof + '\n' + summary + '\n' + eof + '\n' +
101+
'prompt<<' + eof + '\n' + prompt + '\n' + eof + '\n'
102+
);
103+
"
104+
env:
105+
STALE_JSON: ${{ steps.stale.outputs.stale_json }}
106+
107+
- name: Open review PR
108+
if: steps.stale.outputs.has_stale == 'true'
109+
env:
110+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
111+
run: |
112+
VERSION="${{ github.event.release.tag_name || 'manual' }}"
113+
BRANCH="skills/review-${VERSION}"
114+
115+
git config user.name "github-actions[bot]"
116+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
117+
git checkout -b "$BRANCH"
118+
git commit --allow-empty -m "chore: review stale skills for ${VERSION}"
119+
git push origin "$BRANCH"
120+
121+
gh pr create \
122+
--title "Review stale skills (${VERSION})" \
123+
--body "$(cat <<'PREOF'
124+
## Stale Skills Detected
125+
126+
The following skills may need updates after the latest release:
127+
128+
${{ steps.summary.outputs.summary }}
129+
130+
---
131+
132+
### Update Prompt
133+
134+
Paste this into your coding agent (Claude Code, Cursor, etc.):
135+
136+
~~~
137+
${{ steps.summary.outputs.prompt }}
138+
~~~
139+
140+
PREOF
141+
)" \
142+
--head "$BRANCH" \
143+
--base main
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# notify-intent.yml — Drop this into your library repo's .github/workflows/
2+
#
3+
# Fires a repository_dispatch event whenever docs or source files change
4+
# on merge to main. This triggers the skill staleness check workflow.
5+
#
6+
# Requirements:
7+
# - A fine-grained PAT with contents:write on this repository stored
8+
# as the INTENT_NOTIFY_TOKEN repository secret.
9+
#
10+
# Template variables (replaced by `intent setup`):
11+
# @bomb.sh/tools — e.g. @tanstack/query or my-workspace workspace
12+
# docs/** — e.g. docs/**
13+
# src/** — e.g. packages/query-core/src/**
14+
15+
name: Trigger Skill Review
16+
17+
on:
18+
push:
19+
branches: [main]
20+
paths:
21+
- "docs/**"
22+
- "src/**"
23+
24+
jobs:
25+
notify:
26+
name: Trigger Skill Review
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 2
33+
34+
- name: Collect changed files
35+
id: changes
36+
run: |
37+
FILES=$(git diff --name-only HEAD~1 HEAD | jq -R -s -c 'split("\n") | map(select(length > 0))')
38+
echo "files=$FILES" >> "$GITHUB_OUTPUT"
39+
40+
- name: Dispatch to intent repo
41+
uses: peter-evans/repository-dispatch@v3
42+
with:
43+
token: ${{ secrets.INTENT_NOTIFY_TOKEN }}
44+
repository: ${{ github.repository }}
45+
event-type: skill-check
46+
client-payload: |
47+
{
48+
"package": "@bomb.sh/tools",
49+
"sha": "${{ github.sha }}",
50+
"changed_files": ${{ steps.changes.outputs.files }}
51+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# validate-skills.yml — Drop this into your library repo's .github/workflows/
2+
#
3+
# Validates skill files on PRs that touch the skills/ directory.
4+
# Ensures frontmatter is correct, names match paths, and files stay under
5+
# the 500-line limit.
6+
7+
name: Validate Skills
8+
9+
on:
10+
pull_request:
11+
paths:
12+
- "skills/**"
13+
- "**/skills/**"
14+
15+
jobs:
16+
validate:
17+
name: Validate skill files
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Setup Node
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: 20
27+
28+
- name: Install intent CLI
29+
run: npm install -g @tanstack/intent
30+
31+
- name: Find and validate skills
32+
run: |
33+
# Find all directories containing SKILL.md files
34+
SKILLS_DIR=""
35+
if [ -d "skills" ]; then
36+
SKILLS_DIR="skills"
37+
elif [ -d "packages" ]; then
38+
# Monorepo — find skills/ under packages
39+
for dir in packages/*/skills; do
40+
if [ -d "$dir" ]; then
41+
echo "Validating $dir..."
42+
intent validate "$dir"
43+
fi
44+
done
45+
exit 0
46+
fi
47+
48+
if [ -n "$SKILLS_DIR" ]; then
49+
intent validate "$SKILLS_DIR"
50+
else
51+
echo "No skills/ directory found — skipping validation."
52+
fi

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ If you'd like to use this package for your own projects, please consider forking
1111
- `bsh format` command, using [`oxfmt`](https://oxc.rs/docs/guide/usage/formatter)
1212
- `bsh lint` command, using [`oxlint`](https://oxc.rs/docs/guide/usage/linter), [`publint`](https://publint.dev/), [`knip`](https://knip.dev), [`tsgo`](https://npmx.dev/@typescript/native-preview)
1313
- shared `tsconfig.json` file
14+
15+
## Agent Skills
16+
17+
If you use an AI coding agent, run `pnpm add -D @bomb.sh/tools` then have your agent run `pnpm dlx @tanstack/intent@latest install` to load project-specific skills for `@bomb.sh/tools`.

package.json

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"keywords": [
66
"bombshell",
77
"cli",
8-
"internal"
8+
"internal",
9+
"skills",
10+
"tanstack-intent"
911
],
1012
"homepage": "https://bomb.sh",
1113
"license": "MIT",
@@ -21,11 +23,22 @@
2123
"bin": {
2224
"bsh": "dist/bin.mjs"
2325
},
26+
"files": [
27+
"dist",
28+
"skills",
29+
"!skills/_artifacts",
30+
".claude-plugin",
31+
"tsconfig.json",
32+
"package.json",
33+
"oxfmtrc.json",
34+
"oxlintrc.json"
35+
],
2436
"type": "module",
2537
"exports": {
2638
".": {
2739
"import": "./dist/bin.mjs"
2840
},
41+
"./skills/*": "./skills/*",
2942
"./test-utils": {
3043
"types": "./dist/test-utils.d.mts",
3144
"import": "./dist/test-utils.mjs"
@@ -61,6 +74,7 @@
6174
},
6275
"devDependencies": {
6376
"@changesets/cli": "^2.28.1",
77+
"@tanstack/intent": "^0.0.23",
6478
"@types/node": "^22.13.14"
6579
},
6680
"volta": {

0 commit comments

Comments
 (0)