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 internal flag 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.

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.md as the single source of truth.
  • Type declaration: Set metadata.internal: true for 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-skills and 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →