Documentation

Provider translation

Provider-agnostic does not mean every provider has equal capabilities. It means Stemma preserves canonical intent and reports every adaptation or loss.

Canonical concept to native mechanism#

How each canonical concept is expressed by each provider
Canonical concept Copilot Claude Codex Kiro
Always-on context.github/copilot-instructions.mdCLAUDE.mdAGENTS.mdinclusion: always
Path scopeapplyTo, comma-separated globspaths:, a glob listDirectory placement onlyfileMatchPattern
Excluded pathsScope note in the body — lossyScope note in the body — lossyScope note in the body — lossyScope note in the body — lossy
On-demand content.github/prompts/*.prompt.md.claude/skills/*/SKILL.md.agents/skills/*/SKILL.mdinclusion: manual or auto
Skill.github/skills/*/SKILL.md.claude/skills/*/SKILL.md.agents/skills/*/SKILL.md.kiro/skills/*/SKILL.md
Specialist agent.github/agents/*.md — native.claude/agents/*.md — nativeFlattened into AGENTS.md — lossy.kiro/agents/*.json — native
ProcedureNative prompt fileDelivered as a skill — adaptedDelivered as a skill — adaptedDelivered as a skill — adapted

The same entity, four ways#

One path-scoped entity for src/api/** and src/handlers/**, and what a real stemma apply --all wrote for each target.

GitHub Copilot

exact

applyTo carries both patterns as a comma-separated list. The filename is the one the entity was imported from — a preserved hint takes precedence over the generated name.

.github/instructions/api.instructions.md
---applyTo: "src/api/**,src/handlers/**"description: API layer conventions---# API conventions- Validate every request body at the boundary.- Return `application/problem+json` for errors.

Claude Code

exact

Claude rules accept the canonical include patterns in their paths front matter. With no hint preserved for this target, the filename is the full canonical ID, context.api-layer-conventions.

.claude/rules/context-api-layer-conventions.md
---paths:  - src/api/**  - src/handlers/**description: API layer conventions---# API layer conventions- Validate every request body at the boundary.- Return `application/problem+json` for errors.

Codex

lossy

Codex scopes by file location only. Two patterns do not share one directory, so the content stays in the root AGENTS.md with a scope note and STEMMA3201.

AGENTS.md
# demo## API layer conventions> Scope note: this guidance is meant for src/api/**, src/handlers/**.- Validate every request body at the boundary.- Return `application/problem+json` for errors.

Kiro

exact

fileMatchPattern accepts an array of patterns. The filename is the full canonical ID, as for any target with no preserved hint.

.kiro/steering/context-api-layer-conventions.md
---inclusion: fileMatchfileMatchPattern:  - src/api/**  - src/handlers/**---# API layer conventions- Validate every request body at the boundary.- Return `application/problem+json` for errors.

Why Codex is different#

Codex has no glob-based scoping at all. It builds its instruction chain from the repository root down to the directory the session started in, and the nearest file wins. A nested src/api/AGENTS.md is active when Codex starts in src/api or below — it is not a general file-glob mechanism.

So when include patterns resolve to exactly one concrete directory, Stemma writes a nested file:

src/api/AGENTS.md
# Instructions for src/api## API packageValidate every request body at the boundary. Return problem+json errors.

When the include patterns resolve to one concrete directory, Stemma writes a nested AGENTS.md instead.

When they do not, Stemma refuses to invent a directory. The content stays in the root AGENTS.md with a scope note and STEMMA3201, and a profile can pin a directory or skip the entity for that target.

Two other Codex limits worth knowing

Broadening a pattern such as src/api/*.ts to the directory src/api matches more files, and is reported as STEMMA3202. And Codex has no specialist-agent format: agent definitions are flattened into always-on guidance with STEMMA3302, and Stemma never calls the result a native agent.

Brace groups never reach a provider#

A pattern such as src/**/*.{ts,tsx} is expanded into separate patterns on import and again before projection, so what a provider receives is always a plain list. Copilot and Claude both document brace syntax of their own; Stemma does not rely on it, which is what makes the same canonical scope mean one thing across all four targets. Expansion is bounded at 1000 alternatives and 32 nested groups, and an oversized group is rejected on import with a blocking STEMMA2102 instead of being partially expanded.

