Skip to content

duplicate skill name WARN on every workspace: symlink ~/.claude/skills → ~/.agents/skills is not inode-deduped; nested remotion-best-practices SKILL.md collides #46327

Closed as not planned

Description

@eshe-huli

Description

OpenCode 1.18.25 (Desktop, macOS) logs WARN duplicate skill name on every workspace boot, not once per process. Two distinct collisions:

  1. Same skill, two roots, often the same inode. ~/.claude/skills/<name> is a symlink to ~/.agents/skills/<name> (standard Claude + Codex layout). Discovery still treats them as two skills and warns. followSymlinks: true plus no realpath/inode check.

    Example from this machine (already a symlink):

    WARN duplicate skill name name=codex-security-scan
      existing=/Users/…/.claude/skills/codex-security-scan/SKILL.md
      duplicate=/Users/…/.agents/skills/codex-security-scan/SKILL.md
    
  2. Recursive glob inside a skill package. ~/.agents/skills/remotion-best-practices/{remotion-create,remotion-markup,…}/SKILL.md has the same frontmatter name as the sibling top-level ~/.agents/skills/remotion-create/SKILL.md. {skill,skills}/**/SKILL.md indexes both.

This is not the TUI-vs-Desktop which winner bug (#35153) and not only the non-deterministic last-writer (#32202). The user-visible failure here is a warning flood (once per open workspace) and a prompt-cache miss risk from unstable <location> bytes. Related closed: #29950.

OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 is an undocumented workaround for (1) only. It is env-only (not in opencode.json schema). It does not fix (2). There is no config key to skip Claude roots while keeping ~/.agents/skills.

Plugins

oh-my-openagent@latest (warnings are service=skill / OpenCode core, not the plugin)

OpenCode version

Desktop 1.18.25; CLI 1.18.10

Steps to reproduce

  1. Install the same skill in both Claude and Agents roots as a symlink:
    mkdir -p ~/.agents/skills/example
    echo $'---\nname: example\ndescription: demo\n---\n' > ~/.agents/skills/example/SKILL.md
    ln -s ~/.agents/skills/example ~/.claude/skills/example
    
  2. Also copy a nested package layout:
    mkdir -p ~/.agents/skills/pkg/example
    cp ~/.agents/skills/example/SKILL.md ~/.agents/skills/pkg/example/SKILL.md
    
  3. Start OpenCode Desktop (or opencode) from any project.
  4. Open more than one recent workspace.

Expected

  • Same inode / symlink pair: index once, no WARN.
  • Nested **/SKILL.md under another skill directory: do not register as a second skill of the same name, or warn once with a stable winner by documented precedence.
  • A opencode.json flag equivalent to OPENCODE_DISABLE_CLAUDE_CODE_SKILLS.

Actual

Operating System

macOS

Terminal

OpenCode Desktop

Activity

  1. eshe-huli commented on Aug 31, 2026

    @eshe-huli
    Author

    Workaround on this machine after filing:

    • OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 (LaunchAgent + ~/.zshenv)
    • Result: 0 ~/.claude/skills vs ~/.agents/skills WARNs on Desktop relaunch.

    Still remaining on 1.18.25 (this issue, not the Claude root):

    • ~/.agents/skills/remotion-* vs ~/.agents/skills/remotion-best-practices/remotion-* (recursive glob)
    • same name in ~/.agents/skills and ~/.config/opencode/skills (impeccable, beyond-the-object, pipeline-must-pass)
  2. eshe-huli commented on Aug 31, 2026

    @eshe-huli
    Author

    Local close on this machine (still want the core inode/glob fix):

    • Moved nested remotion-best-practices/{remotion-*,mediabunny} aside; parent already links to sibling ../remotion-create etc. Kept remotion-saas.
    • One copy of impeccable / beyond-the-object / pipeline-must-pass (in ~/.agents/skills). OpenCode copies removed so last-writer could not load the Codex-path impeccable into Desktop.
    • After Desktop relaunch: 0 duplicate skill name WARNs.
  3. chenhz01 commented on Sep 17, 2026

    @chenhz01

    We hit this same collision class in a ~490-skill library, and one reframing fixed both of your cases: treat skill identity as a (name, realpath, body) triple rather than the frontmatter name string.

    • realpath/inode resolution kills the symlink double-count exactly as you describe in (1) — index once per resolved inode, no WARN.
    • Comparing bodies separately catches (2)-style nested collisions, where the same name appears under a package dir with different content. That's a distinct failure mode from a true duplicate, and it deserves a distinct message: one says "same skill seen through two roots," the other says "same name, genuinely different skill — pick a winner by documented precedence."

    A cheap deterministic rule that maps onto your expected behavior: dedupe on resolved inode first, then warn once per distinct (name, body) pair per process with a stable precedence — which also fixes the prompt-cache instability, since the winner stops depending on discovery order.

    +1 on a config-file equivalent of OPENCODE_DISABLE_CLAUDE_CODE_SKILLS — env-only workarounds don't survive Desktop reinstalls, and "skip one root but keep the other" is a configuration decision, not an environment accident.

  4. thdxr commented on Oct 11, 2026

    @thdxr
    Member

    Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.

    — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions