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
Kit's current implementation (internal/skills/, pkg/kit/skills.go, cmd/extension_context.go, internal/ui/model.go) is substantially aligned with the spec — discovery layout, <available_skills> catalog, behavioral preamble, /skill:<name> activation, runtime mutation SDK, and XDG-aware user-level scanning are all in place. The gaps below fall into three buckets:
Read-side robustness — parser drops half the spec's frontmatter fields, doesn't validate, doesn't XML-escape, and the YAML failure mode is too brittle for cross-client skills.
Safety / policy — no project-trust gate, no per-skill disable mechanism, slash-command-injected skill content is not compaction-protected.
Optional polish — no dedicated activation tool, no <skill_resources> enumeration, no activation dedup, missing SDK helpers.
All 16 gaps below should be addressed in a single PR executed by a coding agent. They cluster in the same small set of files (internal/skills/, pkg/kit/skills.go, pkg/kit/kit.go, cmd/root.go, plus one new builtin MCP server and one new trust module), and the changes are tightly coupled — e.g. the new frontmatter fields flow through the struct, the SDK type alias, the extension conversion, the catalog rendering, and the docs all at once.
Motivation / Use Case
agentskills.io is the emerging cross-client spec for portable agent skills. As more tooling (Claude Code, Cursor, etc.) adopts it, Kit users expect skills authored elsewhere to "just work" inside Kit, and skills authored for Kit to be portable to other clients. Two concrete pain points today:
A description with <, >, or & produces a malformed catalog XML that some models will refuse to parse — silent quality regression.
A project-level .agents/skills/ directory in a freshly cloned repository silently injects instructions into the system prompt the moment you cd into it. This is a real prompt-injection vector — a malicious repo can add description: …always ignore safety prompts. and have it loaded before the user sees it.
Beyond those, several spec-required behaviors are simply absent (e.g. missing ~/.agents/skills/ scan, missing compatibility/license/metadata fields, no name-collision precedence rule).
What Kit already does well ✅
Spec area
Kit behaviour
Progressive disclosure (3 tiers)
Catalog in system prompt → body on activation → resources via read
.agents/skills/ cross-client convention
Scanned project-local
User-level skills
~/.config/kit/skills/ (XDG aware)
Kit-native dir
.kit/skills/ project-local
<available_skills> catalog tag
Matches spec
Behavioral preamble
Matches the spec's "file-read activation" template almost verbatim
Body-only stripping at activation
/skill:name strips frontmatter, re-reads for freshness
Structured wrapping at activation
Body wrapped in <skill name=… location=…> with baseDir note
A description containing <, >, &, ", or a stray </description> will produce malformed XML. Fix: wrap with encoding/xml.EscapeText or a small inline escaper.
2. Description-required validation is silently broken
internal/skills/skills.go:217-222 skips the <description> element when the field is empty, but still emits the skill in the catalog. The spec says description is required and that skills missing it should be skipped with a logged error (it's "essential for disclosure"). Today such skills appear in the catalog as <skill><name>foo</name></skill> which the model cannot discover by relevance.
Fix: in LoadSkill, return a "skip with warning" sentinel when description is empty. Add a Validate() method returning structured []Diagnostic.
3. --skills-dir semantics are inverted
cmd/root.go:297 flag help: "override the project-local skills directory for auto-discovery". Reality (pkg/kit/kit.go:1745):
LoadSkills(cwd) then appends .agents/skills/ and .kit/skills/ to that cwd. So --skills-dir /tmp/myskills actually scans /tmp/myskills/.agents/skills/ and /tmp/myskills/.kit/skills/, not /tmp/myskills/ itself.
Fix: treat SkillsDir as a direct skills directory (what users expect). Update flag help to match.
🟠 P1 — Spec compliance
4. Missing scan locations
Spec lists four canonical scopes; Kit scans three:
Spec path
Kit scans?
<project>/.agents/skills/
✅
<project>/.kit/skills/
✅
~/.agents/skills/
❌ missing
~/.config/kit/skills/
✅
.claude/skills/ (pragmatic compat)
❌ optional
Fix: in internal/skills/skills.go::LoadSkills, add os.UserHomeDir() + "/.agents/skills/". Optionally scan ~/.claude/skills/ + <cwd>/.claude/skills/ behind a flag for Claude Code compat.
5. Name-collision precedence
Spec: "project-level skills override user-level skills … log a warning when a collision occurs."internal/skills/skills.go:173-180 dedupes by Path only, so two skills named code-review in ~/.config/kit/skills/ and .kit/skills/ both end up in the catalog with duplicate <name> entries.
Fix: dedupe by Name with explicit precedence (project > user) and log.Warn when shadowing occurs.
6. Missing spec frontmatter fields
internal/skills/skills.go::Skill (lines 25-39) only carries Name, Description, Tags, When. The spec defines:
Field
Required
In Kit struct?
name
yes
✅
description
yes
✅
license
no
❌
compatibility
no
❌ (useful — model can adapt execution)
metadata
no
❌
allowed-tools
no (experimental)
❌
tags
— (Kit extension)
✅
when
— (Kit extension)
✅
Fix: add License string, Compatibility string, Metadata map[string]string, AllowedTools string fields with YAML tags. Document tags/when as Kit extensions in godoc. Update pkg/kit/skills.go::convertSkill and internal/extensions Skill type accordingly.
7. Compaction protection for /skill: content
Spec Step 5: "exempt skill content from pruning." When a user runs /skill:foo (see pkg/kit/kit.go:1679-1731expandSkillCommand), the wrapped <skill>...</skill> body becomes a regular user message and is eligible for summarization in internal/compaction/. Skills loaded via the system-prompt catalog are safe (system prompt is replayed), but explicitly-activated skills can silently disappear mid-session, degrading quality with no visible error.
Fix: either (a) add a Protected bool flag on session entries that compaction skips, or (b) detect the <skill_content> / <skill> wrapper tag in compaction.FindCutPoint and preserve those messages.
8. Project-level trust gate
Spec: "Consider gating project-level skill loading on a trust check — only load them if the user has marked the project folder as trusted."
Currently any cloned repo with .agents/skills/ or .kit/skills/ silently injects instructions into the system prompt on cd. Real prompt-injection vector.
Fix: persist a trust allowlist at ~/.config/kit/trusted-projects.json. First time entering a repo with project-level skills, show a TUI prompt: "Load N skills from /path/to/repo?" with Trust / Skip / Trust+Always options.
🟡 P2 — Cross-client compatibility & polish
9. Malformed-YAML fallback
Spec calls out the common description: Use when: … (unquoted colon) failure mode common in Claude-authored skills. Kit's yaml.Unmarshal (internal/skills/skills.go:72) fails the whole skill load on such files.
Fix: on YAML error, regex-detect ^(\w+):\s+(.+:.+)$ scalar lines, wrap the value in quotes, retry once.
Spec: "Hide filtered skills entirely from the catalog … reasons: user disabled, permission denial, disable-model-invocation flag." Kit has no UI/CLI/config for disabling individual skills and doesn't honor any disable flag.
Fix:
Honor disable-model-invocation: true in frontmatter — exclude from catalog, still allow via /skill: slash command.
Add --skill-disable foo flag and skill-disable: [foo] config key.
When /skill:foo runs, expandSkillCommand writes a baseDir hint but does not list scripts/*, references/*, assets/*. Spec recommends surfacing these without reading them, so the model knows what's available.
Fix: after loading body, walk one level into scripts/, references/, assets/, render:
internal/skills/skills.go:223 emits <location>file:///...</location> but spec examples and tool inputs use bare paths. Most models tolerate file:// but Kit's read tool / MCP fs server expect plain paths.
Fix: drop the file:// prefix.
🟢 P3 — Optional, high-ROI enhancements
13. Dedicated activate_skill MCP tool
Spec Step 4 lists this as the preferred pattern when you want bundled-resource enumeration, strict enum-constrained name (prevents hallucination), centralized analytics + dedup, and per-skill permission prompts. Kit relies entirely on the generic read tool today.
Fix: add a builtin MCP tool kit_activate_skill(name: enum[...]) registered only when ≥1 skill is loaded. Re-reads the SKILL.md (freshness), strips frontmatter, enumerates resources, wraps in <skill_content name="…">…</skill_content>, records an event for dedup.
Spec: "Consider tracking which skills have been activated in the current session … skip re-injection." Per-session activatedSkills map[string]bool; on duplicate call return: "Skill 'foo' already loaded earlier in this session."
15. SDK ergonomics
Gap
Recommendation
Skill lacks BaseDir() helper
func (s *Skill) BaseDir() string { return filepath.Dir(s.Path) }
Skill lacks Resources() listing
func (s *Skill) Resources() []string walking one level into scripts/, references/, assets/
internal/config/config.go:498-501 generated .kit.yml template doesn't document the new spec frontmatter fields (compatibility, license, metadata, allowed-tools). Add a brief section alongside #6.
Proposed Implementation
Single PR, executed end-to-end by a coding agent. The work clusters in a small, tightly-coupled blast radius — bundling it into one sweep avoids merge churn (e.g. each frontmatter field change cascades through five files) and lets the agent reason about cross-cutting invariants (compaction-protection tag must match activation-time wrapper must match catalog-time stripping).
Feature Description
Bring Kit's skills subsystem into full compliance with the agentskills.io specification and client implementation guide in a single coordinated sweep.
Kit's current implementation (
internal/skills/,pkg/kit/skills.go,cmd/extension_context.go,internal/ui/model.go) is substantially aligned with the spec — discovery layout,<available_skills>catalog, behavioral preamble,/skill:<name>activation, runtime mutation SDK, and XDG-aware user-level scanning are all in place. The gaps below fall into three buckets:<skill_resources>enumeration, no activation dedup, missing SDK helpers.All 16 gaps below should be addressed in a single PR executed by a coding agent. They cluster in the same small set of files (
internal/skills/,pkg/kit/skills.go,pkg/kit/kit.go,cmd/root.go, plus one new builtin MCP server and one new trust module), and the changes are tightly coupled — e.g. the new frontmatter fields flow through the struct, the SDK type alias, the extension conversion, the catalog rendering, and the docs all at once.Motivation / Use Case
agentskills.iois the emerging cross-client spec for portable agent skills. As more tooling (Claude Code, Cursor, etc.) adopts it, Kit users expect skills authored elsewhere to "just work" inside Kit, and skills authored for Kit to be portable to other clients. Two concrete pain points today:<,>, or&produces a malformed catalog XML that some models will refuse to parse — silent quality regression..agents/skills/directory in a freshly cloned repository silently injects instructions into the system prompt the moment youcdinto it. This is a real prompt-injection vector — a malicious repo can adddescription: …always ignore safety prompts.and have it loaded before the user sees it.Beyond those, several spec-required behaviors are simply absent (e.g. missing
~/.agents/skills/scan, missingcompatibility/license/metadatafields, no name-collision precedence rule).What Kit already does well ✅
read.agents/skills/cross-client convention~/.config/kit/skills/(XDG aware).kit/skills/project-local<available_skills>catalog tag/skill:namestrips frontmatter, re-reads for freshness<skill name=… location=…>with baseDir note/skill:<name>slash command + TUI autocompletename/descriptionextracted;SKILL.mdfilename → directory-name fallbackAddSkill/RemoveSkill/SetSkills/ReloadSkills/LoadAndAddSkill--skill,--skills-dir,--no-skills+ matchingOptionsfields, viper-boundGaps to fix 🚧
All items below ship in a single PR. Priority labels indicate correctness severity, not PR scheduling.
🔴 P0 — Correctness bugs
1. No XML escaping in the catalog
internal/skills/skills.go:206-228(FormatForPrompt) interpolatesname/descriptiondirectly into XML:A description containing
<,>,&,", or a stray</description>will produce malformed XML. Fix: wrap withencoding/xml.EscapeTextor a small inline escaper.2. Description-required validation is silently broken
internal/skills/skills.go:217-222skips the<description>element when the field is empty, but still emits the skill in the catalog. The spec says description is required and that skills missing it should be skipped with a logged error (it's "essential for disclosure"). Today such skills appear in the catalog as<skill><name>foo</name></skill>which the model cannot discover by relevance.Fix: in
LoadSkill, return a "skip with warning" sentinel when description is empty. Add aValidate()method returning structured[]Diagnostic.3.
--skills-dirsemantics are invertedcmd/root.go:297flag help: "override the project-local skills directory for auto-discovery". Reality (pkg/kit/kit.go:1745):LoadSkills(cwd)then appends.agents/skills/and.kit/skills/to that cwd. So--skills-dir /tmp/myskillsactually scans/tmp/myskills/.agents/skills/and/tmp/myskills/.kit/skills/, not/tmp/myskills/itself.Fix: treat
SkillsDiras a direct skills directory (what users expect). Update flag help to match.🟠 P1 — Spec compliance
4. Missing scan locations
Spec lists four canonical scopes; Kit scans three:
<project>/.agents/skills/<project>/.kit/skills/~/.agents/skills/~/.config/kit/skills/.claude/skills/(pragmatic compat)Fix: in
internal/skills/skills.go::LoadSkills, addos.UserHomeDir() + "/.agents/skills/". Optionally scan~/.claude/skills/+<cwd>/.claude/skills/behind a flag for Claude Code compat.5. Name-collision precedence
Spec: "project-level skills override user-level skills … log a warning when a collision occurs."
internal/skills/skills.go:173-180dedupes byPathonly, so two skills namedcode-reviewin~/.config/kit/skills/and.kit/skills/both end up in the catalog with duplicate<name>entries.Fix: dedupe by
Namewith explicit precedence (project > user) andlog.Warnwhen shadowing occurs.6. Missing spec frontmatter fields
internal/skills/skills.go::Skill(lines 25-39) only carriesName,Description,Tags,When. The spec defines:namedescriptionlicensecompatibilitymetadataallowed-toolstagswhenFix: add
License string,Compatibility string,Metadata map[string]string,AllowedTools stringfields with YAML tags. Documenttags/whenas Kit extensions in godoc. Updatepkg/kit/skills.go::convertSkillandinternal/extensionsSkill type accordingly.7. Compaction protection for
/skill:contentSpec Step 5: "exempt skill content from pruning." When a user runs
/skill:foo(seepkg/kit/kit.go:1679-1731expandSkillCommand), the wrapped<skill>...</skill>body becomes a regular user message and is eligible for summarization ininternal/compaction/. Skills loaded via the system-prompt catalog are safe (system prompt is replayed), but explicitly-activated skills can silently disappear mid-session, degrading quality with no visible error.Fix: either (a) add a
Protected boolflag on session entries that compaction skips, or (b) detect the<skill_content>/<skill>wrapper tag incompaction.FindCutPointand preserve those messages.8. Project-level trust gate
Spec: "Consider gating project-level skill loading on a trust check — only load them if the user has marked the project folder as trusted."
Currently any cloned repo with
.agents/skills/or.kit/skills/silently injects instructions into the system prompt oncd. Real prompt-injection vector.Fix: persist a trust allowlist at
~/.config/kit/trusted-projects.json. First time entering a repo with project-level skills, show a TUI prompt: "Load N skills from/path/to/repo?" with Trust / Skip / Trust+Always options.🟡 P2 — Cross-client compatibility & polish
9. Malformed-YAML fallback
Spec calls out the common
description: Use when: …(unquoted colon) failure mode common in Claude-authored skills. Kit'syaml.Unmarshal(internal/skills/skills.go:72) fails the whole skill load on such files.Fix: on YAML error, regex-detect
^(\w+):\s+(.+:.+)$scalar lines, wrap the value in quotes, retry once.10. Per-skill disable +
disable-model-invocationhonoringSpec: "Hide filtered skills entirely from the catalog … reasons: user disabled, permission denial,
disable-model-invocationflag." Kit has no UI/CLI/config for disabling individual skills and doesn't honor any disable flag.Fix:
disable-model-invocation: truein frontmatter — exclude from catalog, still allow via/skill:slash command.--skill-disable fooflag andskill-disable: [foo]config key.(*Kit).DisableSkill(name)/EnableSkill(name)SDK methods.11.
<skill_resources>enumeration on activationWhen
/skill:fooruns,expandSkillCommandwrites a baseDir hint but does not listscripts/*,references/*,assets/*. Spec recommends surfacing these without reading them, so the model knows what's available.Fix: after loading body, walk one level into
scripts/,references/,assets/, render:Cap at ~50 entries with a
(truncated)note.12. Drop
file://prefix on<location>internal/skills/skills.go:223emits<location>file:///...</location>but spec examples and tool inputs use bare paths. Most models toleratefile://but Kit'sreadtool / MCPfsserver expect plain paths.Fix: drop the
file://prefix.🟢 P3 — Optional, high-ROI enhancements
13. Dedicated
activate_skillMCP toolSpec Step 4 lists this as the preferred pattern when you want bundled-resource enumeration, strict enum-constrained
name(prevents hallucination), centralized analytics + dedup, and per-skill permission prompts. Kit relies entirely on the genericreadtool today.Fix: add a builtin MCP tool
kit_activate_skill(name: enum[...])registered only when ≥1 skill is loaded. Re-reads the SKILL.md (freshness), strips frontmatter, enumerates resources, wraps in<skill_content name="…">…</skill_content>, records an event for dedup.14. Activation deduplication (depends on #13)
Spec: "Consider tracking which skills have been activated in the current session … skip re-injection." Per-session
activatedSkills map[string]bool; on duplicate call return: "Skill 'foo' already loaded earlier in this session."15. SDK ergonomics
SkilllacksBaseDir()helperfunc (s *Skill) BaseDir() string { return filepath.Dir(s.Path) }SkilllacksResources()listingfunc (s *Skill) Resources() []stringwalking one level intoscripts/,references/,assets/Validate()onSkill[]Diagnosticpkg/kit/skills.go::convertSkilldrops new fieldsinternal/extensions/api.go:780comment lists scan paths that disagree with codeinternal/skills/skills.gopackage godoc lists only 2 paths but scans 316. Documentation
internal/config/config.go:498-501generated.kit.ymltemplate doesn't document the new spec frontmatter fields (compatibility,license,metadata,allowed-tools). Add a brief section alongside #6.Proposed Implementation
Single PR, executed end-to-end by a coding agent. The work clusters in a small, tightly-coupled blast radius — bundling it into one sweep avoids merge churn (e.g. each frontmatter field change cascades through five files) and lets the agent reason about cross-cutting invariants (compaction-protection tag must match activation-time wrapper must match catalog-time stripping).
Files touched
internal/skills/skills.go,internal/skills/skills_test.go~/.agents/skills/, dropfile://, helpersinternal/skills/prompt_builder.go(small)pkg/kit/skills.go,pkg/kit/kit.go,pkg/kit/kit_test.goconvertSkillupdate,DisableSkill/EnableSkill,--skills-dirsemantics, expandSkillCommand resource enumerationinternal/extensions/api.go,internal/extensions/symbols.goSkillfields exposed to extensionsinternal/mcpserver/skills/(new package) + registration incmd/root.gokit_activate_skillbuiltin MCP tool with enum-constrainedname, dedup, resource listinginternal/compaction/cutpoint.go,internal/session/tree_manager.goProtectedflag or wrapper-tag detectioninternal/trust/(new package), TUI hook ininternal/ui/model.goorcmd/root.gocmd/root.go--skill-disableflag, fix--skills-dirhelp textinternal/config/config.go(generated.kit.ymltemplate)internal/skills/*_test.go,pkg/kit/*_test.go, new tests for trust + MCP toolSuggested execution order within the PR
Skillstruct (feat: highlight @file tokens in input with accent color #6), addValidate()(fix: ToolRenderConfig BorderColor and Background fields are ignored #2), XML escape helper (Add support for overriding model registry and capabilities #1), stripfile://(TUI feels visually noisy: user label, large prompt placeholder, and input help take too much space #12).~/.agents/skills/scan (OAuth fails for remote MCP servers without dynamic client registration (e.g. GitHub) — no way to provide ClientID #4), name-collision precedence (feat: open external $EDITOR for composing long prompts via ctrl+x e chord #5), YAML fallback (OpenAI login does not become the default provider, and starting with --model openai/... fails until model is reselected in /model #9).--skills-dir(AddMCPServer() creates MCPToolManager without inheriting OAuth AuthHandler and TokenStoreFactory #3), add disable mechanism (Shift+Enter does not insert a newline even though the UI hint says it should #10), SDK helpers (Assistant message was temporarily truncated until I sent my next reply #15).<skill_resources>enumeration (/thinking incorrectly reports that GPT-5.4 does not support thinking/reasoning #11), newkit_activate_skillMCP tool (Ctrl+C exits the app instead of clearing the current input #13), dedup tracking (Text selection in the TUI is awkward and makes copying partial output frustrating #14)..kit.ymltemplate (feat: Mirror Fantasy's streaming callbacks as Kit EventBus events (ToolCallStart, ToolCallDelta, Source, etc.) #16),internal/extensions/symbols.gosync.go test -race ./...after each step; final pass withgo vet ./...andgo fmt ./....Acceptance criteria
go test -race ./...passesgo vet ./...cleanlicense/compatibility/unquoted-colon description) loads correctly in Kit<in its description renders valid catalog XMLdescriptionis skipped with a logged warning, not silently dropped from disclosure.agents/skills/prompts for trust before loading--skills-dir /tmp/xscans/tmp/xdirectlyReferences