anthropics / anthropics/claude-code

Account skills sync moves locally-installed skills out of ~/.claude/skills/ into skills/.trash, though the docs scope the sweep to skills/synced/

Open
#95,373 0 comments 0 reactions 0 assignees View on GitHub
area:skills bug platform:macos
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

## Summary

Across seven separate events, Claude Code moved **83 skill directories that live flat at `~/.claude/skills//`** into `~/.claude/skills/.trash/`. 69 of them are a third-party skill pack installed locally two months ago by copying directories into `~/.claude/skills/` — they were never uploaded to, or enabled on, claude.ai.

`~/.claude/skills/synced/` **has never existed on this machine** — not on disk, and not in any commit of the git repository that versions `~/.claude` (checked with `git log --diff-filter=A -- 'skills/synced*'` → 0 commits).

The docs scope this mechanism to `synced/` only, so the observed behaviour appears to be a bug rather than the documented opt-out.

## Environment

- Claude Code 2.1.276 (the waves also occurred under 2.1.273 and 2.1.274)
- macOS 24.6.0, arm64
- `~/.claude/settings.json`: `"syncClaudeAiSkills": false`, `"syncClaudeAiPlugins": false`
- No `settings.local.json`, no managed settings file present
- `~/.claude` is a git repository, so every moved file is provably tracked and restorable — which is how the loss was measured precisely

## What happened

Each wave creates one `~/.claude/skills/.trash/--//` entry per skill, all sharing one timestamp, each wave under a different pid.

| # | UTC | entries |
|---|---|---|
| 1 | 2026-09-16 18:30:27 | 69 |
| 2 | 2026-09-17 07:40:47 | 69 |
| 3 | 2026-09-17 15:30:30 | 69 |
| 4 | 2026-09-17 17:28:03 | 69 |
| 5 | 2026-09-17 17:33:18 | 84 |
| 6 | 2026-09-17 20:33:11 | 69 |
| 7 | 2026-09-18 13:03:19 | 69 |

Between waves the directories were restored from git, which is why the same skills were moved repeatedly. Wave 7 happened 48 minutes after a restore, with no session started in between that I could correlate — consistent with the documented background check "about every 10 minutes" rather than with "at the next launch".

`~/.claude/plugins/synced/.bucket-_` was created at 2026-09-16 18:30:25 UTC — two seconds before wave 1 — and is empty. No `skills/synced` was ever created.

## What was moved

- **69 directories from a third-party skill pack**, installed locally on 2026-08-10 by copying them into `~/.claude/skills/`, committed to my own repo, never touched by claude.ai.
- **14 account-provisioned skills** (`xlsx`, `pptx`, `pdf`, `docx`, `docs`, `morning`, `theme-factory`, `slack-gif-creator`, `canvas-design`, `brand-guidelines`, `algorithmic-art`, `mcp-builder`, `internal-comms`, `import-memory`) — these I would expect to be in scope.

Not moved: 62 other flat directories in the same parent (my own authored skills). So the selection is not "everything under `skills/`" — but it does include locally-installed directories that were never synced.

## Why this looks like a bug

From the docs:

- `en/skills`: "Claude Code downloads your account's skills into `~/.claude/skills/synced/` in the background, then checks claude.ai for changes about every 10 minutes."
- `en/skills`: "To stop syncing on a machine, set `syncClaudeAiSkills` to `false` in your user settings. Claude Code stops downloading, and the next time it starts it moves **the skills it already synced** to `~/.claude/skills/.trash/` and no longer loads them."
- `en/skills`: personal skills live at `~/.claude/skills//SKILL.md` and are described as a separate location from claude.ai account skills.
- `en/claude-directory`: `skills/.trash/` is "synced skills that Claude Code removed".

Nothing in the docs describes a path by which a flat `~/.claude/skills//` directory that was never synced is treated as synced or swept. On this machine, directories in exactly that location, with no `synced/` present at all, are being moved.

## Reproduction

I have not reproduced this on a clean machine — it is reproducing continuously on mine, and I can run any diagnostic you would like. The shape appears to be:

1. Sign in to a claude.ai account that has account skills enabled.
2. Install a skill pack locally by copying directories into `~/.claude/skills//` (no `synced/` directory, no upload to claude.ai).
3. Set `"syncClaudeAiSkills": false` in `~/.claude/settings.json` (the waves began before I set this, so it may not be required).
4. Leave a session running, or start one, and wait.

Expected: only skills under `~/.claude/skills/synced/` are ever moved to `.trash`. Actual: flat, never-synced directories under `~/.claude/skills/` are moved.

## Impact

Every skill in the pack stops loading, silently. There is no message at the time of the move, and nothing in a session says why a skill vanished — the first wave went unnoticed for about 24 hours. Users whose `~/.claude` is not version-controlled would be relying on `.trash` alone, which the retention sweep deletes after `cleanupPeriodDays` (default 30).

## Questions

1. Is the sweep supposed to consider anything outside `~/.claude/skills/synced/`?
2. When `synced/` does not exist, does the sweep fall back to treating `~/.claude/skills/` as the synced root?
3. Is there a supported way to mark a locally-installed directory as out of scope? I could not find one in `en/skills`, `en/claude-directory`, or the settings reference.

Happy to attach the full list of moved directory names, the per-wave pids, or anything else useful.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the behavior and scope described in en/skills and en/claude-directory, then locate the background skill-sync check and any related tests. Trace how it selects directories when skills/synced/ is absent. Done means locally installed flat skills remain in place while only documented synced skills are moved to .trash.

Written by the indexing model from the issue text.

Assessment

Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.