SLOPSHOPPER

pino-guard

Blocks edits that add a pino transport (pino.transport() or a transport target) without a development-only guard: under bun build its worker thread cannot load…

guard
★ 21v0.1.0GPL-3.0updated 2026-10-19fcsouza/agent-skills/mods/pino-guard
A shopper browsing a rack in a slop shop
README

Agent Skills

Production-grade skills for AI coding agents (OpenClaw, Claude Code, and others).

Built by Fabricio Cavalcante — Software Engineer & AI Specialist.

Available Plugins

Plugins are complete workflow bundles — skills + agents + hooks working together as an integrated system. Install a plugin to get the full experience.

PluginDescriptionPlatform
game-dev26 skills, 7 commands, 3 agents, 5 hooks — complete game development workflow with engineering, design, narrative, and infrastructureGame Dev

Claude Code Mods

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.

ModDescription
commit-guardBlocks commits with machine paths or .env files, git add -A, and pushes to main
prod-guardHolds Dokploy MCP writes until you press Proceed
bun-onlyRewrites npm, npx, yarn and pnpm to bun
done-gateShows edited files and the checks still owed
worktreesShows git worktrees, their changes, and the count
usage-ringsContext and plan usage, coloured by level
pr-statusThe current branch's PR: CI checks and review
sql-guardHolds writes to non-local databases until you press Proceed
pino-guardBlocks pino transports that break bundled logging

Available Skills

Skills are individual, cherry-pickable modules. Install only what you need.

Core

SkillDescriptionPlatform
claude-agent-sdkBuild production AI agents with the Claude Agent SDK — query(), hooks, subagents, custom tools, MCP servers, sessions, permissions, hostingClaude Code / API
database-performance-tuningDiagnose 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 scriptPostgreSQL / MySQL
foundry-vtt-module-devBuild, 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 filesFoundry VTT
foundry-vtt-system-devBuild 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, enrichersFoundry VTT
openclaw-genieComprehensive OpenClaw gateway skill — installation, configuration, 38+ channels, memory, tools, hooks, deployment, multi-agentOpenClaw
nuvemshop-sdkPrepare, audit, implement, homologate, and publish Nuvemshop/Tiendanube apps — OAuth, API, NubeSDK, Nexo, Nimbus, webhooks, and App Store approvalNuvemshop
react-animationsReact animation patterns and utilitiesReact

Game Dev — Design

SkillDescription
game-design-fundamentalsCore loops, MDA framework, progression curves
game-economy-designVirtual economies, currencies, loot tables
level-designLevels, environments, difficulty curves
procedural-genDungeon gen, noise terrain, wave function collapse
quest-mission-designQuests, objectives, quest trees
skill-progression-treesSkill trees, talent trees, unlock graphs
ui-ux-gameHUD, menus, onboarding, accessibility

Game Dev — Engineering

SkillDescription
betterauth-integrationAuth, OAuth, JWT, RBAC
bullmq-game-queuesJob queues, async events, scheduled tasks
elevenlabs-sound-musicSFX generation, adaptive music, voice acting
game-backend-architectureGame servers, WebSocket, rooms, tick loops
game-state-syncClient-server sync, rollback netcode, delta compression
gameplay-analyticsRetention analytics, funnels, D1/D7/D30
matchmaking-systemMatchmaking, lobbies, ELO, skill-based queues
postgres-game-schemaGame DB schemas, Drizzle ORM, inventory
redis-game-patternsCaching, leaderboards, pub/sub, rate limiting
stripe-game-paymentsIn-app purchases, subscriptions, webhooks

Game Dev — Infrastructure

SkillDescription
ci-cd-gameCI/CD pipelines, GitHub Actions, deployment
claude-code-game-workflowEntry point for AI agents on game projects
cursor-codex-integrationCursor IDE, .cursorrules, Codex setup
monitoring-game-opsMonitoring, logging, telemetry, alerts

Game Dev — Narrative

SkillDescription
character-design-narrativeCharacters, NPCs, dialogue, archetypes
quest-narrative-coherenceNarrative coherence check, lore validation
story-structure-gameBranching narratives, player agency, story arcs
worldbuildingLore, factions, geography, world bibles

Structure

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 first
  • boilerplate/ files are starter code, copy and customize
  • templates/ are document/config templates to fill in
  • ARCHITECTURE.md explains system design decisions

Installation

game-dev plugin (Claude Code)

/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.

Individual skills (cherry-pick)

# 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

Manual

# 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>/

License

GPL-3.0

Source 2 files
hooks/register.ts 24 lines
1import type { Register } from 'claude-code';
2
3import { addedText, addsUnguardedTransport, hasDevGuard } from './rules';
4
5const SOURCE = /\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$/;
6
7export const register: Register = on => {
8  on('tool.call', { tool: /^(Edit|Write|MultiEdit)$/ }, async ($, e, next) => {
9    const input = e as { file_path?: unknown; content?: unknown; new_string?: unknown; edits?: unknown };
10    const path = String(input.file_path ?? '');
11    if (!SOURCE.test(path) || !addsUnguardedTransport(addedText(input))) {
12      return next(e);
13    }
14    // An Edit lands inside existing code: a guard already in the file counts. A Write replaces the file, so only its own text does.
15    if (e.tool !== 'Write') {
16      const current = await $.fs.read(path).catch(() => '');
17      if (hasDevGuard(current)) return next(e);
18    }
19    return {
20      deny: `${$.plugin.name}: this adds a pino transport to ${path}. Under \`bun build\` its worker thread cannot load inlined modules and every log stream, stdout included, dies with no error. Use \`pino.multistream()\` with direct streams (for example @logtail/node) in production. A transport is fine only on the unbundled development path, behind \`isDevelopment()\`.`,
21    };
22  }).catch(($, e, next) => next(e));
23};
24
hooks/rules.ts 30 lines
1// What a pino transport looks like in source, and what counts as keeping it to development.
2
3// pino.transport({...}) or a transport option with a worker target: pino({ transport: { target: ... } }).
4const TRANSPORT = /pino\s*\.\s*transport\s*\(|transport\s*:\s*\{[^}]*\btargets?\s*:/s;
5
6// The guard the rule allows: a transport only on the unbundled development path.
7const DEV_GUARD = /isDevelopment\s*\(|NODE_ENV\s*[!=]==?\s*['"](development|production)['"]|import\.meta\.env\.DEV|Bun\.env\.NODE_ENV/;
8
9/** The text an edit puts into a file. */
10export function addedText(input: { content?: unknown; new_string?: unknown; edits?: unknown }): string {
11  if (typeof input.content === 'string') return input.content;
12  if (typeof input.new_string === 'string') return input.new_string;
13  if (Array.isArray(input.edits)) {
14    return input.edits
15      .map(edit =>
16        edit !== null && typeof edit === 'object' && typeof (edit as { new_string?: unknown }).new_string === 'string'
17          ? (edit as { new_string: string }).new_string
18          : '',
19      )
20      .join('\n');
21  }
22  return '';
23}
24
25/** True when the added text brings in a pino transport with no development-only guard beside it. */
26export const addsUnguardedTransport = (text: string): boolean => TRANSPORT.test(text) && !DEV_GUARD.test(text);
27
28/** True when a file already keeps something behind a development check. */
29export const hasDevGuard = (text: string): boolean => DEV_GUARD.test(text);
30