You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Anthropic (Claude Code), OpenAI (Codex CLI / ChatGPT) and Google (Gemini CLI) have all converged on the same "Agent Skills" contract over the last 6 months. Skills are now a de-facto standard: a folder containing a SKILL.md with YAML frontmatter that the agent loads as metadata at startup and reads in full only when relevant.
The CLI should adopt the same on-disk format so users can drop an existing skill folder authored for Claude / Codex / Gemini into .infer/skills/ and have it just work — that is the "seamless transition" goal.
A skill is a directory (not a single file) — so it can ship scripts/, references/, assets/.
Entry file is SKILL.md (uppercase, exact name).
YAML frontmatter with at minimum name and description between --- delimiters at the very top of the file.
Progressive disclosure: only name + description go into the system prompt at startup; the body is read lazily when the model decides to activate the skill.
Two scopes: user-global (~/.<vendor>/skills/) and project-local (.<vendor>/skills/).
Project skills override user-global skills with the same name.
SKILL.md format (identical to Anthropic / Gemini / Codex):
---name: my-skill-namedescription: One-paragraph description that tells the model both WHAT this skill does and WHEN to use it. Used for routing — make it specific.---# My Skill
Step-by-step instructions, examples, and references for the model to follow
once this skill is activated.
Frontmatter validation (match Anthropic's spec to maximise portability):
name: required, ≤64 chars, lowercase letters + digits + hyphens only, must equal the directory name, must not contain infer / claude / anthropic / gemini / openai.
description: required, non-empty, ≤1024 chars.
Unknown frontmatter keys are tolerated (forward-compat with vendor extensions like Gemini's disabled: flag).
.infer/skills/pdf-processing/
├── SKILL.md # required: frontmatter + instructions
├── references/ # optional: extra .md files the body links to
├── scripts/ # optional: executable helpers (run via Bash tool)
└── assets/ # optional: templates, fixtures, etc.
Progressive disclosure (the whole point of the format — must be implemented this way, otherwise we burn context):
Startup: scan both skill dirs, parse frontmatter only, inject a single block into the agent system prompt listing each enabled skill's name, description, and absolute path. Body of SKILL.md is not loaded.
Runtime: the model decides to use a skill and reads SKILL.md (and any referenced files) using the existing Read tool. No new tool needed — Read already covers it.
The injected system-prompt block must include a short instruction telling the model how to activate a skill (e.g. "When a task matches a skill's description, read <path>/SKILL.md first, then follow its instructions").
Configuration (do not introduce .infer/skills/config.yaml — that diverges from every other CLI). Instead extend the existing config layout:
# .infer/config.yamlagent:
skills:
enabled: false # disabled by default (see acceptance criteria)disabled_skills: [] # optional per-skill opt-out by name
Env override: INFER_AGENT_SKILLS_ENABLED=true.
When enabled: false, the scan is skipped entirely — zero token cost, no system-prompt block injected.
Acceptance Criteria
Skills are loaded from .infer/skills/<name>/SKILL.md (project) and ~/.infer/skills/<name>/SKILL.md (user-global). Project wins on name collision.
infer init creates an empty .infer/skills/ directory and an example .infer/skills/example/SKILL.md (commented "delete me") so the format is discoverable.
agent.skills.enabled is added to config.yaml defaults as false. Skill loading is a no-op when disabled.
On startup (when enabled), the agent's system prompt includes a block listing each enabled skill's name, description, and absolute path to its SKILL.md, plus a short "how to activate" instruction.
Skill bodies are not loaded at startup — the model reads SKILL.md on demand via the existing Read tool (progressive disclosure, matches Anthropic / Gemini / Codex behaviour).
Frontmatter validation matches the spec above (name charset + length, description length). Invalid skills are skipped with a warning log, never crash startup. Directory whose name doesn't match name frontmatter is rejected.
disabled_skills: [foo, bar] in config skips those skills by name.
An existing Anthropic / Gemini / Codex skill folder copied into .infer/skills/ works without modification (verified by test using a sample from github.com/anthropics/skills).
New infer skills list command shows discovered skills, scope (project/user), enabled state, and any validation errors. Mirrors the existing infer agents / infer mcp patterns.
Documentation added at docs/skills.md covering: format, locations, enabling, authoring tips, security note (skills can instruct the model to run code — only use trusted sources), and a portability note pointing at the three vendor docs.
Unit tests cover: frontmatter parsing (valid + each invalid case), project-overrides-user precedence, disabled-skills filter, system-prompt injection format, and the "no-op when disabled" path.
Out of scope (for this issue)
A dedicated activate_skill tool (Gemini-style). The model can use Read directly; revisit if we observe activation issues.
Skill marketplace / remote install. Skills are filesystem-only for v1.
Skill execution sandboxing beyond what the existing tool-approval system already provides.
Summary
Anthropic (Claude Code), OpenAI (Codex CLI / ChatGPT) and Google (Gemini CLI) have all converged on the same "Agent Skills" contract over the last 6 months. Skills are now a de-facto standard: a folder containing a
SKILL.mdwith YAML frontmatter that the agent loads as metadata at startup and reads in full only when relevant.The CLI should adopt the same on-disk format so users can drop an existing skill folder authored for Claude / Codex / Gemini into
.infer/skills/and have it just work — that is the "seamless transition" goal.Prior art (must stay compatible with)
~/.claude/skills/<name>/.claude/skills/<name>/SKILL.mdname,description~/.gemini/skills/or~/.agents/skills/.gemini/skills/or.agents/skills/SKILL.mdname,description~/.codex/skills/<name>/SKILL.mdname,descriptionReferences:
Convergent contract (shared by all three)
scripts/,references/,assets/.SKILL.md(uppercase, exact name).nameanddescriptionbetween---delimiters at the very top of the file.name+descriptiongo into the system prompt at startup; the body is read lazily when the model decides to activate the skill.~/.<vendor>/skills/) and project-local (.<vendor>/skills/).Design
Locations (mirroring the convention):
.infer/skills/<skill-name>/SKILL.md~/.infer/skills/<skill-name>/SKILL.mdname.SKILL.md format (identical to Anthropic / Gemini / Codex):
Frontmatter validation (match Anthropic's spec to maximise portability):
name: required, ≤64 chars, lowercase letters + digits + hyphens only, must equal the directory name, must not containinfer/claude/anthropic/gemini/openai.description: required, non-empty, ≤1024 chars.disabled:flag).Skill directory contents (all optional except
SKILL.md):Progressive disclosure (the whole point of the format — must be implemented this way, otherwise we burn context):
name,description, and absolute path. Body ofSKILL.mdis not loaded.SKILL.md(and any referenced files) using the existingReadtool. No new tool needed —Readalready covers it.<path>/SKILL.mdfirst, then follow its instructions").Configuration (do not introduce
.infer/skills/config.yaml— that diverges from every other CLI). Instead extend the existing config layout:Env override:
INFER_AGENT_SKILLS_ENABLED=true.When
enabled: false, the scan is skipped entirely — zero token cost, no system-prompt block injected.Acceptance Criteria
.infer/skills/<name>/SKILL.md(project) and~/.infer/skills/<name>/SKILL.md(user-global). Project wins on name collision.infer initcreates an empty.infer/skills/directory and an example.infer/skills/example/SKILL.md(commented "delete me") so the format is discoverable.agent.skills.enabledis added toconfig.yamldefaults asfalse. Skill loading is a no-op when disabled.name,description, and absolute path to itsSKILL.md, plus a short "how to activate" instruction.SKILL.mdon demand via the existingReadtool (progressive disclosure, matches Anthropic / Gemini / Codex behaviour).namecharset + length,descriptionlength). Invalid skills are skipped with a warning log, never crash startup. Directory whose name doesn't matchnamefrontmatter is rejected.disabled_skills: [foo, bar]in config skips those skills by name..infer/skills/works without modification (verified by test using a sample fromgithub.com/anthropics/skills).infer skills listcommand shows discovered skills, scope (project/user), enabled state, and any validation errors. Mirrors the existinginfer agents/infer mcppatterns.docs/skills.mdcovering: format, locations, enabling, authoring tips, security note (skills can instruct the model to run code — only use trusted sources), and a portability note pointing at the three vendor docs.Out of scope (for this issue)
activate_skilltool (Gemini-style). The model can useReaddirectly; revisit if we observe activation issues.