feat(skills): install and remove only skill folders deepctl owns - #124
Draft
dg-coreylweathers wants to merge 7 commits into
Draft
dg-coreylweathers wants to merge 7 commits into
dg-coreylweathers wants to merge 7 commits into
Conversation
dg skills install, update, setup, remove, status and list now install the Deepgram skills as folders in each tool's skills folder. A folder is replaced or deleted only when skills.json records it for that tool, it is a real folder directly in the tool's root, it holds the .deepctl-skill marker, and its content fingerprint matches what deepctl installed. Edited folders are left alone. The record is saved before a folder moves into place, a destination is claimed with mkdir so a folder created after preflight is never replaced, and staging leftovers are reported, never swept by name. Login and plugin keep working through a compatibility shim.
…ints remove keeps a folder's record while its copy waits in staging, and an interrupted put-back is retried. A file or symlink swapped in before a move is put back with a no-replace link on POSIX. The MCP hint now names /setup-mcp and only prints after a Claude Code install, counts are pluralized, and remove notes 0.3.x files that stay behind.
…eporting remove marks a folder held before moving it aside and puts it back if interrupted. A tool upgraded from 0.3.x keeps a v03 flag so remove still notes the files left behind after a plugin refresh. Messages no longer assume a count or claim nothing was installed, and the cross-tool halt, moved-folder report and reporting guards are now covered by tests.
…ve messages remove now says it no longer tracks a folder it cannot prove, and only mentions 0.3.x files when the tool really has some. New tests cover an unreadable folder at settle, remove_tool errors, the v03 condition, setup --ref, status after a user deletes a folder, and a corrupt state failing before any prompt. Command tests pin the console width.
The compatibility shim returns a hint-only tool's recorded 0.3.x paths instead of an empty list, so remove still notes those files after a plugin refresh. E13 and E18 give remedies that fit every cause, remove's staging failure (E21) is tested, and the command tests restore Rich's console width.
… exist list now says no skill folders are installed, which stays true on a HOME upgraded from 0.3.x. Tests pin the release label in the install summary and the Ref column in list.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second PR of the five that replace #111. Stacked on #123 (goal 1, the skills bundle fetch). Its base is
goal/bg-1-skills-bundle-fetchuntil #123 merges, then it will be rebased ontomain.What it does
dg skills install,update,setup,remove,statusandlistnow install all 14 Deepgram skills as folders in each tool's skills folder. The skills come from the pinned bundle that goal 1 added. Before this, skills were concatenated into files, andremovedeleted by glob, so it could delete a user's own files.~/.claude/skills~/.agents/skills~/.gemini/skills~/.cursor/skills~/.config/opencode/skills~/.cline/skillsThe ownership rule, in plain words
deepctl replaces or deletes a skill folder only if all four of these are true:
skills.jsonrecords it for that tool..deepctl-skillmarker.Anything else is left alone and reported. That covers a user's own skills, folders from
npx skills add, symlinked skill folders, and deepctl folders the user has edited. The fingerprint is checked again on the moved-aside copy right before anything is deleted, so an edit made while the operation runs is also caught and put back.Greg's findings this closes (from the 2026-10-05 review on #111)
os.mkdir(POSIX) or a plainos.rename(Windows, which refuses an existing destination). Test: the destination is created afterinstall_conflicts()returns, and the user's folder survives.save_skills_statefails on that write, and no new folder is left while the old one stays intact.mkdtemp, and leftovers are reported, never swept. Test: a user-created.api.tmp-123and.api.old-1-2survive install and remove.CI,CLAUDECODEand TTY variables both set and unset.skills.jsongo through goal 1's name check.Compatibility
Login and plugin are unchanged. A compatibility shim keeps
SkillGenerator.install()and the six module functions they call. Records live under their own key, and the publicsave_skills_state()re-reads that key from disk. That way, a login or plugin run that saves a stale copy of the state can't erase the install records. A test runs the read-install-save-stale sequence. Plugin's auto-update keeps a user's--ref.Upgrade from 0.3.x
I built a HOME with origin/main's real
dg skills install --all, then ran this branch's install, update, an edited-folder update, andremove --allagainst it, as root and as uid 1000. Every 0.3.x file and every seeded user file stayed byte-identical. The 0.3.x files (~/.claude/commands/deepgram/*.md, the marked sections in shared instruction files, and the rules files) stay in place until goal 4.removedrops a tool's 0.3.xinstalled_skillsentry but leaves its files.skill_folders.<tool>.v03records that a tool's 0.3.x files remain, soremovecan say so even after a plugin refresh. Goal 4 must clear it after a successful cleanup.What is deliberately not here yet
skills.jsonlock and the re-check under it (S5): goal 5. Without the lock, two deepctl runs that overlap can lose one run's records: its folders stay on disk but read as not deepctl's, and the next run refuses them until the user deletes them. No file is deleted.-o table/csv, and edit-tolerant fingerprints. Finder's.DS_Storecounts as an edit, and the README says so.How to review
skill_generator.py: ownership helpers (_ownership,_fingerprint,_marker_ok), theninstall_conflicts,install_tool(stage → mark → swap → settle → cleanup),remove_toolandtool_status.command.py: the handlers, which are thin over core.Verification
Stacked series: 2/5. Tracking PR: #111.
🤖 Generated with Claude Code