Agent skills do not load from the mapped drive

Pitfall Workaround available
Claude Code does not discover project skills in a workspace's .claude/skills/ folder when the workspace is opened over the WebDAV-mapped drive, so a skill added there never appears and restarting does not help. The instruction files are unaffected - CLAUDE.md, its @-imported files and settings.local.json are read once at session start and load normally - because only skill discovery depends on directory watching, and fs.watch fails with EISDIR on the mapped drive. Keep Docly skills in the personal ~/.claude/skills/ folder, written workspace-agnostic, with the workspace-specific facts in .claude/CLAUDE.md; or work from a git clone, where project skills load the way the documentation describes.
Applies to: AI agentsWorkspace setupMapped drive

What you'll see

You follow Set up AI agent instruction files for a workspace, add a skill at .claude/skills/my-skill/SKILL.md in a Docly workspace opened over the mapped drive, and restart Claude Code. The skill never appears. /skills does not list it, and invoking it by name returns Unknown skill.

Nothing looks wrong. The front matter is valid, the file sits in a folder named after the skill, CLAUDE.md from the same .claude/ folder loaded fine — and the identical file works in other projects. Restarting again does not help.

What's actually happening

The file is fine. The location is the problem: Claude Code does not discover project skills on the WebDAV-mapped drive.

The controlled test

The same 119-byte pure-ASCII SKILL.md, nothing changed but where it sits:

Location of .claude/skills/zz-probe/SKILL.mdListed
Local disk, in a folder named probe.no (LIVE)yes
L:\databaseutvikling.no (LIVE)\ (mapped drive)no

That rules out the usual suspects in one step: the skill's own content, non-ASCII characters in the description, a long description, and parentheses or dots in the workspace path — the local test folder was deliberately named to carry the same characters.

The file system is not hiding the folders either. fs.readdirSync(dir, {withFileTypes: true}) returns every skill directory on the mapped drive with isDirectory() === true, exactly as it does locally.

What actually fails

Directory watching:

node -e "require('fs').watch('L:\\<workspace>\\.claude\\skills', ()=>{})"

Mapped drive : EISDIR: illegal operation on a directory, watch
Local disk   : OK

Claude Code's documentation states that it watches skill directories for changes, and that creating a top-level skills directory that did not exist when the session started "requires restarting Claude Code so the new directory can be watched". Discovery and watching are coupled. A watcher that cannot be established on the skills directory is the most plausible reason the directory is never registered.

That last step is inference from observed behaviour, not from reading the source. The EISDIR failure and the load test are measured.

Why the instruction files are unaffected

CLAUDE.md, any @-imported file such as docly.md, and .claude/settings.local.json are read once at session start and need no watcher. All three were verified to load from the mapped drive — including an allow-rule from settings.local.json taking effect in a headless session that otherwise auto-denies every prompt. Only skills are affected.

Measured on Claude Code 2.1.220, Windows 11, drive mapped through the Windows WebDAV redirector. If a later version changes this, the two commands above are the check.

What to do

Put the skills in the personal folder

~/.claude/skills/<skill-name>/SKILL.md lives on the local disk, so it loads normally — and it loads in every workspace. That suits Docly skills well, because the platform rules they describe are the same in all of them.

Write them workspace-agnostic, and keep the workspace-specific facts in .claude/CLAUDE.md, which does load from the mapped drive. Nothing is duplicated: the general goes in the skill, the local goes in the instruction file.

Creating ~/.claude/skills/ when it did not exist before requires one restart before the skills appear.

Or work from a git clone

A clone is a local working copy, so project skills in its .claude/skills/ load the way the documentation describes. See Using Git with Docly.

git clone https://<instance>/git/<Folder>

What still belongs in the workspace

Do not move these — they work from the mapped drive, and the workspace root is published, so they must stay under .claude/:

  • .claude/CLAUDE.md — which workspace this is, and its local conventions
  • .claude/docly.md — the KB mandate and the documentation map
  • .claude/settings.local.json — the permission allowlist

Leave a note where the next agent will look

An agent that reads the recommendation to use .claude/skills/ will recreate the folder and lose the same hour. One line in CLAUDE.md prevents it:

Do not put skills in .claude/skills/ here. Claude Code does not discover
them from the WebDAV-mapped drive - skill folders must be watchable, and
fs.watch returns EISDIR on this drive. The Docly skills live in
~/.claude/skills/ instead.

Checking it yourself

Two commands settle it. Run the fs.watch probe above, then start a session in the workspace and ask which skills it can see:

claude -p "List the names of every skill in your available-skills listing, one per line, nothing else."

A fresh process is the same as a restart, so this also answers "did it just need restarting?" — it does not.