Copilot's applyTo is a comma-separated list, so Stemma splits it with brace nesting in mind — a comma inside {ts,tsx} is not a separator, and an unclosed group is rejected with STEMMA2101 rather than imported as a scope that matches nothing. A pattern carrying a literal comma stays valid canonically but cannot be written unambiguously into that list: lossy, STEMMA3102, and a scope note in the body.

Native skills do not imply complete package migration

Stemma imports recognized SKILL.md files, not their entire directories. Supporting templates, reference documents and scripts are not automatically copied, and paths or provider names in the body are not automatically rewritten. Generated names can also change a skill's invocation command. Review migration names, references and resources; an entity's projection outcome is not a dependency check.

Metadata must have the type it claims#

Recognized front matter is type-checked before any entity is created. Strings must be strings, enabled a boolean, and tool lists a string or a list of strings. A present value of the wrong type — null included — is a blocking STEMMA1101 naming the file, the key, the expected type and the type found; the import aborts without writing or replacing the canonical project, and the provider file is preserved verbatim as an opaque block. Kiro's JSON agents follow the same policy under STEMMA1501.

The point is not strictness for its own sake. Invalid metadata that were coerced instead of refused could turn a scoped instruction into always-on context, or drop a tool restriction without saying so. Unknown keys are untouched by this: they stay provider extensions, uninterpreted.

Generated filenames changed for existing projects

A fallback filename is now the complete canonical ID with its type prefix (rule.testing → rule-testing.instructions.md), so two entities can share a title — even across types — without colliding. Cross-provider output with no preserved hint may therefore move from a title-based name to an ID-based one. Review plan before applying: Stemma proposes the old paths for deletion but never deletes them, so remove the obsolete provider files yourself once you have read their replacements, or an agent will load both versions. A profile destination can keep an existing name where it does not conflict.

Capability matrix#

Every claim below is traced to official provider documentation, with the date it was verified, in the repository's compatibility document. Baseline: 2026-09-provider-baseline-1.

Capability support by provider. Each cell states support in words as well as colour.
Capability Copilot import + export Claude import + export Codex import + export Kiro import + export Cursor not implemented
Always-on instructionsGuidance loaded into every request.yesyesyesyesplanned
Path-scoped instructionsGuidance loaded only when matching files are in scope.yesyespartialyesplanned
Include glob patternsA scope expressed as a pattern rather than a directory.yesyesnoyesplanned
Exclude glob patternsNo implemented provider has negative pattern syntax: STEMMA3101.nonononoplanned
Several include patterns per unitMore than one pattern in a single instruction file.yesyesn/ayesplanned
Directory hierarchy affects precedenceFiles deeper in the tree take precedence over shallower ones.noyesyesnoplanned
Native skillsA documented SKILL.md format.yesyesyesyesplanned
Native specialist agentsA dedicated file format for a sub-agent definition.yesyesnoyesplanned
Native procedures / prompt filesAn invocable workflow format. Other targets deliver these as skills.yesnononoplanned
Manual invocationContent a person can call up on demand.yesyesyesyesplanned
Agent tool allowlistTool names carried on an agent definition. Stemma never translates them.yesyesnoyesplanned
Opaque provider content re-emittedContent Stemma refused to interpret is written back verbatim.yesyesyesyesplanned

Cursor#

Stemma declares the cursor target identifier so profiles and reports can reference it, and refuses to compile for it. stemma plan --target cursor fails with STEMMA3001 and exit code 3. Nothing about Cursor is simulated.

What each outcome means is covered in projection outcomes and diagnostics.

Source of truth for this page: docs/provider-compatibility.md ↗