Skip to content

skills: newly added skill directories are not discovered until service restart #52701

Open

Description

@zhzjm

Description

Adding a new skill directory under an already-watched skills root (e.g. ~/.config/opencode/skills/<name>/SKILL.md) while the service is running has no effect: no rescan is triggered and the skill never appears in GET /api/skill until the service is restarted. The watcher reacts to changes of already-tracked skill files, but not to newly added directories.

  • Directory creation triggers no rescan (no skills rescanned log entry, API output unchanged after 10s).
  • Modifying or removing an existing skill file does trigger a rescan, so the watcher is installed but does not react to directory additions.
  • A frontmatter name differing from the directory name is not the cause — a skill with mismatched name/directory loads correctly after restart.

Related issues: #34408, #27956, #36405 report the same symptom but were auto-closed as not_planned by the stale bot (and #36405 predates 2.0). This is still reproducible on 2.0.21, which includes the #41622 refactor that moved skill watching into ConfigSkillPlugin and was supposed to rescan "on relevant filesystem changes". #42478 (open) covers a project .agents directory created after startup; this report is about a skill subdirectory added inside an already-watched skills root. #37426 (open) requests refresh-without-restart as a feature.

Plugins

opencode-dcp, @mohak34/opencode-notifier (opencode.json), plus one local TUI plugin auto-discovered from ~/.config/opencode/plugins/

OpenCode version

2.0.21

Steps to reproduce

  1. With the service running, confirm opencode api get /api/skill returns only built-in skills.

  2. Create a new skill directory with a valid SKILL.md (frontmatter name: probe-skill):

    ~/.config/opencode/skills/probe-skill/SKILL.md
    
  3. Wait ~10 seconds, re-run opencode api get /api/skill → the new skill does not appear, and no skills rescanned entry is logged.

  4. Run opencode service restart, re-query → the skill appears immediately.

Screenshot and/or share link

No response

Operating System

Windows 11 Pro, build 10.0.26200 (win32 x64)

Terminal

PowerShell 7 (pwsh) — verified via CLI/API, no terminal dependency

