From 1cd1cf17c6f11d5d7f513763b47ec55d1fe980a4 Mon Sep 17 00:00:00 2001 From: Gav Verma Date: Thu, 18 Dec 2025 14:30:00 -0800 Subject: [PATCH] Update system skills bundled with codex-rs (#8253) Synced with https://github.com/openai/skills/tree/main/skills/.system --- .gitignore | 5 + .../src/skills/assets/samples/plan/SKILL.md | 33 ++-- .../assets/samples/skill-creator/SKILL.md | 21 ++- .../skill-creator/scripts/init_skill.py | 155 ++++++++++++------ .../skill-creator/scripts/quick_validate.py | 10 +- 5 files changed, 152 insertions(+), 72 deletions(-) diff --git a/.gitignore b/.gitignore index a58e9dfb7..07bc15ccd 100644 --- a/.gitignore +++ b/.gitignore @@ -85,3 +85,8 @@ CHANGELOG.ignore.md # nix related .direnv .envrc + +# Python bytecode files +__pycache__/ +*.pyc + diff --git a/codex-rs/core/src/skills/assets/samples/plan/SKILL.md b/codex-rs/core/src/skills/assets/samples/plan/SKILL.md index 5bdfc9bb3..f202ee9e4 100644 --- a/codex-rs/core/src/skills/assets/samples/plan/SKILL.md +++ b/codex-rs/core/src/skills/assets/samples/plan/SKILL.md @@ -1,13 +1,17 @@ --- name: plan -description: Plan lifecycle management for Codex plans stored in $CODEX_HOME/plans (default ~/.codex/plans). Use when a user asks to create, find, read, update, delete, or manage plan documents for implementation work or overview/reference documentation. +description: Generate a plan for how an agent should accomplish a complex coding task. Use when a user asks for a plan, and optionally when they want to save, find, read, update, or delete plan files in $CODEX_HOME/plans (default ~/.codex/plans). --- # Plan ## Overview -Create and manage plan documents on disk. Plans stored on disk are markdown files with YAML frontmatter and free-form content. When drafting in chat, output only the plan body without frontmatter; add frontmatter only when stashing to disk. Support both implementation plans and overview/reference plans. Only write to the plans folder; do not modify the repository codebase. +Draft structured plans that clarify intent, scope, requirements, action items, testing/validation, and risks. + +Optionally, save plans to disk as markdown files with YAML frontmatter and free-form content. When drafting in chat, output only the plan body without frontmatter; add frontmatter only when saving to disk. Only write to the plans folder; do not modify the repository codebase. + +This skill can also be used to draft codebase or system overviews. ## Core rules @@ -36,11 +40,13 @@ Create and manage plan documents on disk. Plans stored on disk are markdown file ## Plan creation workflow -1. Read relevant docs and entry points (`README.md`, `docs/`, key modules) to scope requirements. -2. Identify scope, constraints, and data model/API implications (or capture existing behavior for an overview). -3. Draft either an ordered implementation plan or a structured overview plan with diagrams/notes as needed. -4. Immediately output the plan body only (no frontmatter), then ask the user if they want to 1. Make changes, 2. Implement it, 3. Stash it as per plan. -5. If the user wants to stash it, prepend frontmatter and save the plan under the computed plans directory using `scripts/create_plan.py`. +1. Scan context quickly: read README.md and obvious docs (docs/, CONTRIBUTING.md, ARCHITECTURE.md); skim likely touched files; identify constraints (language, frameworks, CI/test commands, deployment). +2. Ask follow-ups only if blocked: at most 1-2 questions, prefer multiple-choice. If unsure but not blocked, state assumptions and proceed. +3. Identify scope, constraints, and data model/API implications (or capture existing behavior for an overview). +4. Draft either an ordered implementation plan or a structured overview plan with diagrams/notes as needed. +5. Immediately output the plan body only (no frontmatter), then ask the user if they want to 1. Make changes, 2. Implement it, 3. Save it as per plan. +6. If the user wants to save it, prepend frontmatter and save the plan under the computed plans directory using `scripts/create_plan.py`. + ## Plan update workflow @@ -73,7 +79,7 @@ python ./scripts/list_plans.py --query "rate limit" ## Plan file format -Use one of the structures below for the plan body. When drafting, output only the body (no frontmatter). When stashing, prepend this frontmatter: +Use one of the structures below for the plan body. When drafting, output only the body (no frontmatter). When saving, prepend this frontmatter: ```markdown --- @@ -162,8 +168,11 @@ description: <1-line summary> ## Writing guidance -- Keep action items ordered and concrete; include file/entry-point hints. -- For overview plans, keep action items minimal and set sections to "None" when not applicable. -- Always include testing/validation and risks/edge cases in implementation plans. +- Start with 1 short paragraph describing intent and approach. +- Keep action items ordered and atomic (discovery -> changes -> tests -> rollout); use verb-first phrasing. +- Scale action item count to complexity (simple: 1-2; complex: up to about 10). +- Include file/entry-point hints and concrete validation steps where useful. +- Always include testing/validation and risks/edge cases in implementation plans; include safe rollout/rollback when relevant. - Use open questions only when necessary (max 3). -- If a section is not applicable, note "None" briefly rather than removing it. +- Avoid vague steps, micro-steps, and code snippets; keep the plan implementation-agnostic. +- For overview plans, keep action items minimal and set non-applicable sections to "None." diff --git a/codex-rs/core/src/skills/assets/samples/skill-creator/SKILL.md b/codex-rs/core/src/skills/assets/samples/skill-creator/SKILL.md index 64f076f18..23836e5d8 100644 --- a/codex-rs/core/src/skills/assets/samples/skill-creator/SKILL.md +++ b/codex-rs/core/src/skills/assets/samples/skill-creator/SKILL.md @@ -1,5 +1,5 @@ --- -name: Skill Creator +name: skill-creator description: Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Codex's capabilities with specialized knowledge, workflows, or tool integrations. --- @@ -214,6 +214,7 @@ Follow these steps in order, skipping only if there is a clear reason why they a ### Skill Naming - Use lowercase letters, digits, and hyphens only; normalize user-provided titles to hyphen-case (e.g., "Plan Mode" -> `plan-mode`). +- When generating names, generate a name under 30 characters (letters, digits, hyphens). - Prefer short, verb-led phrases that describe the action. - Namespace by tool when it improves clarity or triggering (e.g., `gh-address-comments`, `linear-address-issue`). - Name the skill folder exactly after the skill name. @@ -270,17 +271,25 @@ When creating a new skill from scratch, always run the `init_skill.py` script. T Usage: ```bash -scripts/init_skill.py --path +scripts/init_skill.py --path [--resources scripts,references,assets] [--examples] +``` + +Examples: + +```bash +scripts/init_skill.py my-skill --path skills/public +scripts/init_skill.py my-skill --path skills/public --resources scripts,references +scripts/init_skill.py my-skill --path skills/public --resources scripts --examples ``` The script: - Creates the skill directory at the specified path - Generates a SKILL.md template with proper frontmatter and TODO placeholders -- Creates example resource directories: `scripts/`, `references/`, and `assets/` -- Adds example files in each directory that can be customized or deleted +- Optionally creates resource directories based on `--resources` +- Optionally adds example files when `--examples` is set -After initialization, customize or remove the generated SKILL.md and example files as needed. +After initialization, customize the SKILL.md and add resources as needed. If you used `--examples`, replace or delete placeholder files. ### Step 4: Edit the Skill @@ -301,7 +310,7 @@ To begin implementation, start with the reusable resources identified above: `sc Added scripts must be tested by actually running them to ensure there are no bugs and that the output matches what is expected. If there are many similar scripts, only a representative sample needs to be tested to ensure confidence that they all work while balancing time to completion. -Any example files and directories not needed for the skill should be deleted. The initialization script creates example files in `scripts/`, `references/`, and `assets/` to demonstrate structure, but most skills won't need all of them. +If you used `--examples`, delete any placeholder files that are not needed for the skill. Only create resource directories that are actually required. #### Update SKILL.md diff --git a/codex-rs/core/src/skills/assets/samples/skill-creator/scripts/init_skill.py b/codex-rs/core/src/skills/assets/samples/skill-creator/scripts/init_skill.py index 2f49f0191..c70271727 100644 --- a/codex-rs/core/src/skills/assets/samples/skill-creator/scripts/init_skill.py +++ b/codex-rs/core/src/skills/assets/samples/skill-creator/scripts/init_skill.py @@ -3,19 +3,22 @@ Skill Initializer - Creates a new skill from template Usage: - init_skill.py --path + init_skill.py --path [--resources scripts,references,assets] [--examples] Examples: init_skill.py my-new-skill --path skills/public - init_skill.py my-api-helper --path skills/private + init_skill.py my-new-skill --path skills/public --resources scripts,references + init_skill.py my-api-helper --path skills/private --resources scripts --examples init_skill.py custom-skill --path /custom/location """ +import argparse import re import sys from pathlib import Path -MAX_SKILL_NAME_LENGTH = 64 +MAX_SKILL_NAME_LENGTH = 30 +ALLOWED_RESOURCES = {"scripts", "references", "assets"} SKILL_TEMPLATE = """--- name: {skill_name} @@ -64,9 +67,9 @@ Delete this entire "Structuring This Skill" section when done - it's just guidan - Concrete examples with realistic user requests - References to scripts/templates/references as needed] -## Resources +## Resources (optional) -This skill includes example resource directories that demonstrate how to organize different types of bundled resources: +Create only the resource directories this skill actually needs. Delete this section if no resources are required. ### scripts/ Executable code (Python/Bash/etc.) that can be run directly to perform specific operations. @@ -101,7 +104,7 @@ Files not intended to be loaded into context, but rather used within the output --- -**Any unneeded directories can be deleted.** Not every skill requires all three types of resources. +**Not every skill requires all three types of resources.** """ EXAMPLE_SCRIPT = '''#!/usr/bin/env python3 @@ -202,13 +205,62 @@ def title_case_skill_name(skill_name): return " ".join(word.capitalize() for word in skill_name.split("-")) -def init_skill(skill_name, path): +def parse_resources(raw_resources): + if not raw_resources: + return [] + resources = [item.strip() for item in raw_resources.split(",") if item.strip()] + invalid = sorted({item for item in resources if item not in ALLOWED_RESOURCES}) + if invalid: + allowed = ", ".join(sorted(ALLOWED_RESOURCES)) + print(f"❌ Error: Unknown resource type(s): {', '.join(invalid)}") + print(f" Allowed: {allowed}") + sys.exit(1) + deduped = [] + seen = set() + for resource in resources: + if resource not in seen: + deduped.append(resource) + seen.add(resource) + return deduped + + +def create_resource_dirs(skill_dir, skill_name, skill_title, resources, include_examples): + for resource in resources: + resource_dir = skill_dir / resource + resource_dir.mkdir(exist_ok=True) + if resource == "scripts": + if include_examples: + example_script = resource_dir / "example.py" + example_script.write_text(EXAMPLE_SCRIPT.format(skill_name=skill_name)) + example_script.chmod(0o755) + print("✅ Created scripts/example.py") + else: + print("✅ Created scripts/") + elif resource == "references": + if include_examples: + example_reference = resource_dir / "api_reference.md" + example_reference.write_text(EXAMPLE_REFERENCE.format(skill_title=skill_title)) + print("✅ Created references/api_reference.md") + else: + print("✅ Created references/") + elif resource == "assets": + if include_examples: + example_asset = resource_dir / "example_asset.txt" + example_asset.write_text(EXAMPLE_ASSET) + print("✅ Created assets/example_asset.txt") + else: + print("✅ Created assets/") + + +def init_skill(skill_name, path, resources, include_examples): """ Initialize a new skill directory with template SKILL.md. Args: skill_name: Name of the skill path: Path where the skill directory should be created + resources: Resource directories to create + include_examples: Whether to create example files in resource directories Returns: Path to created skill directory, or None if error @@ -241,61 +293,49 @@ def init_skill(skill_name, path): print(f"❌ Error creating SKILL.md: {e}") return None - # Create resource directories with example files - try: - # Create scripts/ directory with example script - scripts_dir = skill_dir / "scripts" - scripts_dir.mkdir(exist_ok=True) - example_script = scripts_dir / "example.py" - example_script.write_text(EXAMPLE_SCRIPT.format(skill_name=skill_name)) - example_script.chmod(0o755) - print("✅ Created scripts/example.py") - - # Create references/ directory with example reference doc - references_dir = skill_dir / "references" - references_dir.mkdir(exist_ok=True) - example_reference = references_dir / "api_reference.md" - example_reference.write_text(EXAMPLE_REFERENCE.format(skill_title=skill_title)) - print("✅ Created references/api_reference.md") - - # Create assets/ directory with example asset placeholder - assets_dir = skill_dir / "assets" - assets_dir.mkdir(exist_ok=True) - example_asset = assets_dir / "example_asset.txt" - example_asset.write_text(EXAMPLE_ASSET) - print("✅ Created assets/example_asset.txt") - except Exception as e: - print(f"❌ Error creating resource directories: {e}") - return None + # Create resource directories if requested + if resources: + try: + create_resource_dirs(skill_dir, skill_name, skill_title, resources, include_examples) + except Exception as e: + print(f"❌ Error creating resource directories: {e}") + return None # Print next steps print(f"\n✅ Skill '{skill_name}' initialized successfully at {skill_dir}") print("\nNext steps:") print("1. Edit SKILL.md to complete the TODO items and update the description") - print("2. Customize or delete the example files in scripts/, references/, and assets/") + if resources: + if include_examples: + print("2. Customize or delete the example files in scripts/, references/, and assets/") + else: + print("2. Add resources to scripts/, references/, and assets/ as needed") + else: + print("2. Create resource directories only if needed (scripts/, references/, assets/)") print("3. Run the validator when ready to check the skill structure") return skill_dir def main(): - if len(sys.argv) < 4 or sys.argv[2] != "--path": - print("Usage: init_skill.py --path ") - print("\nSkill name requirements:") - print(" - Use a hyphen-case identifier (e.g., 'data-analyzer')") - print( - " - Input is normalized to lowercase letters, digits, and hyphens only " - "(e.g., 'Plan Mode' -> 'plan-mode')" - ) - print(f" - Max {MAX_SKILL_NAME_LENGTH} characters after normalization") - print(" - Directory name matches the normalized skill name") - print("\nExamples:") - print(" init_skill.py my-new-skill --path skills/public") - print(" init_skill.py my-api-helper --path skills/private") - print(" init_skill.py custom-skill --path /custom/location") - sys.exit(1) + parser = argparse.ArgumentParser( + description="Create a new skill directory with a SKILL.md template.", + ) + parser.add_argument("skill_name", help="Skill name (normalized to hyphen-case)") + parser.add_argument("--path", required=True, help="Output directory for the skill") + parser.add_argument( + "--resources", + default="", + help="Comma-separated list: scripts,references,assets", + ) + parser.add_argument( + "--examples", + action="store_true", + help="Create example files inside the selected resource directories", + ) + args = parser.parse_args() - raw_skill_name = sys.argv[1] + raw_skill_name = args.skill_name skill_name = normalize_skill_name(raw_skill_name) if not skill_name: print("❌ Error: Skill name must include at least one letter or digit.") @@ -309,13 +349,24 @@ def main(): if skill_name != raw_skill_name: print(f"Note: Normalized skill name from '{raw_skill_name}' to '{skill_name}'.") - path = sys.argv[3] + resources = parse_resources(args.resources) + if args.examples and not resources: + print("❌ Error: --examples requires --resources to be set.") + sys.exit(1) + + path = args.path print(f"🚀 Initializing skill: {skill_name}") print(f" Location: {path}") + if resources: + print(f" Resources: {', '.join(resources)}") + if args.examples: + print(" Examples: enabled") + else: + print(" Resources: none (create as needed)") print() - result = init_skill(skill_name, path) + result = init_skill(skill_name, path, resources, args.examples) if result: sys.exit(0) diff --git a/codex-rs/core/src/skills/assets/samples/skill-creator/scripts/quick_validate.py b/codex-rs/core/src/skills/assets/samples/skill-creator/scripts/quick_validate.py index 4e99a7f9b..7fca5da5c 100644 --- a/codex-rs/core/src/skills/assets/samples/skill-creator/scripts/quick_validate.py +++ b/codex-rs/core/src/skills/assets/samples/skill-creator/scripts/quick_validate.py @@ -9,6 +9,8 @@ from pathlib import Path import yaml +MAX_SKILL_NAME_LENGTH = 30 + def validate_skill(skill_path): """Basic validation of a skill""" @@ -66,8 +68,12 @@ def validate_skill(skill_path): False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens", ) - if len(name) > 64: - return False, f"Name is too long ({len(name)} characters). Maximum is 64 characters." + if len(name) > MAX_SKILL_NAME_LENGTH: + return ( + False, + f"Name is too long ({len(name)} characters). " + f"Maximum is {MAX_SKILL_NAME_LENGTH} characters.", + ) description = frontmatter.get("description", "") if not isinstance(description, str):