A band above the prompt listing the files this turn edited and the checks still owed: format, lint, typecheck, tests.

Production-grade skills for AI coding agents (OpenClaw, Claude Code, and others).
Built by Fabricio Cavalcante — Software Engineer & AI Specialist.
Plugins are complete workflow bundles — skills + agents + hooks working together as an integrated system. Install a plugin to get the full experience.
| Plugin | Description | Platform |
|---|---|---|
| game-dev | 26 skills, 7 commands, 3 agents, 5 hooks — complete game development workflow with engineering, design, narrative, and infrastructure | Game Dev |
Mods are plugins built on function hooks: they run inside Claude Code, guard tool calls and draw above the prompt. See mods/ for install steps.
| Mod | Description |
|---|---|
| commit-guard | Blocks commits with machine paths or .env files, git add -A, and pushes to main |
| prod-guard | Holds Dokploy MCP writes until you press Proceed |
| bun-only | Rewrites npm, npx, yarn and pnpm to bun |
| done-gate | Shows edited files and the checks still owed |
| worktrees | Shows git worktrees, their changes, and the count |
| usage-rings | Context and plan usage, coloured by level |
| pr-status | The current branch's PR: CI checks and review |
| sql-guard | Holds writes to non-local databases until you press Proceed |
| pino-guard | Blocks pino transports that break bundled logging |
Skills are individual, cherry-pickable modules. Install only what you need.
| Skill | Description | Platform |
|---|---|---|
| claude-agent-sdk | Build production AI agents with the Claude Agent SDK — query(), hooks, subagents, custom tools, MCP servers, sessions, permissions, hosting | Claude Code / API |
| database-performance-tuning | Diagnose and fix slow databases like a DBA — pg_stat_statements, EXPLAIN plans, index design, query rewrites, vacuum and bloat, safe online rollout. Ships a read-only diagnostic script | PostgreSQL / MySQL |
| foundry-vtt-module-dev | Build, extend, and maintain Foundry VTT v14 modules — TypeDataModel, ApplicationV2 (detached windows), ActorSheetV2, hooks, sockets, dice, canvas/PIXI, Scene Levels, Regions as templates, ActiveEffects V2, v13→v14 migration, boilerplate files | Foundry VTT |
| foundry-vtt-system-dev | Build Foundry VTT v14 game systems — system.json documentTypes, Actor/Item TypeDataModel, dice mechanics, combat/initiative, ActiveEffect V2 subtypes, data migration, character sheets, status effects, macros, enrichers | Foundry VTT |
| openclaw-genie | Comprehensive OpenClaw gateway skill — installation, configuration, 38+ channels, memory, tools, hooks, deployment, multi-agent | OpenClaw |
| nuvemshop-sdk | Prepare, audit, implement, homologate, and publish Nuvemshop/Tiendanube apps — OAuth, API, NubeSDK, Nexo, Nimbus, webhooks, and App Store approval | Nuvemshop |
| react-animations | React animation patterns and utilities | React |
| Skill | Description |
|---|---|
| game-design-fundamentals | Core loops, MDA framework, progression curves |
| game-economy-design | Virtual economies, currencies, loot tables |
| level-design | Levels, environments, difficulty curves |
| procedural-gen | Dungeon gen, noise terrain, wave function collapse |
| quest-mission-design | Quests, objectives, quest trees |
| skill-progression-trees | Skill trees, talent trees, unlock graphs |
| ui-ux-game | HUD, menus, onboarding, accessibility |
| Skill | Description |
|---|---|
| betterauth-integration | Auth, OAuth, JWT, RBAC |
| bullmq-game-queues | Job queues, async events, scheduled tasks |
| elevenlabs-sound-music | SFX generation, adaptive music, voice acting |
| game-backend-architecture | Game servers, WebSocket, rooms, tick loops |
| game-state-sync | Client-server sync, rollback netcode, delta compression |
| gameplay-analytics | Retention analytics, funnels, D1/D7/D30 |
| matchmaking-system | Matchmaking, lobbies, ELO, skill-based queues |
| postgres-game-schema | Game DB schemas, Drizzle ORM, inventory |
| redis-game-patterns | Caching, leaderboards, pub/sub, rate limiting |
| stripe-game-payments | In-app purchases, subscriptions, webhooks |
| Skill | Description |
|---|---|
| ci-cd-game | CI/CD pipelines, GitHub Actions, deployment |
| claude-code-game-workflow | Entry point for AI agents on game projects |
| cursor-codex-integration | Cursor IDE, .cursorrules, Codex setup |
| monitoring-game-ops | Monitoring, logging, telemetry, alerts |
| Skill | Description |
|---|---|
| character-design-narrative | Characters, NPCs, dialogue, archetypes |
| quest-narrative-coherence | Narrative coherence check, lore validation |
| story-structure-game | Branching narratives, player agency, story arcs |
| worldbuilding | Lore, factions, geography, world bibles |
All skills follow a flat layout:
skills/<skill-name>/
├── README.md # Overview and installation instructions
├── SKILL.md # Main skill file (YAML frontmatter + body)
├── boilerplate/ # Starter code to copy and customize (optional)
├── templates/ # Document and config templates (optional)
├── references/ # Deep-dive reference files (optional)
└── ARCHITECTURE.md # System design decisions (optional)
SKILL.md is always the entry point — read this firstboilerplate/ files are starter code, copy and customizetemplates/ are document/config templates to fill inARCHITECTURE.md explains system design decisions/plugin marketplace add fcsouza/agent-skills
/plugin install game-dev@fcsouza-agent-skills
See plugins/game-dev/README.md for the full skill index, commands, and agents.
# Install a specific skill
npx skills add fcsouza/agent-skills --skill game-design-fundamentals
# Install all game-dev engineering skills at once
npx skills add fcsouza/agent-skills --skill betterauth-integration --skill postgres-game-schema --skill game-backend-architecture
# List all available skills
npx skills add fcsouza/agent-skills --list
# Plugin (full bundle)
cp -r plugins/game-dev/ .claude/plugins/game-dev/
# Individual skill
cp -r skills/<skill-name>/ .claude/skills/<skill-name>/
# For OpenClaw
cp -r skills/<skill-name>/ ~/.openclaw/workspace/skills/<skill-name>/
GPL-3.0
hooks/register.tsx 98 lines1import type { EngineInterface, Register } from 'claude-code';
2
3import { type Check, checksIn, checksOffered, isCodeFile } from './checks';
4
5// Files edited since the checks last all passed, and when each check last passed.
6const edited = new Map<string, number>();
7const passedAt = new Map<Check, number>();
8let offered: Check[] = [];
9let editedAt = 0;
10
11const EDIT_TOOLS = new Set(['Edit', 'Write', 'MultiEdit', 'NotebookEdit']);
12
13// Check names for a narrow band.
14const SHORT: Record<Check, string> = { format: 'fmt', lint: 'lint', typecheck: 'tsc', test: 'test' };
15
16async function loadOffered($: EngineInterface): Promise<void> {
17 const cwd = await $.session.cwd();
18 const file = await $.fs.read(`${cwd}/package.json`).catch(() => null);
19 offered = file === null ? [] : checksOffered(file);
20}
21
22const missing = (): Check[] => offered.filter(check => (passedAt.get(check) ?? 0) < editedAt);
23
24export const register: Register = on => {
25 on('session.start', async ($, e, next) => {
26 const started = await next(e);
27 await loadOffered($);
28 return started;
29 });
30
31 on('tool.call', async ($, e, next) => {
32 const ran = await next(e);
33 if (ran.deny !== undefined || ran.isError === true) {
34 return ran;
35 }
36
37 if (EDIT_TOOLS.has(e.tool)) {
38 const input = e as { file_path?: unknown; notebook_path?: unknown };
39 const path = String(input.file_path ?? input.notebook_path ?? '');
40 if (isCodeFile(path)) {
41 editedAt = await $.clock.now();
42 edited.set(path, editedAt);
43 $.ui.invalidate('ui.render');
44 }
45 return ran;
46 }
47
48 if (e.tool === 'Bash') {
49 const command = String((e as { command?: unknown }).command ?? '');
50 const checks = checksIn(command);
51 if (checks.length > 0) {
52 const at = await $.clock.now();
53 for (const check of checks) passedAt.set(check, at);
54 if (missing().length === 0) edited.clear();
55 $.ui.invalidate('ui.render');
56 }
57 if (/package\.json/.test(command)) await loadOffered($);
58 }
59 return ran;
60 }).catch(($, e, next) => next(e));
61
62 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
63 const below = await next(e);
64 if (e.props.hasSurvey) {
65 return below;
66 }
67 const owed = missing();
68 if (edited.size === 0 || owed.length === 0) {
69 return below;
70 }
71
72 const { Box, Button, Text } = $.ui.resolve(e);
73 const narrow = (e.viewport?.columns ?? Number.POSITIVE_INFINITY) < 80;
74 return (
75 <Box flexDirection="column">
76 <Box gap={1} flexWrap="wrap">
77 <Text color="#f59e0b">●</Text>
78 <Text>{narrow ? `${edited.size} edited` : `${edited.size} file${edited.size === 1 ? '' : 's'} edited`}</Text>
79 {offered.map(check => (
80 <Text color={owed.includes(check) ? '#ef4444' : '#22c55e'}>
81 {owed.includes(check) ? '✗' : '✓'} {narrow ? SHORT[check] : check}
82 </Text>
83 ))}
84 <Button
85 key="dismiss"
86 label="Dismiss"
87 onPress={() => {
88 edited.clear();
89 $.ui.invalidate('ui.render');
90 }}
91 />
92 </Box>
93 {below}
94 </Box>
95 );
96 });
97};
98hooks/checks.ts 40 lines1// Which checks a project has, and which shell commands count as running them.
2
3export type Check = 'format' | 'lint' | 'typecheck' | 'test';
4
5export const CHECKS: readonly Check[] = ['format', 'lint', 'typecheck', 'test'];
6
7const CODE_FILE = /\.(ts|tsx|js|jsx|mjs|cjs|mts|cts|json|jsonc|css|scss|vue|svelte|astro)$/;
8
9export const isCodeFile = (path: string): boolean => CODE_FILE.test(path) && !/(^|\/)(bun\.lock|package-lock\.json)$/.test(path);
10
11const RUNS: Record<Check, RegExp> = {
12 format: /\b(bun run (format|fmt)\b|ultracite (fix|format)\b|biome (format|check)\b.*--write)/,
13 lint: /\b(bun run (lint|lint:\S+|check)\b|ultracite (lint|check)\b|biome (lint|check)\b|eslint\b)/,
14 typecheck: /\b(bun run (typecheck|type-check|tsc|check-types|types)\b|tsc\b|bunx tsc\b|vue-tsc\b)/,
15 test: /\b(bun (run )?test\b|vitest\b|jest\b|playwright test\b)/,
16};
17
18/** The checks a command line runs. */
19export function checksIn(command: string): Check[] {
20 return CHECKS.filter(check => RUNS[check].test(command));
21}
22
23/** The checks a package.json offers through its scripts. */
24export function checksOffered(packageJson: string): Check[] {
25 let scripts: Record<string, unknown> = {};
26 try {
27 scripts = (JSON.parse(packageJson) as { scripts?: Record<string, unknown> }).scripts ?? {};
28 } catch {
29 return [];
30 }
31 const names = Object.keys(scripts);
32 const has = (pattern: RegExp) => names.some(name => pattern.test(name));
33 return CHECKS.filter(check => {
34 if (check === 'format') return has(/^(format|fmt)$/);
35 if (check === 'lint') return has(/^lint(:|$)|^check$/);
36 if (check === 'typecheck') return has(/^(typecheck|type-check|tsc|check-types|types)$/);
37 return has(/^test(:|$)/);
38 });
39}
40