[Flat Install Layout] Flat directory naming for global agent skill installs#31
Merged
[Flat Install Layout] Flat directory naming for global agent skill installs#31
Conversation
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Add FlatKey() and InstallFlat() to the install package. FlatKey converts composite keys (github.com/org/repo/skill) to flat directory names (github-com--org--repo--skill) by replacing / with -- and . with -. Wire InstallFlat() for global installs in install, get, and update commands. Project installs continue using nested layout via Install(). Update remove to use FlatKey() for global cleanup and skip parent directory cleanup (flat layout has no parents to clean). Update list --detailed and tree to show composite key format for globally installed skills. Add 6 new tests covering FlatKey edge cases, flat install structure, multi-package, same-name collision safety, and overwrite semantics. Update README.md and E2E_REAL_WORLD_TEST.md with flat layout documentation and expected directory structures. Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
- Add collision detection in InstallFlat: returns error when distinct composite keys produce the same flat key (MF-2) - Add TestInstallFlatCollisionDetection for dot-vs-dash collision case - Improve TestFlatKey to use t.Run subtests for CI diagnostics (C-3) - Document collision limitation in FlatKey docstring and README (SF-6) Co-authored-by: Copilot <[email protected]>
SF-1: Make FlatKey injective — only replace slashes with --, preserve dots as-is. Dots are valid directory characters on all platforms, eliminating the lossy dot-to-dash collision risk entirely. MF-1: Add TestRunRemoveGlobal_FlatCleanup integration test that verifies flat directory cleanup for global remove operations. SF-2: Extract CompositeKey() helper in install package for consistent key construction. Remove.go now uses CompositeKey instead of manual string concatenation, eliminating implicit coupling. SF-3/SF-4: Extract QualifySkillNames() helper in install package, used by both list.go and tree.go to eliminate duplicated display logic. Both commands now use the shared helper instead of inline loops. SF-5: No migration needed — no prior releases used nested global layout. TestInstallFlatDistinguishesDotFromDash: New test proving dots and dashes produce distinct flat keys with injective encoding. Co-authored-by: Copilot <[email protected]>
C-2: QualifySkillNames skips empty skill names to avoid trailing-slash display artifacts in list/tree output. C-4: InstallFlat returns a clear error for empty composite keys instead of falling through to Install's path traversal check with a misleading 'escapes target directory' message. Add TestInstallFlatRejectsEmptyKey test. Co-authored-by: Copilot <[email protected]>
Apply sanitize() to all user-derived strings (alias, URL, skill names, local skills) before passing to RenderTree. Previously list.go sanitized its output but tree.go did not, creating an inconsistency. Co-authored-by: Copilot <[email protected]>
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
Global skill installs now use flat directory names so AI agents (Claude Code, GitHub Copilot) can discover them. The composite key
github.com/org/repo/skillbecomesgithub-com--org--repo--skill— a direct child of the agent's skills root.Project-scoped installs (
forge/) are unchanged and continue using nested composite-key paths.Changes
Core (
internal/install/installer.go)FlatKey()— pure function converting composite keys to flat directory names (.→-,/→--, casing preserved)InstallFlat()— transforms keys viaFlatKey()then delegates toInstall(), reusing all atomic staging, path traversal validation, and overwrite logicCLI Wiring (
install.go,get.go,update.go)craft install -g,craft get,craft update -g) now callInstallFlat()instead ofInstall()Install()— no change toforge/layoutRemove (
remove.go)FlatKey()to derive directory names for cleanupcleanEmptyParentsfor global scope (flat layout has no parents)Display (
list.go,tree.go)craft list -g --detailedandcraft tree -gnow show composite key format (e.g.,github.com/org/repo/skill) for readabilityTests (
installer_test.go)TestFlatKey,TestFlatKeyEdgeCases,TestInstallFlatCreatesStructure,TestInstallFlatMultiPackage,TestInstallFlatSameName,TestInstallFlatOverwritesDocumentation
Testing
go test ./...✅,go vet ./...✅,go build ./...✅Design Decisions
--separator is collision-safe — GitHub disallows--in org/repo namesInstallFlat()delegates toInstall()— no code duplication, all staging/validation logic reusedFlatKey()without needing reverse transformationArtifacts
PAW workflow artifacts viewable at
a02355e:🐾 Generated with PAW