Skip to content

Commit d21e471

Browse files
陈一斌陈一斌
authored andcommitted
Unify discovery installs and skill trials
Replace the old marketplace-oriented discovery flow with a skills.sh-backed experience, concurrent install activity tracking, and discovery-first Try entry points. The app now detects local coding agents from ~/.xxx-style footprints or imported folders, offers install-target selection, avoids URLSession cache-backed sqlite churn, and normalizes OpenAI-compatible provider endpoints so the new Try surface respects the active LLM provider settings. Constraint: Discovery now depends on the public skills.sh HTML structure instead of the removed marketplace service Constraint: Local agent detection must tolerate missing default folders and imported custom roots Rejected: Keep Trial as a sidebar state filter | it left testing fragmented and disconnected from discovery intent Rejected: Trust raw compatible-provider base URLs blindly | local providers returned 404s when /v1/chat/completions was not normalized Confidence: medium Scope-risk: broad Reversibility: clean Directive: Keep discovery actions centered in Discover rather than reintroducing a separate Trial navigation branch without a full real-agent execution model Tested: swift build --disable-sandbox; swift test --disable-sandbox Tested: xcodebuild -project SkillsManager.xcodeproj -scheme SkillsManager -configuration Release -destination platform=macOS build (blocked by sandboxed package resolution / local Xcode environment) Not-tested: GitHub release publication or notarized archive flow Not-tested: End-to-end manual Try run against every provider/backend combination
1 parent 66b1103 commit d21e471

34 files changed

Lines changed: 2218 additions & 813 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ SkillsManager.xcodeproj/project.xcworkspace/xcuserdata/
1616

1717
# Intermediate logo files
1818
*_rgba.png
19+
.omx/

Package.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,10 @@ let package = Package(
1818
],
1919
path: "SkillsManager"
2020
),
21+
.testTarget(
22+
name: "SkillsManagerTests",
23+
dependencies: ["SkillsManager"],
24+
path: "Tests/SkillsManagerTests"
25+
),
2126
]
2227
)

README.md

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ A native macOS app to manage skills across all your coding agents — Claude Cod
88

99
## Screenshots
1010

11-
![Discover & Sandbox](docs/screenshots/discover.png)
12-
*Discover marketplace plugins and test them in the built-in sandbox*
11+
![Discover](docs/screenshots/discover.png)
12+
*Discover skills from skills.sh and inspect them in the native detail view*
1313

1414
![Starred Skills](docs/screenshots/starred.png)
1515
*Manage your library — filter by agent, source, or starred*
@@ -20,7 +20,7 @@ A native macOS app to manage skills across all your coding agents — Claude Cod
2020

2121
Coding agent skills are scattered everywhere. Each agent has its own format, install path, and management story. Skills Manager brings them together in one place.
2222

