Skill Builder
Overview
This skill teaches you how to create new skills properly. Skills are reusable instruction sets that extend your capabilities with specialized knowledge, workflows, and best practices.
Core principle: Write skills that future instances of Codex can discover and apply without human intervention.
When to Use This Skill
Use this skill when:
- •User asks to "create a skill" or "make a skill"
- •You discover a technique that should be reusable
- •User wants to document a workflow or pattern
- •You're asked to "write this down for next time"
- •A process keeps recurring and should be standardized
What Makes a Good Skill
Good skills are:
- •✅ Reusable across multiple projects
- •✅ Clear and actionable (step-by-step)
- •✅ Discoverable (rich metadata)
- •✅ Self-contained (all info needed to use it)
Don't create skills for:
- •❌ One-off solutions
- •❌ Project-specific code (that goes in project docs)
- •❌ Things already well-documented elsewhere
- •❌ Personal preferences without broad applicability
SKILL.md Structure
Every skill must have this structure:
--- name: "Human-Readable Skill Name" description: "One-line summary of what this does" tags: ["keyword1", "keyword2", "keyword3"] intent: "Detailed triggers, symptoms, and situations when this applies. Include error messages, user phrases, and specific scenarios." version: "1.0.0" languages: all | ["python", "javascript"] | specific language --- # Skill Name ## Overview 2-3 sentence explanation of what this skill does and the core principle. ## When to Use Bullet list of: - Specific triggers (error messages, situations) - Symptoms that indicate you need this - Types of tasks where this applies - When NOT to use this ## Core Pattern (if showing before/after) Brief example showing the wrong way and the right way. ## Quick Reference Table or bullet list of common operations/commands for quick scanning. ## Implementation Step-by-step instructions: 1. First step 2. Second step 3. Third step Include code examples inline when relevant. ## Common Mistakes What goes wrong + how to fix it: - ❌ Don't do this - ✅ Do this instead ## Examples Real-world concrete examples of using this skill.
The Critical YAML Frontmatter
The YAML section at the top is critical for discovery. Codex finds skills by matching patterns in these fields.
Required Fields (Codex will fail to load skills missing these)
name: - Human-readable title (REQUIRED)
- •Use active voice: "Creating Skills" not "Skill Creation"
- •Descriptive: "Time Awareness" not just "Time"
- •Use quotes for strings with special characters
description: - One-line summary (REQUIRED by Codex)
- •What does it do in plain language?
- •This shows in skill listings
- •Codex will skip loading skills without this field
tags: - Discovery keywords (recommended)
- •Array of keywords for matching user queries
- •Include synonyms and related terms
- •Example:
["git", "worktree", "branch", "parallel"]
intent: - Discovery metadata (MOST IMPORTANT for matching)
- •Be extremely specific
- •Include error messages, symptoms, trigger words
- •This is how Codex knows to load your skill
- •More detail = better discovery
version: - Semantic version (start with 1.0.0)
languages: - Which languages/contexts apply
- •
allfor universal skills - •
["python", "javascript"]for language-specific - •
["typescript"]for single language
Example of Good vs Bad intent
❌ Bad - Too vague:
intent: "For git workflows"
✅ Good - Specific triggers:
intent: "When working on multiple features simultaneously, when you need to preserve work-in-progress, when switching contexts frequently, when you see 'detached HEAD' state, or when user mentions 'git worktrees'"
Step-by-Step Skill Creation Process
Step 1: Identify the Pattern
Ask yourself:
- •What technique/pattern did we just use?
- •Would this be useful again in a different context?
- •Can it be generalized?
- •Is it already well-documented elsewhere?
Step 2: Choose a Name
Use this format:
- •Action-based: "debugging-with-logs", "creating-tests"
- •Pattern-based: "condition-based-waiting"
- •Clear and searchable: "git-worktree-workflow"
Avoid:
- •Generic names: "helper", "utils"
- •Abbreviations: "db-mgmt"
- •Unclear references: "the-pattern"
Step 3: Write Discovery Metadata
This is THE MOST IMPORTANT part. Write intent with:
Include specific triggers:
- •Error messages: "ENOENT", "Cannot find module"
- •Symptoms: "flaky tests", "race conditions"
- •Keywords: "async", "parallel", "concurrent"
- •User phrases: "how do I...", "keep getting..."
Include context:
- •When in the workflow: "before writing code", "when debugging"
- •Project types: "React projects", "CLI tools"
- •Situations: "when tests are slow", "when merging is difficult"
Step 4: Write Clear Instructions
Use imperative mood:
- •✅ "Run this command"
- •❌ "You should run this command"
Number steps:
- •First do this
- •Then do this
- •Finally do this
Show code examples inline:
# Good examples are commented and complete git worktree add ../feature-branch feature-branch
Explain WHY, not just WHAT:
## Why condition-based waiting works Polling with conditions is more reliable than fixed timeouts because...
Step 5: Add Examples
Include 2-3 real-world examples:
- •Simple case
- •Edge case
- •Common variation
Make them concrete - actual code, actual commands, actual scenarios.
Step 6: Document Common Mistakes
Every skill should have this section:
## Common Mistakes ❌ **Mistake:** Description of what goes wrong ✅ **Fix:** How to do it correctly ❌ **Mistake:** Another common error ✅ **Fix:** The right approach
Step 7: Create the File
# Create skill directory (DOTCODEX_DIR defaults to ../dotcodex)
default_dotcodex="${DOTCODEX_DIR:-$(cd .. && pwd)/dotcodex}"
skills_dir="${default_dotcodex}/skills"
mkdir -p "${skills_dir}/skill-name"
# Create SKILL.md file
cat > "${skills_dir}/skill-name/SKILL.md" <<'EOF'
[paste your skill content here]
EOF
# Verify it appears
codex-skills list
# Test loading it
codex-skills use skill-name
Skill Templates by Type
Technique Skill (How-to)
For teaching a specific technique or method.
Focus on:
- •Clear step-by-step process
- •Code examples
- •Before/after comparisons
Example: time-awareness, systematic-debugging
Pattern Skill (Conceptual)
For teaching a way of thinking or mental model.
Focus on:
- •The principle/concept
- •When to apply it
- •Recognition patterns
Example: defensive-programming, separation-of-concerns
Workflow Skill (Process)
For multi-step processes or workflows.
Focus on:
- •Ordered steps
- •Decision points
- •Checkpoints
Example: git-worktree-workflow, code-review-process
Reference Skill (Documentation)
For API docs, command references, syntax guides.
Focus on:
- •Quick reference tables
- •Command syntax
- •Common operations
Example: docker-commands, regex-patterns
Testing Your Skill
After creating a skill, test it:
1. Discovery Test
# Does it show up? codex-skills list | grep -i "your-skill-name"
2. Loading Test
# Does it load properly? codex-skills use your-skill-name
3. Format Test
- • YAML frontmatter has
---delimiters - • All required fields present
- • No tabs in YAML (use spaces)
- • Headers use
##format - • Code blocks use triple backticks
4. Practical Test
- •Start a new Codex session
- •Create a situation where the skill should apply
- •Does Codex discover and use the skill?
- •Do the instructions work as expected?
Common Mistakes When Creating Skills
❌ Vague intent
intent: "For testing"
✅ Better:
intent: "When writing unit tests, when tests are flaky, when you see 'test timeout' errors, when mocking external dependencies"
❌ No concrete examples
Use the command with appropriate flags.
✅ Better:
## Example ```bash git worktree add ../feature-branch feature-branch cd ../feature-branch # Now you can work here independently
### ❌ Missing the "why" ```markdown Run this command.
✅ Better:
Run this command to avoid race conditions. Fixed timeouts fail when systems are slow; condition-based waiting adapts.
❌ Narrative instead of instructions
Last week we had a bug where...
✅ Better:
## Common Mistakes When files are locked, you'll see EBUSY errors. Use graceful-fs to retry automatically.
Skill Creation Checklist
When creating a new skill, verify:
Discovery:
- •
descriptionfield is present (REQUIRED by Codex) - •
intentincludes specific trigger words - •
intentincludes error messages if applicable - •
intentincludes symptoms/situations - •
tagsinclude relevant keywords - • Name is descriptive and searchable
Content:
- • Overview explains core principle
- • When to Use section is comprehensive
- • Instructions are step-by-step and imperative
- • Code examples are complete and commented
- • Common mistakes section included
- • Real-world examples provided
Format:
- • YAML frontmatter properly formatted
- • All required fields present
- • Sections use ## headers
- • Code uses triple backtick blocks
- • No tabs in YAML (spaces only)
Testing:
- • Appears in
codex-skills list - • Loads with
codex-skills use skill-name - • Actually helps with the intended task
- • Can be found when needed
Integration with Workflow
After creating a skill:
- •Announce it: Tell the user "I've created a new skill: [name]"
- •Explain when to use it: Summarize the triggers
- •Offer to test: "Would you like me to test loading this skill?"
- •Document it: Keep a project log of custom skills if relevant
Example: Creating a Skill (Full Walkthrough)
User asks: "Can you write down how to handle environment variables properly so we don't forget next time?"
You respond:
"I'll create a skill for environment variable handling. Let me structure this properly..."
default_dotcodex="${DOTCODEX_DIR:-$(cd .. && pwd)/dotcodex}"
skills_dir="${default_dotcodex}/skills"
mkdir -p "${skills_dir}/env-var-handling"
You create:
--- name: "Environment Variable Handling" description: "Best practices for managing environment variables securely in applications" tags: ["env", "environment", "secrets", "config", "dotenv", ".env", "configuration"] intent: "When setting up new projects, when you see hardcoded secrets, when configuring deployments, when user mentions 'env vars' or '.env files', when debugging configuration issues" version: "1.0.0" languages: all --- # Environment Variable Handling ## Overview Proper environment variable management keeps secrets out of code, enables configuration across environments, and prevents security vulnerabilities. ## When to Use - Starting a new project that needs configuration - See hardcoded API keys or secrets in code - Deploying to different environments (dev/staging/prod) - User mentions environment variables or configuration - Debugging "works on my machine" issues ## Core Pattern ❌ **Wrong:** ```python API_KEY = "sk-abc123..." # Hardcoded secret DATABASE_URL = "postgres://localhost"
✅ Right:
import os
API_KEY = os.environ.get('API_KEY')
DATABASE_URL = os.environ.get('DATABASE_URL')
Implementation
- •Create .env file for local development:
cat > .env << 'EOF' API_KEY=your-key-here DATABASE_URL=postgres://localhost:5432/mydb NODE_ENV=development EOF
- •Add .env to .gitignore:
echo ".env" >> .gitignore
- •Create .env.example template:
cat > .env.example << 'EOF' API_KEY=your-api-key-here DATABASE_URL=your-database-url NODE_ENV=development EOF
- •Load in application:
# Python from dotenv import load_dotenv load_dotenv()
// Node.js
require('dotenv').config()
- •Access variables:
import os
api_key = os.environ.get('API_KEY')
if not api_key:
raise ValueError("API_KEY not set")
Common Mistakes
❌ Committing .env to git
- •Add .env to .gitignore FIRST
- •Check with:
git statusbefore committing
❌ No validation
# Bad - fails silently
api_key = os.environ.get('API_KEY')
✅ Validate required vars:
# Good - fails fast with clear error
api_key = os.environ.get('API_KEY')
if not api_key:
raise ValueError("API_KEY environment variable required")
❌ Inconsistent naming
- •Use UPPER_SNAKE_CASE consistently
- •Not
apiKeyorapi-key
Examples
Example 1: Python Flask app
from flask import Flask
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
app.config['DATABASE_URI'] = os.environ.get('DATABASE_URL')
if not app.config['SECRET_KEY']:
raise ValueError("SECRET_KEY must be set")
Example 2: Node.js Express app
require('dotenv').config()
const app = express()
const PORT = process.env.PORT || 3000
const DB_URL = process.env.DATABASE_URL
if (!DB_URL) {
throw new Error('DATABASE_URL must be set')
}
Production Deployment
For production:
- •Set env vars in hosting platform (Heroku, AWS, etc.)
- •Never commit production secrets
- •Use secret management tools for sensitive data
- •Rotate secrets regularly
Remember: If it's a secret or configuration, it belongs in an environment variable, not in code.
**You save it:**
```bash
# Save the skill
cat > "${skills_dir}/env-var-handling/SKILL.md" <<'EOF'
[content above]
EOF
You verify:
codex-skills list # Should show: Environment Variable Handling
You announce:
"I've created the 'env-var-handling' skill. It will activate whenever you mention environment variables, configuration, or when I see hardcoded secrets. You can load it anytime with codex-skills use env-var-handling."
Advanced: Skill Families
Related skills can reference each other:
## Related Skills See also: - `codex-skills use security-best-practices` for broader security patterns - `codex-skills use docker-config` for containerized deployments
This creates a knowledge graph of interconnected skills.
Meta-Skill: Using This Skill
When user asks you to create a skill:
- •Announce: "I'll create a new skill for [topic]"
- •Ask clarifying questions if needed:
- •What should trigger this skill?
- •What are common error messages?
- •What mistakes should we warn about?
- •Follow this skill's structure
- •Create the file in
${DOTCODEX_DIR:-../dotcodex}/skills/(symlinked to~/.codex/skills/) - •Verify with
codex-skills list - •Announce completion and when it will activate
Remember: You're creating instructions for your future self. Be clear, be specific, be helpful.
This skill is itself an example of a well-structured skill. Use it as a template!