Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Create and push reusable skills to SkillNote from Codex when repeated instructions are detected or the user says "create a skill", "save this pattern", "push a skill". Guides drafting, review, collection selection, and publishing.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | -11% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 82% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 65% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 17% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 39% | 0% |
Create and push reusable skills to the SkillNote registry so all connected agents learn from repeated patterns.
The SkillNote API is at: http://${CLAUDE_PLUGIN_OPTION_HOST:-localhost}:8082
Only suggest for PERSISTENT conventions, not temporary workarounds.
If the user did not explicitly ask to create a skill, you MUST ask first before doing anything else.
Tell the user what you noticed in one sentence. Be specific. Then ask: "Want me to save this as a SkillNote skill?"
Stop and wait for an explicit yes. Do NOT draft the name/description/content, fetch collections, or present a preview until the user confirms. Unsolicited drafts feel pushy and waste attention.
Skip this step only when the user already said "create a skill for X" / "save this pattern" / "push a skill" in their own words.
Collaborate on three fields:
name: lowercase, hyphens, digits only, max 64 chars. Also used as slug.
description (max 1024 chars — THIS IS THE TRIGGER): Must include what the skill does + explicit trigger keywords. Agents decide to use a skill based solely on its description.
content: Instructions under 200 lines. Start with # Title. Be actionable with examples.
Show the full draft to the user.
pythonimport urllib.request, json, os api = f"http://{os.environ.get('CLAUDE_PLUGIN_OPTION_HOST', 'localhost')}:8082" try: resp = urllib.request.urlopen(f"{api}/v1/skills/<SLUG>") print(f"EXISTS: v{json.loads(resp.read()).get('current_version', '?')}") except urllib.error.HTTPError as e: print("NEW" if e.code == 404 else f"ERROR: {e.code}")
pythonimport urllib.request, json, os api = f"http://{os.environ.get('CLAUDE_PLUGIN_OPTION_HOST', 'localhost')}:8082" try: cols = json.loads(urllib.request.urlopen(f"{api}/v1/collections").read()) for c in cols: print(f" - {c['name']} ({c['count']} skills)") if not cols: print(" (no collections yet)") except Exception as e: print(f"Could not fetch: {e}")
Every skill must belong to at least one collection. Use AskUserQuestion to let the user pick:
^[a-z0-9_-]+$ (lowercase letters, numbers, hyphens, underscores), 1–128 chars, and cannot contain reserved words anthropic or claudeIf the user types an invalid name, the POST /v1/skills call will return 422 COLLECTION_NAME_INVALID. Surface the error, explain the rule, and ask them to type a valid name before retrying.
Show complete skill preview. Emphasize: "Does the description have good trigger keywords?" Wait for approval.
pythonimport json, urllib.request, os api = f"http://{os.environ.get('CLAUDE_PLUGIN_OPTION_HOST', 'localhost')}:8082" payload = json.dumps({"name": "<NAME>", "slug": "<NAME>", "description": "<DESC>", "content_md": "<CONTENT>", "collections": ["<COL>"]}).encode() req = urllib.request.Request(f"{api}/v1/skills", data=payload, headers={"Content-Type": "application/json"}, method="POST") try: result = json.loads(urllib.request.urlopen(req).read()) print(f"Created: {result['slug']} v{result['current_version']}") except urllib.error.HTTPError as e: print(f"Error: {json.loads(e.read())}")
pythonimport json, urllib.request, os api = f"http://{os.environ.get('CLAUDE_PLUGIN_OPTION_HOST', 'localhost')}:8082" payload = json.dumps({"name": "<NAME>", "description": "<DESC>", "content_md": "<CONTENT>", "collections": ["<COL>"]}).encode() req = urllib.request.Request(f"{api}/v1/skills/<SLUG>", data=payload, headers={"Content-Type": "application/json"}, method="PATCH") try: result = json.loads(urllib.request.urlopen(req).read()) print(f"Updated: {result['slug']} v{result['current_version']}") except urllib.error.HTTPError as e: print(f"Error: {json.loads(e.read())}")
After success: link to http://${CLAUDE_PLUGIN_OPTION_HOST:-localhost}:3000/skills/<slug> for viewing.
Other measured skills in the registry, with their headline benchmark lift.