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
Observed: the Codex engine reaches for purchased/equipped skills well, but the Claude engine usually ignores them — even when a relevant skill (e.g. docx, pdf, pptx) is installed and the task obviously fits.
Disk placement is symmetric and correct — buyAndEquip writes the SKILL.md into both runtimes' skill dirs (installBoughtAll → installBought("claude") + installBought("codex"), skill-market/ingest/index.ts:61‑64). So this is not an install bug. The gap is entirely in how each engine is made aware of the skills at session time.
How skills surface to each engine
flowchart TD
Buy["buyAndEquip(skillId)"] --> A["installBought claude<br/>~/.claude/skills/<slug>/SKILL.md"]
Buy --> B["installBought codex<br/>~/.codex/skills/<slug>/SKILL.md"]
A --> C["Claude awareness"]
B --> D["Codex awareness"]
C --> C1["MEMORY.md managed line:<br/>TITLES ONLY<br/>'…installed and ready: docx, pdf, pptx.'"]
C --> C2["SDK native discovery of ~/.claude/skills<br/>(settingSources omitted)"]
D --> D1["AGENTS.md managed line (titles)"]
D --> D2["NATIVE always-on '## Skills' list<br/>name + DESCRIPTION + path, every turn"]
C1 -.weak signal.-> E["Claude rarely invokes the skill"]
D2 == strong signal ==> F["Codex invokes the skill"]
Loading
Codex (works)
~/.codex/skills/<slug>/SKILL.md is auto-discovered by Codex and injected into an always-on ## Skills list with name + description + path every turn (plans/skill-ingestion.md:61‑62, §3). The model sees what each skill does and when to use it on every turn → it reaches for them.
Claude (ignores them)
Claude's awareness today comes from only two things:
A managed MEMORY.md one-liner that lists skill titles only — no descriptions. skillsSection.ts:44‑48 renders "The following skills are installed and ready — use one when it fits the task: <names>." Bare titles like docx, pdf, pptx are a weak trigger: the model can't tell what each does or when it's relevant.
SDK native skill discovery of ~/.claude/skills, relying on settingSources being omitted so the SDK loads the user dir (spawn.ts:327‑330).
The Claude system prompt is kept vanilla ({ type: "preset", preset: "claude_code" }, spawn.ts:317) with nothing appended.
Root-cause candidates (the actionable part)
The code diverges from the settled design in plans/skill-ingestion.md §2–§3. The design specifies, for Claude:
enable skills via skills: ['verify','skill-shopping', …] in query() options, and
settingSources: ['project'], and
append the verify directive to the system prompt (preset:'claude_code', append: <verify-instruction>).
None of these are present in the actual spawn.ts claude engine options (lines 297‑331): there is no skills: array, no settingSources, no append. So Claude is left to implicitly discover skills, with only a titles-only memory line as the nudge.
Candidate causes, roughly in order of likelihood:
No descriptions in Claude's awareness signal. The memory line lists titles only; Codex gets name+description. This alone plausibly explains the behavior — without descriptions the model doesn't connect "I'm editing a .docx" → "use the docx skill."
SDK native discovery may not actually be surfacing the skills as Skill tools the way the comment assumes (no explicit skills:[…]/settingSources → discovery may be partial or off). Needs verification with a logged session: does the Claude turn actually receive the equipped skills as available Skill tools?
Design/impl drift — the skills:[…] + settingSources:['project'] wiring from the design was never landed for the bought-skills path.
Confirm the MEMORY.md skills line is present and current at turn time.
Proposed fix directions
Enrich the awareness signal to match Codex: have skillsSection.ts render name + one-line description per skill (we already have description in the skill metadata / memory record), not just titles — so Claude gets the same "what/when" signal Codex's ## Skills list provides. This reuses the existing memory-splice setter (spliceMarkedBlock), just with a richer block.
And/or land the design's explicit wiring: pass skills: [<equipped names>] (+ settingSources as the design requires) into the Claude query() so equipped skills are first-class Skill tools, not just discovered.
Keep the system prompt vanilla (that decision was deliberate, spawn.ts:312‑316) — surface skills through memory/SDK options, not the prompt.
Summary
Observed: the Codex engine reaches for purchased/equipped skills well, but the Claude engine usually ignores them — even when a relevant skill (e.g.
docx,pdf,pptx) is installed and the task obviously fits.Disk placement is symmetric and correct —
buyAndEquipwrites the SKILL.md into both runtimes' skill dirs (installBoughtAll→installBought("claude")+installBought("codex"),skill-market/ingest/index.ts:61‑64). So this is not an install bug. The gap is entirely in how each engine is made aware of the skills at session time.How skills surface to each engine
flowchart TD Buy["buyAndEquip(skillId)"] --> A["installBought claude<br/>~/.claude/skills/<slug>/SKILL.md"] Buy --> B["installBought codex<br/>~/.codex/skills/<slug>/SKILL.md"] A --> C["Claude awareness"] B --> D["Codex awareness"] C --> C1["MEMORY.md managed line:<br/>TITLES ONLY<br/>'…installed and ready: docx, pdf, pptx.'"] C --> C2["SDK native discovery of ~/.claude/skills<br/>(settingSources omitted)"] D --> D1["AGENTS.md managed line (titles)"] D --> D2["NATIVE always-on '## Skills' list<br/>name + DESCRIPTION + path, every turn"] C1 -.weak signal.-> E["Claude rarely invokes the skill"] D2 == strong signal ==> F["Codex invokes the skill"]Codex (works)
~/.codex/skills/<slug>/SKILL.mdis auto-discovered by Codex and injected into an always-on## Skillslist with name + description + path every turn (plans/skill-ingestion.md:61‑62, §3). The model sees what each skill does and when to use it on every turn → it reaches for them.Claude (ignores them)
Claude's awareness today comes from only two things:
skillsSection.ts:44‑48renders"The following skills are installed and ready — use one when it fits the task: <names>."Bare titles likedocx, pdf, pptxare a weak trigger: the model can't tell what each does or when it's relevant.~/.claude/skills, relying onsettingSourcesbeing omitted so the SDK loads the user dir (spawn.ts:327‑330).The Claude system prompt is kept vanilla (
{ type: "preset", preset: "claude_code" },spawn.ts:317) with nothing appended.Root-cause candidates (the actionable part)
The code diverges from the settled design in
plans/skill-ingestion.md§2–§3. The design specifies, for Claude:skills: ['verify','skill-shopping', …]inquery()options, andsettingSources: ['project'], andpreset:'claude_code', append: <verify-instruction>).None of these are present in the actual
spawn.tsclaude engine options (lines 297‑331): there is noskills:array, nosettingSources, noappend. So Claude is left to implicitly discover skills, with only a titles-only memory line as the nudge.Candidate causes, roughly in order of likelihood:
docxskill."Skilltools the way the comment assumes (no explicitskills:[…]/settingSources→ discovery may be partial or off). Needs verification with a logged session: does the Claude turn actually receive the equipped skills as availableSkilltools?skills:[…]+settingSources:['project']wiring from the design was never landed for the bought-skills path.What to verify
docx(or any bought skill) equipped and confirm whether the SDK surfaces it as an availableSkilltool at all (i.e. is candidate feat: extend Wallet with on-chain signing (unblocks Track 2) #2 real, or does discovery work and it's purely a feat: Session Runtime MVP — claude/codex wrapper + wallet-encrypted sync + VSCode chat #1 signal-strength problem?).Proposed fix directions
skillsSection.tsrender name + one-line description per skill (we already havedescriptionin the skill metadata / memory record), not just titles — so Claude gets the same "what/when" signal Codex's## Skillslist provides. This reuses the existing memory-splice setter (spliceMarkedBlock), just with a richer block.skills: [<equipped names>](+settingSourcesas the design requires) into the Claudequery()so equipped skills are first-classSkilltools, not just discovered.spawn.ts:312‑316) — surface skills through memory/SDK options, not the prompt.Key references
packages/core/src/skill-market/ingest/index.ts:61‑64packages/core/src/memory/skillsSection.ts:44‑48skills:/settingSources/append)packages/core/src/runtime/spawn.ts:297‑331packages/core/src/runtime/spawn.ts:312‑317## Skillslist (name+description)plans/skill-ingestion.md:61‑62, §3plans/skill-ingestion.md§2–§3