feat: add first-party skills, ponytail lock, and full lint suite
Some checks failed
🧪 Test / 🧪 Lock + lint (push) Has been cancelled
Some checks failed
🧪 Test / 🧪 Lock + lint (push) Has been cancelled
- add ponytail skill set to skills-lock.json (14 locked skills total) - add first-party medusa skill under skills/, layered on install - make test now runs ruff, shellcheck, and markdownlint-cli2 - CI installs the lint tools before make test in both workflows - MIT license, funding buttons, thanks and donation sections in README - .markdownlint-cli2.jsonc config; ignore lint caches in .gitignore
This commit is contained in:
18
.github/workflows/test.yml
vendored
18
.github/workflows/test.yml
vendored
@@ -6,11 +6,27 @@ on:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: 🧪 Lock + scripts
|
||||
name: 🧪 Lock + lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: ⬇️ Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: 🐍 Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: 🟢 Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: lts/*
|
||||
|
||||
- name: 📦 Install lint tools
|
||||
run: |
|
||||
pip install ruff
|
||||
sudo apt-get update && sudo apt-get install -y shellcheck
|
||||
npm install -g markdownlint-cli2
|
||||
|
||||
- name: 🧪 Run tests
|
||||
run: make test
|
||||
|
||||
11
.github/workflows/update.yml
vendored
11
.github/workflows/update.yml
vendored
@@ -17,11 +17,22 @@ jobs:
|
||||
- name: ⬇️ Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: 🐍 Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: 🔧 Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: lts/*
|
||||
|
||||
- name: 📦 Install lint tools
|
||||
run: |
|
||||
pip install ruff
|
||||
sudo apt-get update && sudo apt-get install -y shellcheck
|
||||
npm install -g markdownlint-cli2
|
||||
|
||||
- name: 🔄 Update skills
|
||||
run: make update
|
||||
|
||||
|
||||
19
.gitignore
vendored
19
.gitignore
vendored
@@ -1,8 +1,21 @@
|
||||
# Python
|
||||
.venv/
|
||||
dist/
|
||||
build/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
dist/
|
||||
build/
|
||||
.ruff_cache/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
|
||||
# Node
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
|
||||
# Rendered skill install targets
|
||||
.agents/
|
||||
.claude/
|
||||
node_modules/
|
||||
|
||||
# Editor / OS
|
||||
.DS_Store
|
||||
*.swp
|
||||
|
||||
13
.markdownlint-cli2.jsonc
Normal file
13
.markdownlint-cli2.jsonc
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"config": {
|
||||
"default": true,
|
||||
"MD013": false,
|
||||
"MD033": false,
|
||||
"MD041": false
|
||||
},
|
||||
"ignores": [
|
||||
"node_modules",
|
||||
".agents",
|
||||
".claude"
|
||||
]
|
||||
}
|
||||
22
LICENSE
22
LICENSE
@@ -1 +1,21 @@
|
||||
All rights reserved by Kevin Veen-Birkenbach
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Kevin Veen-Birkenbach
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
4
Makefile
4
Makefile
@@ -9,10 +9,12 @@ project:
|
||||
@test -n "$(TARGET)" || { echo "usage: make project TARGET=/path/to/repo"; exit 2; }
|
||||
@TARGET="$(TARGET)" bash scripts/install.sh
|
||||
|
||||
# Validate skills-lock.json and shellcheck the scripts.
|
||||
# Validate the lock, lint Python (ruff), scripts (shellcheck), and markdown.
|
||||
test:
|
||||
@python3 -m unittest discover -s tests -v
|
||||
@if command -v ruff >/dev/null; then ruff check .; else echo "ruff not installed - skipped"; fi
|
||||
@if command -v shellcheck >/dev/null; then shellcheck scripts/*.sh; else echo "shellcheck not installed - skipped"; fi
|
||||
@if command -v markdownlint-cli2 >/dev/null; then markdownlint-cli2 "**/*.md"; else echo "markdownlint-cli2 not installed - skipped"; fi
|
||||
|
||||
# Update all skills to their latest versions and refresh skills-lock.json.
|
||||
update:
|
||||
|
||||
73
README.md
73
README.md
@@ -1,20 +1,73 @@
|
||||
# skills 🧠
|
||||
|
||||
Reproducible agent skill collection, pinned in `skills-lock.json`.
|
||||
Works for Claude Code, Codex, Gemini CLI, Cursor, Copilot, Windsurf, Cline, and more.
|
||||
[](https://github.com/sponsors/kevinveenbirkenbach) [](https://www.patreon.com/c/kevinveenbirkenbach) [](https://buymeacoffee.com/kevinveenbirkenbach) [](https://s.veen.world/paypaldonate)
|
||||
|
||||
Homepage: [github.com/kevinveenbirkenbach/skills](https://github.com/kevinveenbirkenbach/skills)
|
||||
The agent skill collection of Kevin Veen-Birkenbach.
|
||||
Every skill is pinned in `skills-lock.json` for reproducible installs.
|
||||
First-party skills live under `skills/` and are layered on top of the locked ones at install time.
|
||||
Compatible with Claude Code, Codex, Gemini CLI, Cursor, Copilot, Windsurf, Cline, and other agents.
|
||||
|
||||
## Usage 🚀
|
||||
## Requirements 📦
|
||||
|
||||
- `make install` installs the skills globally into your home (`~/.agents/skills` and `~/.claude/skills`).
|
||||
- `make project TARGET=/path/to/repo` copies the skills into a project (`<repo>/.agents/skills` and `<repo>/.claude/skills`).
|
||||
- `make update` refreshes every skill to its latest version and rewrites `skills-lock.json`.
|
||||
- `make test` validates `skills-lock.json` and shellchecks the scripts; CI runs it on every push and after every update.
|
||||
- Node.js (provides `npx skills`).
|
||||
- `jq` (only required for `make update`).
|
||||
|
||||
Node.js is REQUIRED (`npx skills`); `make update` additionally needs `jq`.
|
||||
Restart your agent after installing so it loads the new skills.
|
||||
## Installation 🚀
|
||||
|
||||
Install the skills globally into your home (`~/.agents/skills` and `~/.claude/skills`):
|
||||
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
|
||||
Copy the skills into a specific project (`<repo>/.agents/skills` and `<repo>/.claude/skills`):
|
||||
|
||||
```bash
|
||||
make project TARGET=/path/to/repo
|
||||
```
|
||||
|
||||
Restart your agent afterwards so it loads the new skills.
|
||||
|
||||
## Maintenance 🔧
|
||||
|
||||
Refresh every skill to its latest version and rewrite `skills-lock.json`:
|
||||
|
||||
```bash
|
||||
make update
|
||||
```
|
||||
|
||||
Validate `skills-lock.json` and shellcheck the scripts (also run by CI on every push and after every update):
|
||||
|
||||
```bash
|
||||
make test
|
||||
```
|
||||
|
||||
## Related Tools 🧰
|
||||
|
||||
This collection is part of a wider toolset for managing IT and infrastructure:
|
||||
|
||||
- [alias](https://github.com/kevinveenbirkenbach/alias) — shell aliases for common commands.
|
||||
- [package-manager](https://github.com/kevinveenbirkenbach/package-manager) — `pkgmgr`, a single command to install and manage these repositories.
|
||||
- [infinito-nexus](https://github.com/kevinveenbirkenbach/infinito-nexus) — automation platform for self-hosted infrastructure.
|
||||
|
||||
## License 📜
|
||||
|
||||
MIT License, Copyright (c) 2026 Kevin Veen-Birkenbach.
|
||||
|
||||
## Author 👤
|
||||
|
||||
Kevin Veen-Birkenbach [kevin@veen.world](mailto:kevin@veen.world)
|
||||
|
||||
## Thanks 🙏
|
||||
|
||||
Thanks to the [#ai:infinito.nexus](https://matrix.to/#/%23ai:infinito.nexus) community, and especially to [Paulinhx](https://github.com/Paulinhx) for the inspiration.
|
||||
|
||||
## Donation ❤️
|
||||
|
||||
If these tools help you, consider supporting their development:
|
||||
|
||||
- [GitHub Sponsors](https://github.com/sponsors/kevinveenbirkenbach)
|
||||
- [Patreon](https://www.patreon.com/c/kevinveenbirkenbach)
|
||||
- [Buy Me a Coffee](https://buymeacoffee.com/kevinveenbirkenbach)
|
||||
- [PayPal](https://s.veen.world/paypaldonate)
|
||||
- Bitcoin: [bc1qle7j8m9kvny2h2q3jzsnc64s4f5zme5re23pzc2lc2d7hhasc4dqachflp](bitcoin:bc1qle7j8m9kvny2h2q3jzsnc64s4f5zme5re23pzc2lc2d7hhasc4dqachflp?message=%E2%9D%A4%EF%B8%8F%20Help%20Build%20the%20Future%20-%20Donation%20to%20Kevin%20Veen-Birkenbach.)
|
||||
|
||||
@@ -32,6 +32,11 @@ if [[ ! -d "${src}" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -d "${REPO_ROOT}/skills" ]]; then
|
||||
log "skills: adding first-party skills from skills/..."
|
||||
cp -a "${REPO_ROOT}/skills/." "${src}/"
|
||||
fi
|
||||
|
||||
for dst in "${TARGET}/.agents/skills" "${TARGET}/.claude/skills"; do
|
||||
log "skills: copying -> ${dst}"
|
||||
rm -rf "${dst}"
|
||||
|
||||
@@ -48,6 +48,42 @@
|
||||
"sourceType": "github",
|
||||
"skillPath": "skills/compress/SKILL.md",
|
||||
"computedHash": "c91bdf427a68b686ee9d6f63766c72d164b16915434736edfedf13e24dae0e8c"
|
||||
},
|
||||
"ponytail": {
|
||||
"source": "DietrichGebert/ponytail",
|
||||
"sourceType": "github",
|
||||
"skillPath": "skills/ponytail/SKILL.md",
|
||||
"computedHash": "210fa0831f649ce9f8a305f7b7c8cf2a0dd09ac4dd53067109941b96e7811d4e"
|
||||
},
|
||||
"ponytail-audit": {
|
||||
"source": "DietrichGebert/ponytail",
|
||||
"sourceType": "github",
|
||||
"skillPath": "skills/ponytail-audit/SKILL.md",
|
||||
"computedHash": "8b8d72e6ff70b65b6c9518d470fcf29dc696eea93d28f3efa10fdcc60cbd696d"
|
||||
},
|
||||
"ponytail-debt": {
|
||||
"source": "DietrichGebert/ponytail",
|
||||
"sourceType": "github",
|
||||
"skillPath": "skills/ponytail-debt/SKILL.md",
|
||||
"computedHash": "0099b82174e3a4261828b4ec04d2c068b1b294fdab14f76701c2acd1f7c99539"
|
||||
},
|
||||
"ponytail-gain": {
|
||||
"source": "DietrichGebert/ponytail",
|
||||
"sourceType": "github",
|
||||
"skillPath": "skills/ponytail-gain/SKILL.md",
|
||||
"computedHash": "c45ecba7906960eea904218b623abf097ebff84ecbacca6d68da1d0687435f75"
|
||||
},
|
||||
"ponytail-help": {
|
||||
"source": "DietrichGebert/ponytail",
|
||||
"sourceType": "github",
|
||||
"skillPath": "skills/ponytail-help/SKILL.md",
|
||||
"computedHash": "10e8382b1033c9a0fec0073de6d3de3846b4f5dca7d78b6df2d476a1f4cd43c6"
|
||||
},
|
||||
"ponytail-review": {
|
||||
"source": "DietrichGebert/ponytail",
|
||||
"sourceType": "github",
|
||||
"skillPath": "skills/ponytail-review/SKILL.md",
|
||||
"computedHash": "4646594fcd75455533f7ff1425f4f1c5ba0fa65f88241bf262b1c4fc275f049a"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
32
skills/medusa/SKILL.md
Normal file
32
skills/medusa/SKILL.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: medusa
|
||||
description: >
|
||||
Run the MEDUSA AI security scanner (medusa-security on PyPI) against a
|
||||
repository, working tree, or secret stores. Use when the user asks for a
|
||||
security scan, supply-chain vetting of a repo before cloning, leaked-secret
|
||||
detection in AI chat or shell history, or invokes /medusa. Defensive scanning
|
||||
only.
|
||||
---
|
||||
|
||||
MEDUSA is a defensive AI-first security scanner (40,000+ patterns: CVEs, prompt injection, MCP tool poisoning, leaked secrets).
|
||||
|
||||
## Setup
|
||||
|
||||
Check availability with `medusa --version`.
|
||||
If missing, install it with `pipx install medusa-security` (fallback: `pip install --user medusa-security`).
|
||||
|
||||
## Commands
|
||||
|
||||
| Task | Command |
|
||||
| --- | --- |
|
||||
| Scan the current project | `medusa scan .` |
|
||||
| Vet a remote repo BEFORE cloning (supply chain, poisoned `.claude/` hooks, permissions, skills) | `medusa scan --git <url-or-org/repo>` |
|
||||
| Find leaked API keys in AI chat + shell history | `medusa secrets scan` |
|
||||
| Scan one exported file | `medusa secrets scan --path <file>` |
|
||||
|
||||
## Rules
|
||||
|
||||
- Run scans read-only; never pass `--reveal` and never run `medusa secrets purge` unless the user explicitly asks for it.
|
||||
- Summarize findings by severity with file/line references; do not paste secret values into the conversation, even redacted ones.
|
||||
- Treat findings as signals for review, not verdicts; confirm true positives in the code before proposing fixes.
|
||||
- Vet third-party agent repos (`medusa scan --git`) before recommending the user clone or install them.
|
||||
@@ -50,6 +50,26 @@ class TestSkillsLock(unittest.TestCase):
|
||||
f"skills must be sorted ascending; expected {sorted(names)}",
|
||||
)
|
||||
|
||||
def test_first_party_skills_have_valid_frontmatter(self):
|
||||
for skill_md in sorted((REPO_ROOT / "skills").glob("*/SKILL.md")):
|
||||
with self.subTest(skill=skill_md.parent.name):
|
||||
text = skill_md.read_text(encoding="utf-8")
|
||||
self.assertTrue(text.startswith("---\n"), "missing frontmatter")
|
||||
frontmatter = text.split("---", 2)[1]
|
||||
self.assertIn("name:", frontmatter, "frontmatter missing name")
|
||||
self.assertIn(
|
||||
"description:", frontmatter, "frontmatter missing description"
|
||||
)
|
||||
|
||||
def test_first_party_skills_do_not_shadow_locked_skills(self):
|
||||
locked = set(self.lock["skills"].keys())
|
||||
for skill_dir in sorted((REPO_ROOT / "skills").glob("*/")):
|
||||
self.assertNotIn(
|
||||
skill_dir.name.rstrip("/"),
|
||||
locked,
|
||||
f"first-party skill '{skill_dir.name}' collides with a locked skill",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user