Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/check-skill-names.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Skill names

on:
pull_request:
push:
branches:
- main

jobs:
skill-names:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: node scripts/check-skill-names.mjs
52 changes: 52 additions & 0 deletions scripts/check-skill-names.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env node
import { execFileSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import process from "node:process";

const files = execFileSync("git", ["ls-files", "-z", "--", "*SKILL.md"], {
encoding: "utf8",
})
.split("\0")
.filter(Boolean);

const frontmatterName = (raw) => {
const lines = raw.split(/\r?\n/);
if (lines[0] !== "---") return undefined;
const end = lines.indexOf("---", 1);
if (end === -1) return undefined;
for (const line of lines.slice(1, end)) {
const match = /^name:\s*(.*)$/.exec(line);
if (!match) continue;
const trimmed = match[1].trim();
if (
trimmed.length >= 2 &&
((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
(trimmed.startsWith("'") && trimmed.endsWith("'")))
) {
return trimmed.slice(1, -1).trim();
}
return trimmed;
}
return undefined;
};

const records = files.map((file) => ({
path: file,
folder: path.basename(path.dirname(file)),
name: frontmatterName(fs.readFileSync(file, "utf8")),
}));

const mismatches = records.filter((record) => record.name !== record.folder);
for (const record of mismatches) {
if (record.name === undefined) {
console.error(`${record.path}: missing frontmatter name`);
} else {
console.error(
`${record.path}: name "${record.name}" does not match folder "${record.folder}"`,
);
}
}
if (mismatches.length) process.exit(1);

console.log(`${records.length} skill names match their folders`);
2 changes: 1 addition & 1 deletion skills/make-bot-ui/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: Make Bot UI
name: make-bot-ui
description: >-
Use when building a custom UI (page, dashboard, buttons) that should wake a
Grok Bot over a webhook, when the user must provide a webhook sender key, or
Expand Down
2 changes: 1 addition & 1 deletion skills/odd-mode/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: Odium Mode
name: odd-mode
description: odium's agent style for concise, detailed responses, deliberate subagents, unslopped prose, simple code, and verified work. Use for odium, /odd-mode, or requests to work in this style.
disable-model-invocation: true
mode: true
Expand Down
Loading