feat: symlink to multiple vendors and shared configurable lib#74
feat: symlink to multiple vendors and shared configurable lib#74mikkezavala wants to merge 3 commits intoShpigford:mainfrom
Conversation
|
I have a small fix, in non-existent dirs.... |
7b10208 to
6334bed
Compare
|
Haven't reviewed yet but just saying the thing out loud: I'm super nervous about this. It's 100% needed (we all know how much of a dumpster fire skills files are). But just clarifying I want to be VERY careful as we approach this. |
|
@Shpigford I totally understand. I really just wanted to have a head first to this, but very open for feedback and approach bounce. if feels unstructured, we can benefit from an spec, to benefit the most as possible. |
|
Talking this out. How would this practically work with daily usage? Say a user creates a new skill from...anywhere (Claude CLI, Having a hard time picturing what the workflow would be. |
bf21797 to
a8217d6
Compare
|
@Shpigford Not really, global is a new concept and optional one: The way I use it is I do have it in a global directory (~/.chops as example) and I store them there and I decide where to link to. If you create one in ~/.claude it will stay there even if you have the "shared" one but you can also link it to ~/.cursor, the shared is just an extra layer for organization in reality does not affect the core capability. You can create in shared and symlink it to any other vendor if you want to, but you might not want to. |
a3bddb2 to
c1e2a94
Compare
c1e2a94 to
3288329
Compare
Symlink multi-vendor support
Adds the ability to symlink a skill, agent, or rule into any installed vendor's global directory directly from the detail view. Includes a new shared library concept: a vendor-neutral directory you configure once and link from freely.
Note: Most of the vendors (Cursor, Augment, Windsurf, etc...) already mostly inherits plugins, skills, rules from ~/.claude. This gives you an extra layer if you want to disable in the that capability.
I did not used additional directories, that is meant more for "project" specific skills/rules and pinning on it will cause to deviate from it's original intent.
With the Shared lib, you can point to any directory, including
iCloud Driveand just symlink. WARNING: different machines might need similaruser homedirectory to work out of the box.What changed
ToolSource.shared— new enum case backed by a user-configured path (sharedLibraryPathin UserDefaults). Derivesskills/,agents/, andrules/subdirectories automatically.isInstalledreturns true only when the configured path exists on disk.SymlinkTarget(SwiftData model): tracks every active symlink as a(resolvedPath, toolSource)pair. StoresToolSourceandItemKindas raw strings for#Predicatecompatibility; exposes typedtoolSourceEnum/itemKindaccessors.isBrokenis set by reconcile when the linked path no longer resolves.SymlinkService:@MainActorsingleton.linkcreates the symlink and inserts the record (idempotent only when the existing symlink points to the same source; errors if it points elsewhere).unlinkusesattributesOfItemto distinguish a deleted file from a non-symlink, cleaning up the record silently in the former case.targetsandisLinkedlog fetch errors instead of swallowing them.reconcileis called on launch and after every scan.VendorLinkingPanel: collapsible panel in the skill detail view (hidden for plugin and remote skills). Shows only installed vendors that support the skill's kind. Excludes the resolved physical origin and any symlink host unless an active record already exists (which allows unlinking).VendorLinkRowtakesinitiallyLinkedat init time viaState(initialValue:)soonChangeonly fires on real user interaction, not ononAppear.linkedPathis cached in@Stateand refreshed after each operation.PathCrumbrenders a single-line~/src → ~/dstdisplay.LibrarySettingsView: replaces the old SOT directory picker with a shared library path field + Browse button. Tilde expansion is normalized on bothonSubmitand after Browse via a sharednormalize(_:)helper.includeHiddenFilesis persisted via@AppStorage.ToolSource.globalDirs(for:): new extension method that returns the correct global paths for a givenItemKind, eliminating the duplicateditemKindswitch that previously existed in bothVendorLinkingPanelandSymlinkService.ChopsSettings: Cleaned SOT directory properties (sotDir,sotSkillsDir, etc.) that were superseded byToolSource.shared.This resolve most of: #13, #16, #17, #66 and maybe #68