skills/skill-scaffolder/SKILL.md
Meta-skill for creating new agent skills that involve multi-step automation, browser navigation, state tracking, evidence capture, and both local (VS Code Insiders) and VPS (Playwright) execution. Use when the user wants to 'create a skill', 'build a new skill', 'scaffold a skill', 'make a skill for X', or describes a multi-step agentic workflow they want to automate.
npx skillsauth add arndvs/ctrlshft skill-scaffolderInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Output "Read Skill Scaffolder skill." to chat to acknowledge you read this file.
Creates production-ready agent skills that follow the proven agentic pipeline architecture: Python scripts provide the scaffolding (state management, config, error handling), while the VS Code Copilot agent provides the runtime muscle (browser interactions, code analysis, decision-making).
Before generating any files, ask the user these questions to determine which patterns the skill needs. Ask questions one at a time:
repo-portfolio, competitor-scraper)If skill type = knowledge/workflow, skip to the Lightweight Skill Path section below.
If skill type = automation pipeline, continue:
Skip questions where the answer is obvious from context. For example, if the user says "scrape these 50 URLs and screenshot each", you know: work unit = URL, browser = yes, evidence = yes.
For knowledge/workflow skills that don't need scripts, state stores, or orchestrators. Use this path when:
Structure:
{skill-name}/
├── SKILL.md # Main instructions (required, ≤100 lines)
├── references/ # Supplemental docs (if SKILL.md would exceed 100 lines)
│ ├── overview.md # Detailed reference docs
│ └── examples.md # Usage examples (if patterns are complex)
└── scripts/ # Only if deterministic operations exist
└── helper.js
When to add scripts (even in lightweight skills):
Scripts save tokens and improve reliability vs. regenerated code.
When to split into separate files:
After generating a lightweight skill, proceed to the Quality Checklist section.
Based on the interview answers, select which modules to include:
| Question | If YES, include | If NO, skip |
| ------------------------ | --------------------------------------- | ---------------------------------- |
| Browser needed? | browser_adapter.py + screenshot tools | Omit browser modules |
| State tracking = Sheets? | sheets_client.py + setup_sheet.py | Use state_store.py (JSON/SQLite) |
| Authentication? | credential_vault.py | Omit vault |
| Evidence capture? | screenshot_manager.py | Omit screenshots |
| Dual-mode execution? | browser_adapter.py with both adapters | Single adapter only |
| Email verification? | email_handler.py | Omit email |
Always include (every skill gets these):
SKILL.mdconfig.example.json + config.jsonscripts/__init__.pyscripts/shared_utils.pyscripts/session_logger.pyscripts/preflight.pyscripts/run_{name}.py (main orchestrator)Every generated skill follows this layout:
{skill-name}/
├── SKILL.md ← agent instructions (most important file)
├── config.json ← user's actual config (gitignored if has secrets)
├── config.example.json ← committed template with placeholders
├── references/
│ ├── setup.md ← environment setup guide
│ └── {domain-specific}.md ← domain knowledge docs
└── scripts/
├── __init__.py ← makes scripts/ a package
├── shared_utils.py ← env loading, config, paths, circuit breaker
├── session_logger.py ← JSONL audit trail
├── preflight.py ← Phase 0 validation
├── run_{name}.py ← main orchestrator
└── {domain-specific modules} ← varies per skill
Generate files in this exact order. Each file must be complete, production-ready, with no TODOs or placeholders in code (config templates may have YOUR_*_HERE placeholders).
Code generation rules (apply to ALL generated Python files):
# comment lines — do not comment generated code (by convention)pass statements — every method must have a real implementationCUSTOMIZE: markers, replace them with actual codeself.state must be initialized to a real state store instance (not None/commented-out)self.browser may be None in VS Code mode — the agent provides browser interaction via MCP toolsconfig.example.jsonTemplate config with all required keys. Sensitive values use YOUR_*_HERE placeholders.
{
"skill_specific_section": {
"key": "YOUR_VALUE_HERE"
},
"state_store": {
"type": "sheets|json|sqlite",
"spreadsheet_id": "YOUR_SPREADSHEET_ID_HERE",
"tab_name": "Main",
"summary_tab": "Summary"
},
"output": {
"evidence_path": "./evidence/",
"report_path": "./output/"
},
"session": {
"max_items_per_session": 50,
"item_cooldown_seconds": 5,
"circuit_breaker_threshold": 5
}
}
scripts/__init__.py"""Run entry points from the project root:
python -m scripts.run_{name} --config config.json
python -m scripts.preflight --config config.json
"""
scripts/shared_utils.pyGenerate using Patterns 1, 2, and 3 from references/pattern-catalog.md. Customize:
_ENV_FILES paths (keep ~/dotfiles/secrets/.env.agent as primary, .env.secrets for credentials){SKILL_PREFIX}_* naming)REQUIRED_CONFIG dict for validate_config()NOTE_MAX_LEN constantMust include these functions:
load_env() / ensure_env() — idempotent env loading from ~/dotfiles/secrets/.env.agent and .env.secretsresolve_path(p) — expand ~ and resolve to absolutediscover_credentials(config) — GCP service account auto-discovery (only if using Sheets)load_config(config_path) — JSON load + env var overlayvalidate_config(config) — required key validationdue_date(days) — date offset helperMust include these classes:
CircuitBreaker(threshold) — consecutive failure trackingscripts/session_logger.pyGenerate using Pattern 11 from references/pattern-catalog.md. The only customization: rename the work_unit parameter in log_event() and log_error() if a more specific name fits the skill's domain.
scripts/screenshot_manager.py (if evidence capture needed)Generate using Pattern 12 from references/pattern-catalog.md. Customize only:
STEP_ORDER list — replace with the workflow steps for this skill's domainunit_dir() method name — rename if a more specific name fits (e.g., repo_dir())The class structure (timestamped filenames, step ordering, capture() that never throws) stays identical.
scripts/sheets_client.py + scripts/setup_sheet.py (if Google Sheets state store)Generate the SheetsClient using Pattern 4 from references/pattern-catalog.md. Customize:
COL dict — column index mapping for the new skill's schemaHEADERS list — column header namesSTATUS_CODES set — valid statuses for this skillSKIP_ON_STARTUP set — statuses that mean "done"get_pending_items() — filter + sort logic for work queueAlso generate scripts/setup_sheet.py — a one-time script that calls SheetsClient.setup_headers() and write_summary() to initialize the spreadsheet. Follow the citation-builder-skill's scripts/setup_sheet.py pattern: load config, create client, write headers, print spreadsheet URL.
scripts/state_store.py (if JSON/SQLite state store — alternative to Sheets)Generate using Pattern 5 from references/pattern-catalog.md. The JsonStateStore class is a drop-in replacement for SheetsClient — same interface (get_all_items, get_pending_items, update_item, set_status, add_item, write_summary) but backed by an atomic-write JSON file instead of Google Sheets API.
scripts/browser_adapter.py (if browser needed)Generate using Pattern 8 from references/pattern-catalog.md. Includes the BrowserAdapter ABC and PlaywrightAdapter concrete class.
Important: In VS Code mode, the agent does NOT instantiate a Python adapter. Instead, the agent directly uses VS Code browser tools (open_browser_page, click_element, type_in_page, screenshot_page, read_page) following the phase method docstrings. The PlaywrightAdapter is only used for VPS headless execution.
scripts/credential_vault.py (if authentication needed)Generate using Pattern 7 from references/pattern-catalog.md. Full AES-256 Fernet encrypted vault. Only include if the skill creates accounts on external services.
scripts/preflight.pyGenerate using Pattern 6 from references/pattern-catalog.md. Each check prints ✓/✗, collects all errors, fails at end with summary.
Standard checks for every skill:
Conditional checks:
scripts/run_{name}.py — Main OrchestratorThis is the most important generated file. The orchestrator follows the Pattern 9 (Error Boundary Structure) from references/pattern-catalog.md.
Mandatory structure:
__init__ must assign self.state to the actual state store instance (SheetsClient or JsonStateStore) — never leave it as None or commented out__init__ must create self.logger, self.breaker, and set session limits from configrun() calls preflight, iterates pending items, enforces session limit and circuit breaker_run_item() has three try/except zones: pre-execution → point-of-no-return → post-execution_phase_N_name() method has a docstring starting with Agent: that tells the agent what to do{"skip": False, ...} with agent-discovered valuesGeneration rules:
{Name} with PascalCase skill name (e.g., PortfolioRunner){name} with snake_case skill name (e.g., portfolio)from scripts.sheets_client import SheetsClient or from scripts.state_store import JsonStateStoreargparse with --config, --item, --dry-run flagsself.browser = None and runtime check in run()SKILL.mdThe most critical file. This is what the agent reads to understand how to operate the skill. Follow this structure:
Description formatting rules (the description is the ONLY thing the agent sees when choosing skills):
---
name: { skill-name }
description: >
{Single sentence: what it does and when to invoke it.
Max 1024 chars. Third person. Specific enough to distinguish from similar skills.}
---
# {Skill Title}
{One-sentence summary of what this skill does.}
---
## First-Time Setup
{Step-by-step setup instructions. Include:
- Venv activation
- Dependency installation
- Config file creation
- Service account / API key setup
- State store initialization
- Pre-flight check}
---
## File Structure
{Complete directory listing with one-line descriptions}
---
## Config Template
{Full config.json example with all keys}
---
## Phase Overview
{Table: Phase | What it does}
---
## Running
{CLI commands for: full run, single item, dry run, preflight only}
---
## State Store Schema
{Table: columns/fields, types, descriptions}
## Status Codes
{List of all valid statuses with descriptions}
---
## Error Recovery & Circuit Breaker
{Table: error type → recovery action}
---
## Rate Limiting
{Delays, cooldowns, session limits}
SKILL.md line budget: If the generated SKILL.md exceeds 100 lines, move advanced sections (Error Recovery, Rate Limiting, State Store Schema) into references/ and link to them from SKILL.md.
references/setup.mdEnvironment setup guide covering:
references/troubleshooting.mdCommon errors and fixes, organized by category. Follow the citation-builder-skill's references/troubleshooting.md structure:
When writing phase methods for the orchestrator, follow these rules:
Docstring is the agent interface. The docstring tells the agent what to do. Start agent instructions with Agent: prefix.
Return a dict with skip: bool. Every phase can signal the orchestrator to skip remaining phases for this work unit.
Initialize result with None/defaults. The agent fills in discovered values.
Update state store after processing. Never leave state un-persisted between phases.
Pre-execution phases wrap in try/except → mark failed. Post-execution phases → append notes only, never revert status.
Phase boundaries are the resume points. If the skill crashes, it picks up at the last un-completed phase.
| Item | Convention | Example |
| -------------------- | --------------------------- | ------------------------------- |
| Skill directory | kebab-case | repo-portfolio |
| Python modules | snake_case.py | feature_discovery.py |
| Orchestrator class | PascalCase + Runner | PortfolioRunner |
| Config env prefix | UPPER_SNAKE | PORTFOLIO_ |
| State store columns | snake_case | feature_name |
| Status codes | snake_case | in_progress |
| Evidence directories | sanitized_domain | github_com_user_repo |
| Session logs | session_{timestamp}.jsonl | session_20260402_143022.jsonl |
When a skill uses browser automation in VS Code mode, the agent uses these deferred tools (load via tool_search before first use):
| Tool | Purpose |
| ------------------- | ------------------------------ |
| open_browser_page | Navigate to a URL |
| read_page | Get page DOM/text content |
| click_element | Click by selector or text |
| type_in_page | Fill form fields |
| screenshot_page | Capture page state |
| hover_element | Hover for tooltips/dropdowns |
| handle_dialog | Accept/dismiss browser dialogs |
| navigate_page | Go back/forward/reload |
| drag_element | Drag and drop |
The SKILL.md must instruct the agent to load these tools before starting browser phases.
For VPS/headless mode, the generated skill includes browser_adapter.py with PlaywrightAdapter. The entry point script handles Playwright lifecycle:
import os
MODE = os.environ.get("SKILL_MODE", "vscode")
if MODE == "playwright":
from playwright.sync_api import sync_playwright
from scripts.browser_adapter import PlaywrightAdapter
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
adapter = PlaywrightAdapter(page)
runner = MyRunner(config_path)
runner.browser = adapter
runner.run()
browser.close()
After generating all files, run through references/skill-checklist.md — it contains the full 50+ item QA checklist covering structure, SKILL.md completeness, Python code quality, config/secrets, state management, error handling, browser automation, Google Sheets, and evidence/logging.
Quick review (verify these regardless of skill type):
User says: "Create a skill that audits a GitHub repo, identifies all features, spins up the frontend, screenshots each feature, and generates a portfolio document."
Interview answers (inferred):
repo-portfoliodevelopment
Use when implementing UI, checking dark/light mode, or validating animations — adds a visual feedback loop via browser screenshots so frontend changes are verified, not assumed.
development
Use when Claude Code sessions had many manual approval ("press 1") prompts or when auditing hook permissions; identifies which Bash commands required approval.
tools
Use after merging a PR or during periodic cleanup to archive plan-mode files by linking them to merged PRs.
testing
Use when stress-testing a plan against the project's domain model — grills the design, sharpens terminology, and updates documentation (CONTEXT.md, ADRs) inline as decisions crystallise.