π―What you get here
Complete mental model of polyskill β why it exists, what problem it addresses, and how it works internally. Without this, the CLI in the next lesson becomes "memorized commands." With it, the architecture is clear.
Detailed content
π The open Agent Skills spec (agentskills.io)
Standard originating at Anthropic and released as an open spec. Adopted by 40+ tools today. Defines the canonical skill format: SKILL.md + YAML frontmatter + Markdown body + folder conventions.
The 4 pillars β what ALL runtimes agree on
SKILL.md β don't invent variationsname e descriptionscripts/, references/, assets/π‘Why this matters
Everything you write within these 4 pillars works in any compatible runtime. Everything OUTSIDE (allowed-tools, backtick-bang, openai.yaml, model override) ties you to a specific runtimeβand thatβs where the polyskill work comes in.
Key concepts
agentskills.io
Broad adoption
Portable core
Outside the 4 = runtime
π© The pain β maintaining two divergent skills
Without understanding the pain, polyskill seems like overkill. This is the story EVERYONE who uses both runtimes goes through:
Day 1 β Create a skill in Claude
Works perfectly. Youβre happy.
Day 2 β Copy/adapt it for Codex
Move it to .agents/skills/, remove the backtick-bang, adjust the description. It works in both. Youβre still happy with it.
Week 2 β Improve Claude's (forget Codex's)
Find a new use case, add instructions to Claude. Forget to propagate them.
Week 3 β Improve Codex's (forget Claude's)
It was in Codex, spotted a bug, fixed it. Forgot to bring the change over to Claude.
Month 1 β TWO DIFFERENT skills
The versions diverged in 4 places. You don't remember which one is right. Every time you improve one, you throw away the improvement in the other. Ambiguous source of truth.
πInvisible costs of drift
- β’ Time wasted deciding "which version is the good one"
- β’ Bugs come back (you fixed it in one version and forgot in the other)
- β’ Feature works in one agent, but not the other
- β’ Team gets confused (skill behaves differently)
- β’ Documentation gets outdated on both sides
Key concepts
Inevitable without tooling
Diverging versions
What's the best option?
Constant decision-making
π‘ The core idea β one source, multiple targets
Polyskill solves the pain point by a compiler turns "portable code". You write the skill ONCE in the canonical portable format (definition.md). The polyskill compiles to dist/claude/ e dist/codex/, each optimized for the target runtime.
Direct analogy β Babel/TypeScript
Same metaphor: canonical source, selective compilation by target, optimized output.
What the structure looks like
minha-skill/ βββ definition.md β SOURCE canΓ΄nica (vocΓͺ edita aqui) βββ scripts/ βββ references/ βββ assets/ βββ dist/ β OUTPUTS (gerados pelo polyskill build) βββ claude/ β βββ minha-skill/ β βββ SKILL.md β versΓ£o Claude (com allowed-tools, backtick-bang...) βββ codex/ βββ minha-skill/ βββ SKILL.md β versΓ£o Codex (sem bang, description front-loaded) βββ agents/ βββ openai.yaml β sidecar gerado automaticamente
π―The "aha moment"
You never edit dist/. Edit only definition.md. Run polyskill build. O dist/ reflects. Runs polyskill install. Both runtimes get the latest version. A single source of truth.
Key concepts
definition.md
polyskill build
Don't edit by hand
By adapter
π§± The 3 pieces β IR, adapters, CLI
Inside, polyskill has three parts. Once you understand that, you can see that adding Gemini/Cursor/Copilot is ONE file β the adapter. No rewrite.
1. IR (Intermediate Representation)
A runtime-neutral version of everything a skill needs to be, with NO ties to a specific runtime. Itβs the esperanto of polyskill.
2. Adapters
One TypeScript file per runtime. Each adapter implements parse() + emit() + validate(). Plug in β supported. Remove β gone.
3. CLI
What you run in the terminal. It orchestrates adapters via the registry. It doesnβt know runtime details β ask the adapter.
Visual architecture
The Adapter interface
interface Adapter { name: string; // LΓͺ o formato do runtime e devolve IR parse(path: string): IR; // Pega IR e escreve no formato do runtime emit(ir: IR, outputDir: string): void; // Roda regras especΓficas do runtime (lint) validate(ir: IR): ValidationResult; } // Registrar Γ© literalmente uma linha: register(new CodexAdapter());
πWhy this scales
When Gemini CLI gains traction, someone implements src/adapters/gemini.ts with parse/emit/validate, registers in the registry, opens a PR. Polyskill gains Gemini support without changing a single line of core. Same thing for Cursor, Copilot, whatever comes next.
Key concepts
No runtime lock-in
Adapter contract
Dynamic plugin
Via PR adapter
π Round-trip β Claude β portable β Codex
The Adapter βreads AND writes.β You can import an existing Claude skill (--from claude), make it portable, then emit for both. You don't have to start from scratch.
Round-trip workflows
Claude β portable import
$ polyskill import \ ~/.claude/skills/x \ --from claude
Reads SKILL.md + scripts + references. Generates definition.md while preserving everything.
Codex β portable import
$ polyskill import \ ~/.agents/skills/x \ --from codex
Reads SKILL.md + sidecar openai.yaml. Normalizes to portable.
Lossless when possible, lossy when needed
Round-trip preserves almost everything:
- β
scripts/,references/,assets/pass through intact in both directions - β Portable frontmatter (name, description) is preserved
- β Markdown body is preserved
Runtime-specific things become markers in the IR:
- β οΈ Claudeβs backtick-bang β IR marks it as "dynamic injection" β emitted to Codex as prose
- β οΈ Codexβs openai.yaml sidecar β IR marks it as "mcp deps" + "branding" β emitted to Claude as
allowed-tools
Key concepts
Reads AND writes
Origin flag
scripts/refs/assets
Bang β prose
π‘οΈ Drift policy β protection against overwriting
Every time it builds, polyskill calculates the hash of the output files. On the next build, if any destination file was edited manually outside polyskill, the build ABORTS with an error. You decide.
The drift workflow
polyskill build β generates dist/claude/x/SKILL.md, stores the hash in .polyskill-hashes~/.claude/skills/x/SKILL.md (specific adjustment)polyskill build again--force (overwrites, loses customization) OR polyskill reconcile (inspects, decides).β Why this is safe
- β’ Never silently overwrites your work
- β’ Drift is SEEN, not hidden
- β’ You always have the option to force OR reconcile
- β’ Production edits can be detected in the next build
β Without a drift policy, it would beβ¦
- β’ A manual adjustment would disappear in the next build
- β’ You'd never know (no error)
- β’ Trust in the tool would drop
- β’ You'd go back to manual maintenance anyway
Output example
$ polyskill build β Drift detected! The following targets have been modified outside polyskill: - ~/.claude/skills/x/SKILL.md (last hash: a3f9...; current: 8d2b...) Options: - Run `polyskill build --force` to overwrite (loses local edits) - Run `polyskill reconcile` to inspect and merge Build aborted.
Key concepts
.polyskill-hashes
Abort first
Opt-in override
Interactive merge
π¦ The meta-skill β polyskill as a skill
Poetic detail: polyskill if it distributes using itself. Comes as an installable skill in both runtimes. You invoke it in natural language; the skill calls the CLI under the hood, translating your request into commands.
π· Claude Code
/polyskill converts my skill y-compare to work in both runtimes
Skill receives NL, translates to:
$ polyskill import \
~/.claude/skills/y-compare \
--from claude
$ polyskill build
π£ Codex
$polyskill converte minha skill y-compare pra funcionar nos dois runtimes
Same skill, same translation:
$ polyskill import \
~/.agents/skills/y-compare \
--from codex
$ polyskill build
Installation paths β A vs. B
Copy skill/dist/claude/polyskill to ~/.claude/skills/ e skill/dist/codex/polyskill to ~/.agents/skills/. Without CLI. Only the meta-skill works; the commands it needs to run break.
Clone the repo, npm install && npm run build && npm link. Full CLI on the PATH. To build your own skills, B is required.
π‘Full dogfooding
Polyskill solves the "cross-runtime skills" problem by using a cross-runtime skill that it generates itself. If the meta-skill works in both runtimes, polyskill proves it works. If it breaks in one, that proves the opposite. Architectural honesty.
Key concepts
Polyskill as a skill
No need to memorize flags
Without CLI / with
Use the tool itself
π―Module summary
Next module:
5.2 β polyskill CLI in practice (init, import, build, install, validate, reconcile)