23-
- **Discover** skills from the marketplace and community sources
23+
- **Discover** skills from [skills.sh](https://skills.sh/) and community repositories
2424
- **Install** to one or multiple agents at once
2525
- **Test** skills in the built-in LLM sandbox before committing
2626
- **Manage** installed skills — update, remove, star favorites
@@ -55,16 +55,52 @@ open SkillsManager.xcodeproj
5555

5656
## Architecture
5757

58-
Pure local architecture — no backend, works offline (except sandbox LLM calls). Reads and writes agent config files directly, uses Git to sync with skill marketplaces.
58+
Pure local architecture — no backend, works offline except for network-backed features like Discover detail loading and sandbox LLM calls. Reads and writes agent config files directly and uses local Git history for version management.
5959

6060
Built with SwiftUI + Swift 6, SwiftData, macOS 14+.
6161

62+
## Terminal UI
63+
64+
The repository also includes a terminal UI in `tui/`.
65+
66+
Current status:
67+
- **Blessed TUI:** complete for the current scope and treated as the primary terminal implementation
68+
- **Ink TUI:** historical backup/reference only, no longer the target runtime
69+
70+
Official CLI command:
71+
72+
```bash
73+
cd tui
74+
npm exec skills-manager
75+
```
76+
77+
For a global command, run once inside `tui/`:
78+
79+
```bash
80+
npm link
81+
```
82+
83+
Then launch from anywhere with:
84+
85+
```bash
86+
skills-manager
87+
```
88+
89+
The Blessed TUI currently supports:
90+
- three-panel keyboard-first navigation
91+
- discover via [skills.sh](https://skills.sh/)
92+
- install / uninstall / star
93+
- source-file opening and discover source-page opening
94+
- search, detail overlays, full refresh
95+
- version history is temporarily disabled
96+
- local / plugin differentiation, including Codex plugin cache and Pi package resources
97+
6298
## Roadmap
6399

64-
- [ ] Auto-update detection for marketplace skills
100+
- [ ] Auto-update detection for discovered skills
65101
- [ ] Skill conflict detection across agents
66102
- [ ] Export / import skill sets
67-
- [ ] Team sync via shared marketplace fork
103+
- [ ] Team sync via shared skills repository
68104

69105
## Contributing
70106

SkillsManager.xcodeproj/project.pbxproj

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,21 @@
1111
0947139B78E3F9D9857F730A /* GitService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 666D8599524120C18BABB3FF /* GitService.swift */; };
1212
1237553ECFA7488940CF0ECB /* SkillsManager/Adapters/AgentRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6B333DD3AFEB259FA109238 /* SkillsManager/Adapters/AgentRegistry.swift */; };
1313
164C12203FA1D8638EB72C2F /* SandboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6BD0C5D68F6CEB4FE4C14CD /* SandboxView.swift */; };
14-
19C98540FC00FBE609E1FC97 /* MarketplacePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 554254E6F25F55D3E78B7ADB /* MarketplacePlugin.swift */; };
14+
19C98540FC00FBE609E1FC97 /* DiscoverSkill.swift in Sources */ = {isa = PBXBuildFile; fileRef = 554254E6F25F55D3E78B7ADB /* DiscoverSkill.swift */; };
15+
1A8A1001C14F65A1A0000001 /* DiscoverInstallActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A8A1001C14F65A1A0000002 /* DiscoverInstallActivity.swift */; };
16+
1B8A1001C14F65A1A0000001 /* DiscoverInstallToAgentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B8A1001C14F65A1A0000002 /* DiscoverInstallToAgentView.swift */; };
17+
1C8A1001C14F65A1A0000001 /* DiscoverDirectoryCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C8A1001C14F65A1A0000002 /* DiscoverDirectoryCategory.swift */; };
1518
2532A8AD74AC05FE72D82528 /* VersionHistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50069145DEE4F107B789596A /* VersionHistoryView.swift */; };
19+
3A8A1001C14F65A1A0000001 /* ExecutableLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8A1001C14F65A1A0000002 /* ExecutableLocator.swift */; };
1620
407EA88DE8026BC89CCF9A18 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E21F4876DF0FEEB0B346AFA /* AppSettings.swift */; };
1721
5407109449B814A8F2658F23 /* SkillListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 072BA9F86FFF3B545CCC344D /* SkillListView.swift */; };
1822
5427BC541444486E97ABECF1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F161109A29CF7DCE1257393 /* ContentView.swift */; };
1923
59BA0662EF7FD224605372CF /* AgentAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D71148B256CA7E29C4034F4 /* AgentAdapter.swift */; };
2024
617909719D9F4BFBB8B9BCDD /* UniversalAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7B86A2FA72346719A0DF343 /* UniversalAdapter.swift */; };
2125
67760A8B31C1AA2B7744DF2D /* FileWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2C11FFC9FF1183A71189CA /* FileWatcher.swift */; };
2226
6968AC6A50D44EE422856B92 /* SkillsManager/Services/SymlinkInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34850DA72E29812DF60C423C /* SkillsManager/Services/SymlinkInstaller.swift */; };
23-
6D64F0E2F5774C92ABF36D01 /* MarketplaceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA73E4EF79EC927A3418CA4F /* MarketplaceService.swift */; };
27+
6D64F0E2F5774C92ABF36D01 /* SkillsDirectoryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA73E4EF79EC927A3418CA4F /* SkillsDirectoryService.swift */; };
28+
6E8A1001C14F65A1A0000001 /* NetworkSessionFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E8A1001C14F65A1A0000002 /* NetworkSessionFactory.swift */; };
2429
71ECCDC7A46C7E521247C2EF /* SandboxSlot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5274AE0EE82A46941B29B3F1 /* SandboxSlot.swift */; };
2530
758801517F2A42748B68DD20 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF81F058B00F5224DD515ED1 /* AppDelegate.swift */; };
2631
7970AB614D3D0C641C9FB0EC /* SidebarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFF0465C82F147C7332064AC /* SidebarView.swift */; };
@@ -48,6 +53,7 @@
4853
0525175ED2964BB6E2E0B1B0 /* SkillsManagerApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkillsManagerApp.swift; sourceTree = "<group>"; };
4954
072BA9F86FFF3B545CCC344D /* SkillListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkillListView.swift; sourceTree = "<group>"; };
5055
2F161109A29CF7DCE1257393 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
56+
3A8A1001C14F65A1A0000002 /* ExecutableLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExecutableLocator.swift; sourceTree = "<group>"; };
5157
34850DA72E29812DF60C423C /* SkillsManager/Services/SymlinkInstaller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkillsManager/Services/SymlinkInstaller.swift; sourceTree = SOURCE_ROOT; };
5258
3BE38B49272B1AA0A1752A87 /* ClaudeCodeAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClaudeCodeAdapter.swift; sourceTree = "<group>"; };
5359
42BA7574CDF65767B64E1FEE /* DiscoverView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoverView.swift; sourceTree = "<group>"; };
@@ -58,17 +64,21 @@
5864
52C4A4957C14CE0EEBB00D79 /* ProjectScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectScanner.swift; sourceTree = "<group>"; };
5965
541163F5E744A67FA92AE00F /* SkillStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkillStore.swift; sourceTree = "<group>"; };
6066
5427F0708C634AC8F5F4B080 /* Skill.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Skill.swift; sourceTree = "<group>"; };
61-
554254E6F25F55D3E78B7ADB /* MarketplacePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketplacePlugin.swift; sourceTree = "<group>"; };
67+
554254E6F25F55D3E78B7ADB /* DiscoverSkill.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoverSkill.swift; sourceTree = "<group>"; };
68+
1A8A1001C14F65A1A0000002 /* DiscoverInstallActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoverInstallActivity.swift; sourceTree = "<group>"; };
69+
1B8A1001C14F65A1A0000002 /* DiscoverInstallToAgentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoverInstallToAgentView.swift; sourceTree = "<group>"; };
70+
1C8A1001C14F65A1A0000002 /* DiscoverDirectoryCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoverDirectoryCategory.swift; sourceTree = "<group>"; };
6271
57E8B78AFE5E90D7D1B044AC /* SidebarFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarFilter.swift; sourceTree = "<group>"; };
6372
666D8599524120C18BABB3FF /* GitService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitService.swift; sourceTree = "<group>"; };
73+
6E8A1001C14F65A1A0000002 /* NetworkSessionFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkSessionFactory.swift; sourceTree = "<group>"; };
6474
71E86521947227FAD14E43AA /* Skills Manager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Skills Manager.app"; sourceTree = BUILT_PRODUCTS_DIR; };
6575
7C2C11FFC9FF1183A71189CA /* FileWatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileWatcher.swift; sourceTree = "<group>"; };
6676
7DBBBF8B70FCF8E665BA164F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
6777
7E21F4876DF0FEEB0B346AFA /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = "<group>"; };
6878
8B204889413D1B5B1DE273D2 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
6979
8D71148B256CA7E29C4034F4 /* AgentAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AgentAdapter.swift; sourceTree = "<group>"; };
7080
9FE67140FC42B93008948827 /* SkillFormatConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkillFormatConverter.swift; sourceTree = "<group>"; };
71-
AA73E4EF79EC927A3418CA4F /* MarketplaceService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketplaceService.swift; sourceTree = "<group>"; };
81+
AA73E4EF79EC927A3418CA4F /* SkillsDirectoryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkillsDirectoryService.swift; sourceTree = "<group>"; };
7282
AFF0465C82F147C7332064AC /* SidebarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarView.swift; sourceTree = "<group>"; };
7383
B2C3D4E5F678901234ABCDEF /* InstallToAgentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallToAgentView.swift; sourceTree = "<group>"; };
7484
C12D2413CCD83C7EC8E03F9C /* Skill+Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Skill+Mock.swift"; sourceTree = "<group>"; };
@@ -100,6 +110,7 @@
100110
children = (
101111
2F161109A29CF7DCE1257393 /* ContentView.swift */,
102112
42BA7574CDF65767B64E1FEE /* DiscoverView.swift */,
113+
1B8A1001C14F65A1A0000002 /* DiscoverInstallToAgentView.swift */,
103114
AA1234567890ABCDEF123456 /* FlowLayout.swift */,
104115
F000347C95927A1B1EE9704F /* ProjectSkillsView.swift */,
105116
F6BD0C5D68F6CEB4FE4C14CD /* SandboxView.swift */,
@@ -118,7 +129,9 @@
118129
children = (
119130
8D71148B256CA7E29C4034F4 /* AgentAdapter.swift */,
120131
7E21F4876DF0FEEB0B346AFA /* AppSettings.swift */,
121-
554254E6F25F55D3E78B7ADB /* MarketplacePlugin.swift */,
132+
1A8A1001C14F65A1A0000002 /* DiscoverInstallActivity.swift */,
133+
1C8A1001C14F65A1A0000002 /* DiscoverDirectoryCategory.swift */,
134+
554254E6F25F55D3E78B7ADB /* DiscoverSkill.swift */,
122135
5274AE0EE82A46941B29B3F1 /* SandboxSlot.swift */,
123136
57E8B78AFE5E90D7D1B044AC /* SidebarFilter.swift */,
124137
5427F0708C634AC8F5F4B080 /* Skill.swift */,
@@ -181,10 +194,12 @@
181194
isa = PBXGroup;
182195
children = (
183196
7C2C11FFC9FF1183A71189CA /* FileWatcher.swift */,
197+
3A8A1001C14F65A1A0000002 /* ExecutableLocator.swift */,
184198
666D8599524120C18BABB3FF /* GitService.swift */,
185199
CC4AC87ED906F4D954E16850 /* InstallService.swift */,
186200
522C4FF85D5865CEB9DEEF64 /* LLMService.swift */,
187-
AA73E4EF79EC927A3418CA4F /* MarketplaceService.swift */,
201+
6E8A1001C14F65A1A0000002 /* NetworkSessionFactory.swift */,
202+
AA73E4EF79EC927A3418CA4F /* SkillsDirectoryService.swift */,
188203
52C4A4957C14CE0EEBB00D79 /* ProjectScanner.swift */,
189204
9FE67140FC42B93008948827 /* SkillFormatConverter.swift */,
190205
E755FBEC77714122731E7A45 /* SkillParser.swift */,
@@ -277,13 +292,18 @@
277292
617909719D9F4BFBB8B9BCDD /* UniversalAdapter.swift in Sources */,
278293
5427BC541444486E97ABECF1 /* ContentView.swift in Sources */,
279294
7A8064994B4633978FA3E334 /* DiscoverView.swift in Sources */,
295+
1B8A1001C14F65A1A0000001 /* DiscoverInstallToAgentView.swift in Sources */,
280296
BB9876543210FEDCBA987654 /* FlowLayout.swift in Sources */,
281297
67760A8B31C1AA2B7744DF2D /* FileWatcher.swift in Sources */,
298+
3A8A1001C14F65A1A0000001 /* ExecutableLocator.swift in Sources */,
282299
0947139B78E3F9D9857F730A /* GitService.swift in Sources */,
283300
79C92DE48CAF4F5BBAEDF299 /* InstallService.swift in Sources */,
284301
96428207D0C4C159CC581D38 /* LLMService.swift in Sources */,
285-
19C98540FC00FBE609E1FC97 /* MarketplacePlugin.swift in Sources */,
286-
6D64F0E2F5774C92ABF36D01 /* MarketplaceService.swift in Sources */,
302+
1A8A1001C14F65A1A0000001 /* DiscoverInstallActivity.swift in Sources */,
303+
1C8A1001C14F65A1A0000001 /* DiscoverDirectoryCategory.swift in Sources */,
304+
19C98540FC00FBE609E1FC97 /* DiscoverSkill.swift in Sources */,
305+
6E8A1001C14F65A1A0000001 /* NetworkSessionFactory.swift in Sources */,
306+
6D64F0E2F5774C92ABF36D01 /* SkillsDirectoryService.swift in Sources */,
287307
7C0C9E9A97FA6E85F1819B7B /* ProjectScanner.swift in Sources */,
288308
F90897662904C11B2D9E1411 /* ProjectSkillsView.swift in Sources */,
289309
71ECCDC7A46C7E521247C2EF /* SandboxSlot.swift in Sources */,

0 commit comments

Comments
 (0)