Skip to content

Commit 75f045c

Browse files
committed
docs: add multi-platform accordion redesign spec
1 parent e074608 commit 75f045c

1 file changed

Lines changed: 244 additions & 0 deletions

File tree

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
# Configure AI Tools — Multi-Platform Redesign Spec
2+
3+
## Goal
4+
5+
Revise the accordion panel to support installing skills to multiple platforms simultaneously. Replace the single-select IDE tab control with a multi-select "Install for" platform checklist placed *below* the skills list. Add Universal (`.agents/skills/`) and Windsurf as install targets; retire the Cursor-specific `.cursor/rules/` path in favour of Universal.
6+
7+
---
8+
9+
## Platform Definitions
10+
11+
| ID | Display name | Skills path | Notes |
12+
|----|-------------|-------------|-------|
13+
| `universal` | Universal | `.agents/skills/{dirName}/SKILL.md` | Covers Cursor, Codex, Amp, Warp, Antigravity, Gemini CLI + more |
14+
| `claude-code` | Claude Code | `.claude/skills/{dirName}/SKILL.md` | |
15+
| `vscode-copilot` | VS Code (Copilot) | `.github/copilot-instructions.md` | Appends `## {name}` section |
16+
| `windsurf` | Windsurf | `.windsurf/skills/{dirName}/SKILL.md` | |
17+
18+
Cursor's old `.cursor/rules/{dirName}.mdc` install path is **retired** from the webview flow. The QuickPick command palette fallback may keep it for now but the accordion uses Universal for Cursor users.
19+
20+
### Universal sub-label
21+
22+
The `universal` platform row shows a muted sub-label: **"Cursor, Codex, Amp, Warp + more"** to make it obvious that checking this covers Cursor-based workflows.
23+
24+
---
25+
26+
## Panel Layout (Ready state)
27+
28+
```
29+
Skills
30+
────────────────────────────
31+
☑ cloudinary-docs installed
32+
☑ cloudinary-react partial
33+
☑ cloudinary-transforms —
34+
35+
Install for
36+
────────────────────────────
37+
☑ Universal
38+
Cursor, Codex, Amp, Warp + more
39+
☑ Claude Code
40+
☐ VS Code (Copilot)
41+
☐ Windsurf
42+
43+
MCP Servers
44+
────────────────────────────
45+
☐ Asset Management configured
46+
☑ MediaFlows —
47+
48+
[ Apply ]
49+
```
50+
51+
Skills checklist is above the platform selector. Platform selector is always visible (not collapsible).
52+
53+
---
54+
55+
## Skill Status Logic
56+
57+
Status is computed relative to the **currently checked platforms**:
58+
59+
| Condition | Label | Default checked? |
60+
|-----------|-------|-----------------|
61+
| Installed on **all** checked platforms | `installed` | No |
62+
| Installed on **some** checked platforms | `partial` | Yes (fills the gaps) |
63+
| Installed on **none** of the checked platforms | `` | Yes |
64+
65+
Status label is recomputed live whenever the user toggles a platform checkbox. No round-trip to the extension needed — all `installedByPlatform` data is cached in the client from the initial `aiToolsData` message.
66+
67+
---
68+
69+
## Default Platform Selection
70+
71+
On accordion open, the extension computes `activePlatforms` — the set of platforms that should be pre-checked:
72+
73+
1. **Detected IDE** → mapped to platform ID:
74+
- `detectEditor()` returns `"unknown"` or `"cursor"``universal`
75+
- `"claude-code"` / `"antigravity"``claude-code` … wait, antigravity → `universal`
76+
- Full mapping: `cursor``universal`, `windsurf``windsurf`, `vscode``vscode-copilot`, everything else (claude-code, unknown, antigravity) → `claude-code` for claude-code, `universal` for others
77+
78+
Simplified: `windsurf``windsurf`; `vscode``vscode-copilot`; `cursor` or `antigravity``universal`; default (claude-code, unknown) → `claude-code`.
79+
80+
2. **Already-installed platforms** → any platform where at least one skill dir is found on disk is also pre-checked (user has an existing setup there).
81+
82+
`activePlatforms` = union of detected-IDE platform + all platforms with existing installs.
83+
84+
---
85+
86+
## Data Flow
87+
88+
### Open accordion
89+
90+
Extension computes in parallel:
91+
- `fetchSkillList()` (cached after first open)
92+
- `readInstalledSkillDirNames(rootUri, platformId, skills)` for all 4 platforms
93+
- `readActivePlatforms(rootUri)` — checks which platform dirs exist on disk
94+
- `readConfiguredMcpServerKeys(rootUri, ...)`
95+
96+
Posts `aiToolsData`:
97+
98+
```json
99+
{
100+
"command": "aiToolsData",
101+
"skills": [
102+
{ "name": "cloudinary-docs", "dirName": "cloudinary-docs", "description": "..." }
103+
],
104+
"installedByPlatform": {
105+
"universal": ["cloudinary-docs"],
106+
"claude-code": ["cloudinary-docs"],
107+
"vscode-copilot": [],
108+
"windsurf": []
109+
},
110+
"activePlatforms": ["universal", "claude-code"],
111+
"mcpServers": [
112+
{ "key": "cloudinary-asset-mgmt", "label": "Asset Management", "description": "..." }
113+
],
114+
"configuredMcpKeys": ["cloudinary-asset-mgmt"]
115+
}
116+
```
117+
118+
Note: `detectedIde` is gone; replaced by `activePlatforms`.
119+
120+
### Apply
121+
122+
Webview posts:
123+
124+
```json
125+
{
126+
"command": "installAiTools",
127+
"skills": ["cloudinary-react"],
128+
"platforms": ["universal", "claude-code"],
129+
"mcpServers": ["mediaflows"]
130+
}
131+
```
132+
133+
Extension installs each skill to each platform in sequence. Progress posted per skill (one event covers all platforms for that skill — error if any platform fails):
134+
135+
```json
136+
{ "command": "aiToolsProgress", "item": "cloudinary-react", "status": "done" }
137+
{ "command": "aiToolsProgress", "item": "mediaflows", "status": "done" }
138+
```
139+
140+
Final result:
141+
142+
```json
143+
{ "command": "aiToolsResult", "errors": [] }
144+
```
145+
146+
---
147+
148+
## New / Changed Service Functions (`src/aiToolsService.ts`)
149+
150+
### New types
151+
152+
```typescript
153+
export type PlatformId = 'universal' | 'claude-code' | 'vscode-copilot' | 'windsurf';
154+
155+
export type PlatformDef = {
156+
id: PlatformId;
157+
label: string;
158+
sublabel?: string;
159+
};
160+
```
161+
162+
### New constant
163+
164+
```typescript
165+
export const PLATFORMS: PlatformDef[] = [
166+
{ id: 'universal', label: 'Universal', sublabel: 'Cursor, Codex, Amp, Warp + more' },
167+
{ id: 'claude-code', label: 'Claude Code' },
168+
{ id: 'vscode-copilot', label: 'VS Code (Copilot)' },
169+
{ id: 'windsurf', label: 'Windsurf' },
170+
];
171+
```
172+
173+
### New install functions
174+
175+
`installForUniversal(rootUri, skillName, content, createdFiles, errors)` — writes SKILL.md to `.agents/skills/{skillName}/SKILL.md`. Same structure as `installForClaudeCode` but with `.agents/skills/` prefix.
176+
177+
`installForWindsurf(rootUri, skillName, content, createdFiles, errors)` — writes SKILL.md to `.windsurf/skills/{skillName}/SKILL.md`. Same structure.
178+
179+
### Updated `readInstalledSkillDirNames`
180+
181+
Signature changes to accept `PlatformId` instead of `ideTargetLabel: string`:
182+
183+
```typescript
184+
export async function readInstalledSkillDirNames(
185+
rootUri: vscode.Uri,
186+
platform: PlatformId,
187+
skills: SkillInfo[]
188+
): Promise<Set<string>>
189+
```
190+
191+
Routing:
192+
- `universal`stat `.agents/skills/{dirName}/SKILL.md`
193+
- `claude-code`stat `.claude/skills/{dirName}/SKILL.md`
194+
- `vscode-copilot`read `.github/copilot-instructions.md`, check for `## {name}` sections
195+
- `windsurf`stat `.windsurf/skills/{dirName}/SKILL.md`
196+
197+
### New `detectActivePlatforms`
198+
199+
```typescript
200+
export async function detectActivePlatforms(
201+
rootUri: vscode.Uri
202+
): Promise<PlatformId[]>
203+
```
204+
205+
Checks for existence of each platform's skills directory (or instructions file). Returns IDs of platforms that have any install present. Used to pre-check platforms that have existing setups.
206+
207+
### `detectEditorPlatform`
208+
209+
```typescript
210+
export function detectEditorPlatform(): PlatformId
211+
```
212+
213+
Maps `detectEditor()` result to a `PlatformId`:
214+
- `windsurf``windsurf`
215+
- `vscode``vscode-copilot`
216+
- `cursor` | `antigravity``universal`
217+
- everything else (claude-code, unknown) → `claude-code`
218+
219+
---
220+
221+
## File Map
222+
223+
| Action | File | What changes |
224+
|--------|------|-------------|
225+
| Modify | `src/aiToolsService.ts` | Add `PlatformId`, `PlatformDef`, `PLATFORMS`; add `installForUniversal`, `installForWindsurf`; update `readInstalledSkillDirNames` to use `PlatformId`; add `detectActivePlatforms`, `detectEditorPlatform` |
226+
| Modify | `src/webview/homescreenView.ts` | Replace IDE segmented control HTML with platform checkbox section; update `_handleAiToolsExpanded` (new message shape); update `_handleInstallAiTools` (accepts `platforms[]`) |
227+
| Modify | `src/webview/client/homescreen.ts` | Replace IDE selector UI with platform multi-select; update skill status logic; update Apply payload |
228+
229+
---
230+
231+
## Styling
232+
233+
- Platform section uses the same `.hs-ai-item` / `.hs-ai-cb` pattern as skills and MCP rows
234+
- Sub-label ("Cursor, Codex, Amp…") uses `--vscode-descriptionForeground`, font-size ~9.5px, displayed on its own line below the platform name
235+
- No segmented control / pill animation neededplain checkboxes
236+
- Platform section header uses `.hs-ai-section-head` pattern
237+
238+
---
239+
240+
## Out of Scope
241+
242+
- `installForCursor` (old `.cursor/rules/` path) is kept in `aiToolsService.ts` for the QuickPick command palette flow but is not used by the accordion
243+
- No per-platform progress ticks in the done state (one tick per skill covers all platforms)
244+
- No "install globally" (to `~/.claude/skills` etc.) — workspace-level only

0 commit comments

Comments
 (0)