Skip to content

fix(sync): Adopt only directories that contain a SKILL.md - #194

Merged
gricha merged 1 commit into
getsentry:mainfrom
m-naoki-m:fix/sync-adopt-only-skill-dirs
Sep 28, 2026
Merged

gricha merged 1 commit into
getsentry:mainfrom
m-naoki-m:fix/sync-adopt-only-skill-dirs

Conversation

@m-naoki-m

Copy link
Copy Markdown
Contributor

sync adopts every undeclared directory under the skills directory, whether or not it is a skill. A hidden directory gets written to agents.toml under a name the config schema rejects, and from then on every command fails, doctor included:

$ git init -q demo && cd demo
$ printf 'version = 1\nagents = ["claude"]\n' > agents.toml
$ mkdir -p .agents/skills/.cache
$ npx @sentry/dotagents --project sync
Invalid config in /path/to/demo/agents.toml:
  - skills.0.name: Skill names must start with alphanumeric and contain only [a-zA-Z0-9._-]
$ npx @sentry/dotagents --project doctor
Invalid config in /path/to/demo/agents.toml:
  - skills.0.name: Skill names must start with alphanumeric and contain only [a-zA-Z0-9._-]

A directory without a SKILL.md, such as notes/, is adopted as a skill named notes.

I hit this with Claude Code. Global init migrates ~/.claude/skills/ into ~/.agents/skills/, and Claude Code keeps its own synced/ (skills synced from claude.ai, nested one level deeper under an account directory), .trash/, and .staging/ there. After init --agents claude,codex,opencode, the next sync wrote .staging, .trash, and synced into ~/.agents/agents.toml, and sync, install, and doctor all exited with the error above.

Fix

The adopt step now skips a directory unless its name passes the same check managedSkillPath uses and it contains a SKILL.md. This also covers .dotagents-managed, so its special case is removed. Pruning of stale managed skills runs before the new check and is unchanged.

If a directory that was adopted earlier loses its SKILL.md and its agents.toml entry, its in-place agents.lock entry is dropped too. Otherwise the leftover lock entry would make .agents/.gitignore list the directory as managed and hide its files from Git.

specs/SPEC.md now says which directories sync adopts. The README, docs site, and bundled skill already describe adopting skills, which matches the new behavior.

Verification

  • pnpm check passes on Node 20 and 26 (lib 295 tests, host 844). The CI build job steps (pnpm build, CLI --help, packing both packages, scripts/verify-pack.mjs) pass on Node 20, and the docs build passes on Node 22.
  • Two new tests in sync.test.ts, both failing on main:
    • adopts only directories that are valid skills places .trash/, synced/<bucket>/<skill>/, a notes/ without SKILL.md, and a valid review/, and expects only review to be adopted.
    • forgets an adopted skill whose directory no longer has a SKILL.md expects the stale lock entry to be removed and the directory to stay out of .agents/.gitignore.
  • The built CLI against a throwaway HOME containing ~/.claude/skills/{review,synced/<account>/pdf,.trash/old,.staging}: init, sync, install, and doctor all succeed, and only dotagents and review are declared. The same run in the dotagents-qa Docker image passes, and pnpm qa:example passes there.
  • pnpm qa:plugins fails in the Docker image at the Copilot proof ("Copilot did not report enabled qa-tools from the live local marketplace"), on main as well.

Separately from this fix, Claude Code's claude.ai-synced skills end up visible to Codex after the global migration. That needs a design decision, so I opened #193 for it.

sync adopted every undeclared directory under the skills directory. A
hidden directory such as .trash/ was written to agents.toml with a name
the config schema rejects, so every later command, including doctor,
failed with 'Invalid config'. Directories without a SKILL.md, such as
Claude Code's synced/ after ~/.claude/skills/ is migrated, were adopted
as skills.

Adopt a directory only when its name is a valid skill name and it
contains a SKILL.md. Pruning of stale managed skills is unchanged. If a
directory adopted earlier loses its SKILL.md and its agents.toml entry,
drop its in-place agents.lock entry too, so .agents/.gitignore stops
hiding its files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 27, 2026

Copy link
Copy Markdown

@m-naoki-m is attempting to deploy a commit to the Sentry Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added the risk: medium PR risk score: medium label Sep 27, 2026
@gricha
gricha merged commit e42112b into getsentry:main Sep 28, 2026
12 of 13 checks passed
@gricha

gricha commented Sep 28, 2026

Copy link
Copy Markdown
Member

Thanks!

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

Labels

risk: medium PR risk score: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants