Mobile harness does not register project skills from .claude/skills/ as slash commands
Summary
On the Claude Code mobile app (iOS), project-level skills under .claude/skills/*/SKILL.md are present on disk and readable by the model via context, but are not registered as user-invocable slash commands — AND the Skill tool dispatched programmatically by the agent cannot resolve them either. The desktop CLI registers both paths correctly.
Reproduction
- Mobile session on a project whose
.claude/skills/contains N custom skills (e.g.,/skill-a,/skill-b,/skill-c) - In session, type
/skill-a - Agent responds conversationally instead of invoking the skill via the Skill tool
- Ask agent: "what slash commands are available?" — only ~12 built-ins appear (
/update-config,/simplify,/loop,/claude-api,/session-start-hook,/init,/statusline,/review,/security-review,/insights,/team-onboarding,/keybindings-help) - Ask agent to
ls .claude/skills/— N custom skills present on disk - Agent attempts
Skill("skill-a")programmatically — returnsUnknown skill: skill-a
Expected
Project skills should be registered and invocable via both paths (user /slash typing AND the agent's Skill tool) on mobile, matching desktop behaviour.
Impact — two axes
Axis 1: user UX
Operators cannot invoke custom skills via slash commands on mobile. They must describe them in natural language (e.g., "run the analyze skill"), relying on the agent to Read and follow the SKILL.md directly.
Axis 2: agent autonomous / chained execution
This is the bigger impact. Any autonomous / multi-skill workflow that chains through skill invocations (e.g., /analyze → /plan → /code → /test → /stage, or whatever SDLC phases a given project defines) fails on mobile because every chained Skill("<name>") call returns Unknown skill.
Workaround possible via a project-level rule: instruct the agent on mobile to invoke custom skills by Read(".claude/skills/<name>/SKILL.md") then execute the protocol inline. This works for behavioral equivalence, BUT:
Token-cost asymmetry: each invocation now lands the full SKILL.md content in conversation context (vs. a short tool call + result). For a 20-skill autonomous chain:
| Path | Tokens for skill machinery |
|---|---|
| Tool dispatch (desktop) | ~15-30k |
| Read + interpret (mobile workaround) | ~60-100k |
On mobile — where sessions already have tighter effective context budgets and compaction is more brittle than desktop — this hits the compaction threshold 2-3 skills sooner than desktop. Autonomous chains still run, just more compactions, more re-reading of survival context, more turn budget consumed.
Context
Projects distribute skills under .claude/skills/ using the documented directory layout. Desktop Claude Code registers these at session start; mobile apparently does not. The substrate files themselves land correctly (rules, agents, custom skill files all on disk and readable by model context via additionalDirectories inheritance); it's specifically the mobile harness's slash-command / Skill-tool registry step that doesn't pick up .claude/skills/ entries.
Environment
- Mobile: claude.ai/code iOS app, tested 2026-04-15
- Skills:
.claude/skills/*/SKILL.mdwith standard frontmatter (name, description, etc.) - Readable from model context: ✅ (the
additionalDirectories/CLAUDE.mdinheritance path DOES surface them) - Resolvable by Skill tool: ❌
Desired behavior
Mobile harness should scan .claude/skills/*/SKILL.md at session start (ideally post-SessionStart-hook) and register each discovered skill in both the user slash-command UI AND the Skill tool's resolvable set, matching desktop CLI behavior.
Related
- Desktop CLI handles this correctly — both
.claude/skills/andadditionalDirectoriesskills are registered - Model can still follow skill content via
Read(SKILL.md)+ inline execution if instructed via a project-level rule, at the token cost described above
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