feat(skill): add explicit project scope - #643
Open
ousamabenyounes wants to merge 4 commits into
Open
Conversation
The workspace-isolation wording in docs/install.md is restored exactly as written, with the project-scope exception added as a separate line instead of a rewrite. SKILL.md, SKILL_en.md and docs/update.md carried the same rule and would otherwise instruct agents to refuse a supported flag.
A project-scoped install had no matching removal: _uninstall_skill() only swept user directories, so files the CLI created in a project could not be removed by the CLI. Both operations now resolve the target through one helper that refuses symlinked path components, and the absolute destination is printed before the first write. 'agent-reach uninstall' stays user-scoped.
The scope guard, the symlinked-target unlink, the removal-failure report and the not-found message were all reachable but unasserted: each one survived being broken. Also restores a blank line dropped with the old argument validation, and narrows the _project_skill_paths docstring, which claimed more containment than a pre-flight symlink check can give.
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.
摘要 / Summary
根据维护者关闭 #390 时提出的方向,本 PR 实现了显式的
scope参数:--scope=user|project。默认值仍为user,不进行隐式推断。Adds an explicit
--scope=user|projectparameter for skill registration.userremains the default, and nothing is inferred from the working directory.
Addresses #333.
Design rationale
Issue #333 asked for project-local skill installation, and listed an explicit
--scopeflag as one of its two options. #390 (@StevanusPangau) explored thefeature and identified the same target path, but derived the scope from the
working directory; it was closed in favour of designing an explicit scope
parameter. This PR implements that project-local target with an explicit flag
rather than inference, on the current installer.
Keeping
useras the default is deliberate: an implicit write into the workingdirectory would contradict the workspace-isolation rules in
docs/install.mdand the read-only-by-default install introduced in #577.
On
agent-reach install, project scope is already covered by the--systemgate from #577 —
install --scope=projectwithout--systemwrites nothing.Only
agent-reach skill --install/--uninstallis ungated, and it is ungatedtoday for user scope too, so this PR did not add a second authorization flag
there. Instead the resolved absolute destination is printed before the first
write, so a project-scoped install is never silent about where it lands. Happy
to put the
skillsubcommand behind--systemas well if you prefer.Changes
--scope=user|projectonagent-reach installandagent-reach skill --install/--uninstall, defaulting touser<cwd>/.claude/skills/agent-reachthrough one helpershared by install and uninstall, which refuses to proceed when
.claudeor.claude/skillsis a symlinkskill --uninstall --scope=projectremoves that directory, so aproject-scoped install can be undone by the CLI that created it;
agent-reach uninstallstays user-scoped and never touches the workingdirectory
docs/install.mdis kept byte-identical andthe exception added as a separate line;
agent_reach/skill/SKILL.md,SKILL_en.mdanddocs/update.mdstate the same rule and are updated in thesame PR, so the agent-facing instructions do not tell an agent to refuse a
supported flag
CHANGELOG.mdentry under## [Unreleased]— happy to drop or re-target itif you keep the changelog on a different cadence
Documentation diffs are additions only:
docs/install.md+19/-0,docs/update.md+2/-0,SKILL.md+2/-0,SKILL_en.md+3/-0.Test verification (RED → GREEN)
tests/test_skill_command.pyfrom this branch applied toupstream/mainwithno production changes (RED):
Patched branch (GREEN):
upstream/mainbaseline is 586 passed, measured in a clean worktree; this PRadds 20 tests and removes none.
Each project-uninstall branch was mutation-checked rather than only covered —
breaking the scope guard, the symlinked-target unlink, the removal-failure
report or the not-found message each fails a test:
Verification
ruff check agent_reach tests— All checks passedmypy agent_reach— Success: no issues found in 35 source filespytest -q— 606 passed