Activity

  1. added
    needs:complianceThis means the issue will auto-close after 2 hours.
    and removed
    needs:complianceThis means the issue will auto-close after 2 hours.
    on Oct 2, 2026
  2. github-actions commented on Oct 2, 2026

    @github-actions
    Contributor

    Thanks for updating the issue with the Bug Report description, reproduction steps, and system details!

  3. r266-tech commented on Oct 2, 2026

    @r266-tech
    Contributor

    I exercised current v2 ConfigSkillPlugin → real Watcher → Skill.Service on macOS, with listener readiness awaited and no injected watcher events. Immediate directory + SKILL.md creation, an empty directory followed later by SKILL.md, existing-file edits, and removal all refreshed the registry without a restart (1 test, 8 assertions). A frontmatter name different from the directory also loaded. Both source blobs match current v2.

    This does not reproduce the Windows failure or test the HTTP handler. @zhzjm, does the affected service log “watcher started” with backend “windows” for that exact skills root, or “failed to subscribe” / “watcher backend not supported”? That would distinguish native event delivery/acquisition from parsing. The existing config tests manually emit create events and cannot establish that boundary. AI-assisted investigation.

  4. zhzjm commented on Oct 3, 2026

    @zhzjm
    Author

    Answering your question first, with logs from the affected service (2.0.21, Windows 11 / win32):

    2026-10-02T13:24:18.995Z INFO message="watcher started" path="C:\\Users\\Ennis Zhu\\.config\\opencode\\skills" type=directory backend=windows ignores=0 role=server
    2026-10-02T15:53:02.116Z INFO message="watcher started" path="C:\\Users\\Ennis Zhu\\.claude\\skills" type=directory backend=windows ignores=0 role=server
    

    No failed to subscribe / watcher backend not supported anywhere in the logs — the watcher starts fine with backend windows. So parsing/subscription acquisition is not the issue; it points to native event delivery/consumption for directory creations.

    Update: no longer reproducible on 2.0.22. I re-ran the exact scenario after upgrading (create <skills>/win-repro-20261003/SKILL.md while the service is running):

    09:16:46.644 watcher subscribe  path="...\\.config\\opencode\\skills" type=directory
    09:16:46.652 watcher started    path="...\\.config\\opencode\\skills" type=directory backend=windows
    09:16:46.662 skills rescanned   file="...\\win-repro-20261003\\SKILL.md" sources=["directory:..."]
    09:16:46.671 skills rescanned   file="...\\win-repro-20261003\\SKILL.md" sources=["directory:..."]
    

    The rescan fires twice within <1s of creation (source directory:...), and GET /api/skill immediately contains the new skill (before: absent, 12s later: present). Note the watcher is also re-subscribed/started on the creation event, which is the behavior that seemed missing on 2.0.21.

    The original 2.0.21 observations stand: creating a new skill directory produced no rescan at all (10s wait, no skills rescanned entry, API unchanged), while editing/removing an existing skill file did trigger a rescan, and the skill only appeared after opencode service restart.

    Since your macOS test on current v2 matches what I now see on Windows 2.0.22, the symptom looks specific to the 2.0.21 Windows path. If you want to trace it, the interesting delta is whatever changed between 2.0.21...2.0.22 in ConfigSkillPlugin's reaction to directory creations (the re-subscribe-on-create behavior). Otherwise feel free to close this as fixed in 2.0.22.

  5. crpdestroy-crypto commented on Oct 18, 2026

    @crpdestroy-crypto

    Additional data point on v2.0.28 (Android/Termux, aarch64): a new directory added to a global compatibility skills root is not discovered while the service is running, and the failure is visible to the model, not only via GET /api/skill.

    Two things worth noting on top of the report above:

    1. The source is the global compatibility root ~/.agents/skills (not ~/.config/opencode/skills). The very same directory is picked up after opencode reload, so discovery itself works — it is only the rescan trigger that is missing.
    2. opencode reload is sufficient; opencode service restart is not required.

    Reproduction (v2.0.28)

    1. Service running, session open (session cwd is a project directory; the skill lives in $HOME/.agents/skills/).

    2. Create ~/.agents/skills/zz-repro/SKILL.md with minimal valid frontmatter — name: zz-repro and description: ... only — to rule out a frontmatter parse problem.

    3. Load it with the skill tool by its exact ID:

      {"error":{"type":"tool.execution","message":"Unable to load skill zz-repro"}}

      zz-repro is also absent from the model's available-skills list, and opencode api skill.list omits it.

    4. Run opencode reload → prints Configuration reloaded.

    5. The skill is now announced to the model and loads successfully:

      <skill_content name="zz-repro">
      # Skill: zz-repro
      Probe body.
      Base directory for this skill: /data/data/com.termux/files/home/.agents/skills/zz-repro
      

    Notes

    • Reproduced twice. The first failing skill was a real one (agent-browser, frontmatter with extra allowed-tools); the second was the minimal control skill above, which failed identically.
    • A skill installed earlier into the project's .agents/skills directory did appear live in the same session. That lines up with cli: service skill/compatibility watcher self-loops on .agents/skills, ~37% idle CPU #54114 / skills: project .agents created after startup is not discovered until config reload #42478: project .agents paths get watch handling that the global compatibility root does not.
    • opencode api skill.list was inconsistent across calls in this environment (once empty, once built-ins only, once including the new skill right after a reload), so the reliable signal here was the model-side skill list rather than the API.
    • Workaround used: opencode reload after installing skills into a global compatibility directory.

    Related: #43742 (global ~/.agents/skills not loaded at all), #42478 (project .agents created after startup), #54114 (watcher loop on .agents/skills).

  6. r266-tech commented on Oct 19, 2026

    @r266-tech
    Contributor

    I independently reproduced a narrower case on current dev (f394d9d410bc) on macOS: .agents already exists, but skills/ does not exist when the compatibility plugin starts. Creating skills/probe/SKILL.md afterward leaves the registry empty. The compatibility loader skips the missing directory, so nothing observes its creation.

    There is already a fix for that boundary in #55280, including watch readiness/reconciliation. I am linking it here rather than opening another PR.

    For the narrow boundary, a local subscription to the missing directory as a file target makes discovery and subsequent edits work. The existing config/skill suite passed 10 runs; a separate fixture using the real compatibility plugin, native filesystem events, watcher readiness, and Skill.Service registered the new skill in 10/10 runs. The unchanged-code controls fail. This is focused fixture validation, not a green full-suite result or a test of #55280's entire head.

    For the Termux report, did ~/.agents/skills exist before the installation? If it already existed, that observation may involve a different event-delivery boundary. This also does not establish the persistent-empty-state cause in #57035. AI-assisted investigation.

  7. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    Thanks for the detailed report. I tried this on Linux with 2.0.21. With the service running, I created ~/.config/opencode/skills/probe-skill/SKILL.md, and within a few seconds the service logged skills rescanned and probe-skill showed up in opencode api get /api/skill without a restart.

    On Windows, OpenCode uses a different file-watcher backend, so this looks specific to Windows. I can't test Windows here, so it needs a maintainer with a Windows machine to confirm.

    These would help in the meantime:

    • Run opencode service restart, add the skill directory, then check the service log (under %LOCALAPPDATA% or ~/.local/share/opencode/log/opencode.log). Look for watcher started / failed to subscribe lines whose path is your skills folder, and paste them here, including the backend= value.
    • Tell us whether it makes a difference if you create the folder first and the SKILL.md a few seconds later, or copy in a whole folder at once.

    Possibly related: #57524 (/api/skill empty on Windows) and #47505 (updating a global skill on Windows terminates the service).

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