How to Develop New OpenSEO Skills: The Complete Workflow Guide
Developing a new OpenSEO skill requires creating a canonical SKILL.md file in .agents/skills/<kebab-name>/, declaring it as internal or public, and wiring it into the Claude Code symlinks, test rosters, documentation, and plugin manifests to ensure the AI agent can execute it.
OpenSEO skills are reusable, markdown-driven workflow definitions that AI agents—including Claude Code, Codex, and the in-app SAM—can execute to perform SEO tasks. In the every-app/open-seo repository, adding a new skill follows a strict pipeline that keeps definitions canonical, discoverable, and synchronized across the entire codebase.
Establishing the Canonical Skill Location
All skill definitions live under **/.agents/skills/<kebab-name>/SKILL.md**. This path serves as the single source of truth for both internal tooling and public product features. The name field in the front-matter must exactly match the kebab-case folder name.
Creating the Skill Skeleton
Begin by creating the directory and the main definition file:
mkdir .agents/skills/my-new-skill
Create SKILL.md with the required YAML front-matter and markdown body:
---
name: my-new-skill
description: Performs a specific SEO workflow. Use when the user requests competitive analysis.
metadata:
internal: true # Omit this line for public product skills
---
# My New Skill
## Context
{{ get_project_context(projectId) }}
## Steps
1. Analyze the input...
2. Generate recommendations...
The complete template structure is documented in .agents/skills/create-repo-skill/SKILL.md.
Internal vs. Public Skills
You must declare the skill type using the metadata.internal flag:
- Internal repo skills: Set
metadata.internal: true. These require only a symlink in.claude/skills/so Claude Code agents can load them, with no public documentation required. - Public product skills: Omit the
internalflag entirely. These must be registered in every user-facing location including documentation, UI lists, and plugin manifests so end-users can discover and install them.
Wiring Skills into the Ecosystem
After establishing the canonical file, register the skill across seven destinations to make it discoverable and executable.
Claude Code Integration via Symlinks
For internal skills, create a symbolic link from the Claude Code skills directory to the canonical source:
ln -s ../../.agents/skills/my-new-skill .claude/skills/my-new-skill
This ensures Claude Code loads the skill definition directly from .agents/skills/ without maintaining stale copies.
Test Registry and SAM Integration
Add the skill name to the roster in src/server/features/sam/samSkills.test.ts. The test suite validates that this list remains current and will fail if it drifts from the actual skill implementations, preventing broken deployments.
Documentation and UI Registration
For public skills, create a documentation page at web/content/docs/skills/<kebab-name>.mdx and update web/content/docs/skills/meta.json to add navigation entries. Additionally, insert the skill slug into the SKILL_NAMES array in src/routes/_app/ai.tsx to expose it in the web interface dropdown.
Plugin Bundling
Add the skill directory to plugins/openseo/skills/ and execute the synchronization command:
pnpm sync-plugin-skills
The scripts/sync-plugin-skills.mjs script copies canonical files into the Claude Code and Codex plugin bundles, ensuring published plugins contain the latest definitions.
Maintaining Synchronization
To prevent configuration drift between the canonical source and deployed instances, always validate your changes after editing.
Validating with Sync-Check
Run the format step and the drift detection loop to verify that every entry in .claude/skills/* is a symlink pointing to a valid source in .agents/skills/:
pnpm format:write
for d in .claude/skills/*/; do
n=$(basename "$d")
[ -L "${d%/}" ] || echo "DRIFT RISK — not a symlink: $n"
[ -e ".agents/skills/$n" ] || echo "BROKEN — no canonical source: $n"
done
This validation catches hardcoded copies that could become outdated and ensures the repository remains the single source of truth.
Publishing and Installation
Once committed and pushed, users can install the new skill using the standard command:
npx skills add every-app/open-seo --skill my-new-skill
To install all available OpenSEO skills at once, use the wildcard syntax:
npx skills add every-app/open-seo --skill '*'
These commands pull the canonical definitions from the repository and make them available to local AI agents immediately.
Summary
- Canonical location: Place all skills in
.agents/skills/<kebab-name>/SKILL.mdas the single source of truth. - Type declaration: Set
metadata.internal: truefor internal tools; omit entirely for public features requiring full registration. - Ecosystem wiring: Register skills in Claude Code symlinks, SAM test files (
src/server/features/sam/samSkills.test.ts), UI registries (src/routes/_app/ai.tsx), documentation (web/content/docs/skills/), and plugin manifests. - Synchronization: Run
pnpm sync-plugin-skillsand validation loops to prevent drift between canonical sources and deployed instances. - Installation: Users consume skills via
npx skills add every-app/open-seo --skill <kebab-name>.
Frequently Asked Questions
What file format does an OpenSEO skill use?
OpenSEO skills are markdown files with YAML front-matter containing name, description, and metadata fields. The workflow logic is written in the markdown body using templated instructions that AI agents interpret and execute.
Where should I place a new skill in the repository?
Place the canonical SKILL.md inside .agents/skills/<kebab-name>/, where <kebab-name> is a kebab-case identifier matching the name field in the front-matter. This location acts as the single source of truth referenced by symlinks, tests, and plugin bundles.
How do I make a skill available to Claude Code?
Create a symbolic link from .claude/skills/<kebab-name> pointing to ../../.agents/skills/<kebab-name>. This symlink allows Claude Code agents to load the skill definition directly from the canonical source rather than from a potentially stale copy.
How do I prevent skills from drifting out of sync?
Run the sync-check validation script to ensure all entries in .claude/skills/ are symlinks pointing to valid directories in .agents/skills/. Additionally, the test suite in src/server/features/sam/samSkills.test.ts will fail if the skill roster does not match the actual available skills, catching registration errors before deployment.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →