How Cowork Implements Skills
By Feifan Zhou
Claude Code and other agent harnesses load skills from your local filesystem. They live in .agents/skills or .claude/skills, either in your home directory or within a project directory; they don't change unless you ask them to change; and in general behave like normal files.
Cowork … does not do this. In Cowork, editing skills from the filesystem seemingly does nothing, and sometimes they disappear.
I wanted to understand how Cowork's skill implementation actually worked, so I pointed an agent at /Applications/Claude.app/Contents/Resources/app.asar and cracked it open.
Cowork has a skills plugin cache
Claude Desktop writes its state/config to ~/Library/Application Support/Claude. Within that directory, Cowork skills are located in local-agent-mode-sessions/skills-plugin/<orgId>/<accountId>.
Inside one of these folders, the structure looks roughly like this:
.claude-plugin/plugin.json
manifest.json
skills/
schedule/SKILL.md
consolidate-memory/SKILL.md
setup-cowork/SKILL.md
xlsx/SKILL.md
pdf/SKILL.md
pptx/SKILL.md
docx/SKILL.md
skill-creator/SKILL.md
<user-or-remote-skill>/SKILL.md
These skills come from three places:
- built-in Anthropic skills bundled with Claude Desktop
- team-shared skills fetched from Claude's internal backend
- user skills created outside of a Cowork project
manifest.json contains an index of which skills exist, whether they are enabled, and when they were last updated.
Notably, these files are not the source of truth! They are treated as an ephemeral cache, and are frequently overwritten.
Shared skills are synced from private APIs
Cowork has a built-in (albeit clunky) mechanism for sharing skills with your team, synchronized through private APIs:
GET /api/organizations/<org_uuid>/skills/list-skills?include_wiggle_skills=true&entrypoint=local-agent
GET /api/organizations/<org_uuid>/skills/download-dot-skill-file?skill_id=<skill_id>&entrypoint=local-agent
The version driver is updatedAt. If the server returns a skill with a newer updatedAt, or if the local SKILL.md is missing, Claude Desktop downloads the skill again. If a managed remote skill is no longer returned by the backend, Desktop removes it from the cache.
API endpoints for updating shared skills exist, but calling them with proper authentication is a challenge.
Sync runs more often than you might expect
When Claude Desktop is launched, and then periodically (typically every 10 minutes), skills are re-synced and the existing files on disk (both the manifest.json and skills directories themselves) are re-written from server-side data.
If Claude Desktop is not focused, it'll skip a sync interval and catch up later when the app is focused again. It also syncs when the window regains focus if enough time has passed.
Each sync roughly does this:
- resolve the active org and account
- ensure the plugin directory exists
- rewrite built-in skills
- read and normalize
manifest.json
- fetch enabled remote skills
- download changed skills and remove stale managed skills
- preserve local user skills marked
syncManaged: false
- delete orphan directories not represented in the manifest.
If manifest.json is corrupt, Desktop quarantines it as manifest.json.corrupt and rebuilds from what it can recover.
There is an escape hatch
Setting syncManaged: false for a skill in manifest.json will tell the sync engine to leave that skill alone, which means its manifest entry and files on disk will not be overwritten.
Skills are mounted into Cowork sandboxes
Claude Chat and Cowork sessions run in a server-side sandbox, into which skills are mounted. The underlying sessions are not reading skill files directly from files on your local disk.