Writing Golem-Powers Skills
Meta-skill for creating executable skills. Skills are tools that Claude can invoke and automatically execute.
Skill Structure
Every golem-powers skill MUST have this structure:
skills/golem-powers/<skill-name>/
├── SKILL.md # REQUIRED: Frontmatter + documentation
├── CLAUDE.md # OPTIONAL: Environment requirements, complex setup
├── scripts/ # REQUIRED: Executable files
│ ├── default.sh # Pattern A: Bash script
│ └── run.sh # Pattern B: Wrapper for TypeScript
├── src/ # OPTIONAL: TypeScript source (Pattern B)
│ └── index.ts
├── package.json # OPTIONAL: Required if using TypeScript
├── bun.lock # OPTIONAL: Required if using TypeScript
└── workflows/ # OPTIONAL: Multi-step procedures
├── create.md
└── verify.md
SKILL.md Frontmatter (REQUIRED)
--- name: <skill-name> description: <when to use this skill - shown in skill discovery> execute: scripts/default.sh # Path to script Claude runs on invocation ---
The execute: field is what makes a skill executable. When Claude loads a skill with execute: frontmatter, it MUST run that script IMMEDIATELY via Bash before any other action.
Dual Execution Patterns
Pattern A: Bash Script
Best for: Simple CLI wrappers, no dependencies, quick operations.
Frontmatter:
execute: scripts/review.sh
Structure:
skill-name/
├── SKILL.md
└── scripts/
└── review.sh # chmod +x
Script conventions:
- •Scripts output Markdown for Claude to parse
- •Use
set -euo pipefailfor safety - •Exit 0 on success, non-zero on failure
- •Print errors to stderr, results to stdout
- •MUST use BASH_SOURCE for path detection (see Path Standard below)
Example script:
#!/usr/bin/env bash
set -euo pipefail
# REQUIRED: Self-detect script location (works from any cwd)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
echo "## Review Results"
echo ""
some-cli-tool review --format markdown
Pattern B: TypeScript/Bun
Best for: Complex logic, API calls, type safety, structured data processing.
Frontmatter:
execute: scripts/run.sh --action=default
Structure:
skill-name/ ├── SKILL.md ├── scripts/ │ └── run.sh # Wrapper that calls bun ├── src/ │ └── index.ts # Main TypeScript file ├── package.json └── bun.lock
The wrapper script (scripts/run.sh):
#!/usr/bin/env bash
set -euo pipefail
# REQUIRED: Self-detect script location (works from any cwd)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
cd "$SKILL_DIR"
bun run src/index.ts "$@"
TypeScript requirements:
- •Use Bun runtime (fast, TypeScript-native)
- •Accept CLI arguments via
process.argv - •Output Markdown or JSON to stdout
- •Handle errors gracefully with exit codes
CLI Pattern (for TypeScript skills)
Use flags to support multiple operations in one skill:
--action Flag
execute: scripts/run.sh --action=default
Available actions defined in your TypeScript:
const action = process.argv.find(a => a.startsWith('--action='))?.split('=')[1] || 'default';
switch (action) {
case 'default':
// Main skill behavior
break;
case 'verify':
// Verification mode
break;
case 'list':
// List mode
break;
}
--env Flag
For environment selection:
scripts/run.sh --action=deploy --env=prod
const env = process.argv.find(a => a.startsWith('--env='))?.split('=')[1] || 'dev';
Execution Rule
CRITICAL: When loading a golem-powers skill with execute: frontmatter, Claude MUST run that script IMMEDIATELY via Bash before any other action.
This means:
- •Claude loads the skill SKILL.md
- •Claude sees
execute: scripts/foo.sh - •Claude IMMEDIATELY runs
bash ~/.claude/commands/golem-powers/<skill>/scripts/foo.sh - •Claude reads the output
- •Only THEN does Claude proceed with other actions
This ensures skills are executable tools, not just documentation.
Quick Actions
| What you want | Workflow |
|---|---|
| Create a new skill | workflows/create.md |
| Audit skill structure | workflows/audit.md |
Template Generator
Use the included script to scaffold new skills:
bash ~/.claude/commands/golem-powers/writing-skills/scripts/create-skill.sh \ --name=my-skill \ --type=bash
Options:
- •
--name=<skill-name>(required): Name for the new skill - •
--type=bash|typescript(required): Execution pattern - •
--output=<path>(optional): Output directory (default: ./skills/golem-powers/)
This creates:
- •Pattern A (bash):
SKILL.md,scripts/default.sh - •Pattern B (typescript):
SKILL.md,scripts/run.sh,src/index.ts,package.json
Examples
See working examples in this repo:
- •
skills/golem-powers/example-bash/- Simple bash skill - •
skills/golem-powers/example-typescript/- TypeScript/Bun skill
Safety Rules
- •Always chmod +x - All scripts must be executable
- •Test before commit - Run
shellcheckon all .sh files - •Output Markdown - Scripts should return Markdown Claude can parse
- •Exit codes matter - 0 = success, non-zero = failure
- •Use BASH_SOURCE pattern - All scripts MUST self-detect their location
Path Standard (CRITICAL)
All skill scripts MUST use this pattern for portability:
#!/usr/bin/env bash
set -euo pipefail
# REQUIRED: Self-detect script location (works from any cwd)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
# Now use absolute paths relative to skill
source "$SKILL_DIR/config.sh" # If needed
For project detection (when script needs prd-json/, package.json, etc.):
# Walk up from cwd to find project root
find_project_root() {
local dir="$PWD"
while [[ ! -d "$dir/prd-json" && "$dir" != "/" ]]; do
dir="$(dirname "$dir")"
done
if [[ -d "$dir/prd-json" ]]; then
echo "$dir"
else
echo ""
fi
}
PROJECT_ROOT="$(find_project_root)"
if [[ -z "$PROJECT_ROOT" ]]; then
echo "Error: Cannot find prd-json/ directory" >&2
exit 1
fi
Why this matters:
- •Skills are symlinked in
~/.claude/commands/but users run Claude from project directories - •Relative paths like
./scripts/foo.shfail when cwd != skill directory - •BASH_SOURCE provides reliable self-location regardless of invocation context
See contexts/skill-authoring.md for full details.