@orderful/droid 0.36.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -118
- package/.claude-plugin/plugin.json +49 -0
- package/AGENTS.md +4 -0
- package/CHANGELOG.md +59 -0
- package/README.md +53 -39
- package/dist/bin/droid.js +525 -212
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/tui/components/PlatformBadges.d.ts.map +1 -1
- package/dist/commands/tui/components/SettingsDetails.d.ts.map +1 -1
- package/dist/commands/tui/hooks/useAppUpdate.d.ts.map +1 -1
- package/dist/commands/tui/views/SetupScreen.d.ts.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/index.js +345 -186
- package/dist/lib/agents.d.ts +4 -2
- package/dist/lib/agents.d.ts.map +1 -1
- package/dist/lib/migrations.d.ts.map +1 -1
- package/dist/lib/platform.codex.d.ts +36 -0
- package/dist/lib/platform.codex.d.ts.map +1 -0
- package/dist/lib/platforms.d.ts +30 -24
- package/dist/lib/platforms.d.ts.map +1 -1
- package/dist/lib/skills.d.ts +4 -2
- package/dist/lib/skills.d.ts.map +1 -1
- package/dist/lib/types.d.ts +2 -1
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/tools/brain/.claude-plugin/plugin.json +8 -1
- package/dist/tools/brain/TOOL.yaml +1 -1
- package/dist/tools/brain/commands/brain.md +3 -2
- package/dist/tools/brain/skills/brain/SKILL.md +41 -10
- package/dist/tools/brain/skills/brain/references/templates.md +61 -0
- package/dist/tools/brain/skills/brain/references/workflows.md +78 -9
- package/dist/tools/brain/skills/brain-obsidian/SKILL.md +2 -0
- package/dist/tools/coach/.claude-plugin/plugin.json +6 -0
- package/dist/tools/coach/skills/coach/SKILL.md +3 -0
- package/dist/tools/code-review/.claude-plugin/plugin.json +12 -0
- package/dist/tools/code-review/skills/code-review/SKILL.md +2 -0
- package/dist/tools/codex/.claude-plugin/plugin.json +9 -0
- package/dist/tools/codex/skills/codex/SKILL.md +3 -0
- package/dist/tools/comments/.claude-plugin/plugin.json +7 -1
- package/dist/tools/comments/TOOL.yaml +1 -1
- package/dist/tools/comments/skills/comments/SKILL.md +11 -4
- package/dist/tools/droid/.claude-plugin/plugin.json +8 -1
- package/dist/tools/droid/TOOL.yaml +4 -2
- package/dist/tools/droid/commands/setup.md +125 -0
- package/dist/tools/droid/skills/droid/SKILL.md +117 -2
- package/dist/tools/plan/.claude-plugin/plugin.json +7 -1
- package/dist/tools/plan/TOOL.yaml +1 -1
- package/dist/tools/plan/commands/plan.md +3 -1
- package/dist/tools/plan/skills/plan/SKILL.md +23 -9
- package/dist/tools/plan/skills/plan/references/workflows.md +57 -20
- package/dist/tools/project/.claude-plugin/plugin.json +6 -0
- package/dist/tools/project/skills/project/SKILL.md +3 -0
- package/dist/tools/tech-design/.claude-plugin/plugin.json +7 -1
- package/dist/tools/tech-design/TOOL.yaml +1 -1
- package/dist/tools/tech-design/commands/tech-design.md +2 -0
- package/dist/tools/tech-design/skills/tech-design/SKILL.md +45 -13
- package/dist/tools/tech-design/skills/tech-design/references/publish.md +272 -216
- package/dist/tools/tech-design/skills/tech-design/references/start.md +50 -20
- package/dist/tools/wrapup/.claude-plugin/plugin.json +6 -0
- package/dist/tools/wrapup/skills/wrapup/SKILL.md +2 -0
- package/package.json +1 -1
- package/scripts/build-plugins.ts +154 -6
- package/src/bin/droid.ts +16 -0
- package/src/commands/setup.ts +107 -2
- package/src/commands/tui/components/PlatformBadges.tsx +1 -0
- package/src/commands/tui/components/SettingsDetails.tsx +1 -0
- package/src/commands/tui/hooks/useAppUpdate.ts +21 -1
- package/src/commands/tui/views/SetupScreen.tsx +10 -1
- package/src/commands/update.ts +21 -1
- package/src/lib/agents.ts +13 -2
- package/src/lib/migrations.ts +81 -9
- package/src/lib/platform.codex.ts +131 -0
- package/src/lib/platforms.ts +127 -6
- package/src/lib/skills.ts +53 -6
- package/src/lib/types.ts +1 -0
- package/src/tools/brain/.claude-plugin/plugin.json +8 -1
- package/src/tools/brain/TOOL.yaml +1 -1
- package/src/tools/brain/commands/brain.md +3 -2
- package/src/tools/brain/skills/brain/SKILL.md +41 -10
- package/src/tools/brain/skills/brain/references/templates.md +61 -0
- package/src/tools/brain/skills/brain/references/workflows.md +78 -9
- package/src/tools/brain/skills/brain-obsidian/SKILL.md +2 -0
- package/src/tools/coach/.claude-plugin/plugin.json +6 -0
- package/src/tools/coach/skills/coach/SKILL.md +3 -0
- package/src/tools/code-review/.claude-plugin/plugin.json +12 -0
- package/src/tools/code-review/skills/code-review/SKILL.md +2 -0
- package/src/tools/codex/.claude-plugin/plugin.json +9 -0
- package/src/tools/codex/skills/codex/SKILL.md +3 -0
- package/src/tools/comments/.claude-plugin/plugin.json +7 -1
- package/src/tools/comments/TOOL.yaml +1 -1
- package/src/tools/comments/skills/comments/SKILL.md +11 -4
- package/src/tools/droid/.claude-plugin/plugin.json +8 -1
- package/src/tools/droid/TOOL.yaml +4 -2
- package/src/tools/droid/commands/setup.md +125 -0
- package/src/tools/droid/skills/droid/SKILL.md +117 -2
- package/src/tools/plan/.claude-plugin/plugin.json +7 -1
- package/src/tools/plan/TOOL.yaml +1 -1
- package/src/tools/plan/commands/plan.md +3 -1
- package/src/tools/plan/skills/plan/SKILL.md +23 -9
- package/src/tools/plan/skills/plan/references/workflows.md +57 -20
- package/src/tools/project/.claude-plugin/plugin.json +6 -0
- package/src/tools/project/skills/project/SKILL.md +3 -0
- package/src/tools/tech-design/.claude-plugin/plugin.json +7 -1
- package/src/tools/tech-design/TOOL.yaml +1 -1
- package/src/tools/tech-design/commands/tech-design.md +2 -0
- package/src/tools/tech-design/skills/tech-design/SKILL.md +45 -13
- package/src/tools/tech-design/skills/tech-design/references/publish.md +272 -216
- package/src/tools/tech-design/skills/tech-design/references/start.md +50 -20
- package/src/tools/wrapup/.claude-plugin/plugin.json +6 -0
- package/src/tools/wrapup/skills/wrapup/SKILL.md +2 -0
|
@@ -50,14 +50,40 @@ The codex skill will:
|
|
|
50
50
|
- UI/UX considerations (from DESIGN.md if present)
|
|
51
51
|
- Key constraints or requirements
|
|
52
52
|
|
|
53
|
-
### 3. Create
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
### 3. Create Unified Tech Design Folder
|
|
54
|
+
|
|
55
|
+
Create a single folder to hold all tech design artifacts:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Get brain config
|
|
59
|
+
brain_config=$(droid config --get tools.brain)
|
|
60
|
+
brain_dir=$(echo "$brain_config" | grep -o '"brain_dir": *"[^"]*"' | cut -d'"' -f4)
|
|
61
|
+
inbox_folder=$(echo "$brain_config" | grep -o '"inbox_folder": *"[^"]*"' | cut -d'"' -f4)
|
|
62
|
+
|
|
63
|
+
# Determine base path
|
|
64
|
+
if [ -n "$inbox_folder" ]; then
|
|
65
|
+
base_path="$inbox_folder"
|
|
66
|
+
else
|
|
67
|
+
base_path="$brain_dir"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Create folder structure
|
|
71
|
+
design_folder="$base_path/tech-designs/{project}"
|
|
72
|
+
mkdir -p "$design_folder"
|
|
73
|
+
```
|
|
56
74
|
|
|
75
|
+
**Folder structure:**
|
|
57
76
|
```
|
|
58
|
-
/
|
|
77
|
+
{brain_dir}/{inbox?}/tech-designs/{project}/
|
|
78
|
+
├── research.md
|
|
79
|
+
├── thought-doc.md
|
|
80
|
+
└── [diagrams, artifacts as needed]
|
|
59
81
|
```
|
|
60
82
|
|
|
83
|
+
### 4. Create Research Doc
|
|
84
|
+
|
|
85
|
+
Create `research.md` in the design folder:
|
|
86
|
+
|
|
61
87
|
**Research doc template:**
|
|
62
88
|
|
|
63
89
|
```markdown
|
|
@@ -81,7 +107,7 @@ Research for tech design: {brief description from PRD}
|
|
|
81
107
|
|
|
82
108
|
## Codebase Discoveries
|
|
83
109
|
|
|
84
|
-
{This section populated in step
|
|
110
|
+
{This section populated in step 5}
|
|
85
111
|
|
|
86
112
|
## Key Findings
|
|
87
113
|
|
|
@@ -174,13 +200,9 @@ Update the "Codebase Discoveries" section with specific discoveries:
|
|
|
174
200
|
- Testing: {e.g., unit test setup, integration test patterns}
|
|
175
201
|
```
|
|
176
202
|
|
|
177
|
-
### 5. Create Thought Doc
|
|
178
|
-
|
|
179
|
-
Use the brain skill to create the planning document:
|
|
203
|
+
### 5. Create Thought Doc
|
|
180
204
|
|
|
181
|
-
|
|
182
|
-
/brain plan tech-design-{project}
|
|
183
|
-
```
|
|
205
|
+
Create `thought-doc.md` in the same folder:
|
|
184
206
|
|
|
185
207
|
**Thought doc template:**
|
|
186
208
|
|
|
@@ -191,7 +213,7 @@ Use the brain skill to create the planning document:
|
|
|
191
213
|
**Status:** exploring
|
|
192
214
|
**Created:** {current date}
|
|
193
215
|
**PRD:** [[codex:projects/{project}/PRD]]
|
|
194
|
-
**Research:** [[
|
|
216
|
+
**Research:** [[research|Research doc in same folder]]
|
|
195
217
|
|
|
196
218
|
Tech design for {project}.
|
|
197
219
|
|
|
@@ -203,7 +225,7 @@ Tech design for {project}.
|
|
|
203
225
|
- Who it's for and why it matters
|
|
204
226
|
- Key constraints or requirements
|
|
205
227
|
|
|
206
|
-
See research
|
|
228
|
+
See research.md for codebase context and discovered patterns.
|
|
207
229
|
|
|
208
230
|
## Proposal
|
|
209
231
|
|
|
@@ -214,15 +236,18 @@ See research doc for codebase context and discovered patterns.
|
|
|
214
236
|
{What we don't know yet - to be explored}
|
|
215
237
|
```
|
|
216
238
|
|
|
217
|
-
Set thought
|
|
239
|
+
Set thought-doc.md path for session tracking (active design).
|
|
218
240
|
|
|
219
241
|
### 6. Provide Links to User
|
|
220
242
|
|
|
221
|
-
After creating both docs, give the user the
|
|
243
|
+
After creating both docs, give the user the folder path:
|
|
222
244
|
|
|
223
245
|
```
|
|
224
|
-
✓
|
|
225
|
-
|
|
246
|
+
✓ Tech design folder created: {design_folder}/
|
|
247
|
+
|
|
248
|
+
Files:
|
|
249
|
+
• research.md - Codex context and codebase discoveries
|
|
250
|
+
• thought-doc.md - Design iteration workspace (active)
|
|
226
251
|
|
|
227
252
|
Research doc includes:
|
|
228
253
|
• Codex project context from {project}
|
|
@@ -230,6 +255,7 @@ Research doc includes:
|
|
|
230
255
|
• Technical stack notes
|
|
231
256
|
|
|
232
257
|
You can continue working on this with:
|
|
258
|
+
• /tech-design search {project} - Resume this design later
|
|
233
259
|
• /tech-design draft - Auto-generate sections from research
|
|
234
260
|
• /tech-design think {topic} - Explore specific ideas
|
|
235
261
|
• /brain add {text} - Quick additions to active doc
|
|
@@ -243,7 +269,7 @@ What would you like to do next?
|
|
|
243
269
|
- **Brain not configured:** "Brain skill not configured. Please run `/brain` to set up your brain directory first."
|
|
244
270
|
- **Codex not configured:** "Codex skill not configured. Please run `/codex` to set up your codex repository first."
|
|
245
271
|
- **PRD missing:** Offer to create via `/codex new {project}` or continue without context
|
|
246
|
-
- **
|
|
272
|
+
- **Folder already exists:** "Tech design for '{project}' already exists at {path}. Resume with `/tech-design search {project}` or create with different name?"
|
|
247
273
|
- **Codebase exploration fails:** Gracefully note what couldn't be found, continue with what's available
|
|
248
274
|
|
|
249
275
|
## Example Output
|
|
@@ -257,8 +283,11 @@ Research findings:
|
|
|
257
283
|
🔗 Identified 5 integration points (validation, storage, API)
|
|
258
284
|
📦 Dependencies: 2 already available, 1 to add
|
|
259
285
|
|
|
260
|
-
✓
|
|
261
|
-
|
|
286
|
+
✓ Tech design folder created: {brain_dir}/0-Inbox/tech-designs/transaction-templates/
|
|
287
|
+
|
|
288
|
+
Files:
|
|
289
|
+
• research.md - Codex context and codebase discoveries
|
|
290
|
+
• thought-doc.md - Design iteration workspace (active)
|
|
262
291
|
|
|
263
292
|
Research doc includes:
|
|
264
293
|
• Codex project context from transaction-templates
|
|
@@ -266,6 +295,7 @@ Research doc includes:
|
|
|
266
295
|
• Technical stack notes
|
|
267
296
|
|
|
268
297
|
You can continue working on this with:
|
|
298
|
+
• /tech-design search transaction-templates - Resume this design later
|
|
269
299
|
• /tech-design draft - Auto-generate sections from research
|
|
270
300
|
• /tech-design think {topic} - Explore specific ideas
|
|
271
301
|
• /brain add {text} - Quick additions to active doc
|
|
@@ -18,6 +18,8 @@ Wrapup has no configuration of its own. It reads config from other installed too
|
|
|
18
18
|
|
|
19
19
|
If these tools aren't configured, wrapup skips those artifacts and focuses on git state and conversation summary.
|
|
20
20
|
|
|
21
|
+
**Overrides:** This skill supports user-defined overrides. See `/droid` skill § Skill Overrides.
|
|
22
|
+
|
|
21
23
|
## Context Lifeboat Pattern
|
|
22
24
|
|
|
23
25
|
This skill runs at the END of sessions when context pressure is highest.
|
package/package.json
CHANGED
package/scripts/build-plugins.ts
CHANGED
|
@@ -15,9 +15,14 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { mkdirSync, writeFileSync, existsSync, readdirSync, readFileSync } from 'fs';
|
|
18
|
-
import { join } from 'path';
|
|
18
|
+
import { join, basename } from 'path';
|
|
19
19
|
import { parse as parseYaml } from 'yaml';
|
|
20
20
|
|
|
21
|
+
interface CommandInclude {
|
|
22
|
+
name: string;
|
|
23
|
+
is_alias?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
interface ToolManifest {
|
|
22
27
|
name: string;
|
|
23
28
|
description: string;
|
|
@@ -26,7 +31,7 @@ interface ToolManifest {
|
|
|
26
31
|
system?: boolean;
|
|
27
32
|
includes: {
|
|
28
33
|
skills: Array<{ name: string; required: boolean; description?: string }>;
|
|
29
|
-
commands:
|
|
34
|
+
commands: CommandInclude[];
|
|
30
35
|
agents: string[];
|
|
31
36
|
};
|
|
32
37
|
dependencies?: string[];
|
|
@@ -44,6 +49,9 @@ interface PluginJson {
|
|
|
44
49
|
repository?: string;
|
|
45
50
|
license?: string;
|
|
46
51
|
keywords?: string[];
|
|
52
|
+
skills?: string[];
|
|
53
|
+
commands?: string[];
|
|
54
|
+
agents?: string[];
|
|
47
55
|
}
|
|
48
56
|
|
|
49
57
|
interface MarketplacePlugin {
|
|
@@ -111,11 +119,122 @@ function getToolDirs(): string[] {
|
|
|
111
119
|
return entries
|
|
112
120
|
.filter((e) => e.isDirectory())
|
|
113
121
|
.map((e) => join(TOOLS_DIR, e.name))
|
|
114
|
-
.filter((dir) => existsSync(join(dir, 'TOOL.yaml')))
|
|
122
|
+
.filter((dir) => existsSync(join(dir, 'TOOL.yaml')))
|
|
123
|
+
.sort(); // Ensure deterministic order across platforms
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get relative paths to skill files for plugin.json.
|
|
128
|
+
* Paths are relative to the tool's .claude-plugin directory.
|
|
129
|
+
*/
|
|
130
|
+
function getSkillPaths(manifest: ToolManifest): string[] {
|
|
131
|
+
const skills = manifest.includes.skills ?? [];
|
|
132
|
+
return skills.map((skill) => `./skills/${skill.name}/SKILL.md`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get relative paths to command files for plugin.json.
|
|
137
|
+
* Excludes alias commands since they're just pointers to the main command.
|
|
138
|
+
*/
|
|
139
|
+
function getCommandPaths(manifest: ToolManifest): string[] {
|
|
140
|
+
const commands = manifest.includes.commands ?? [];
|
|
141
|
+
return commands
|
|
142
|
+
.filter((cmd) => !cmd.is_alias)
|
|
143
|
+
.map((cmd) => `./commands/${cmd.name}.md`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get relative paths to agent files for plugin.json.
|
|
148
|
+
*/
|
|
149
|
+
function getAgentPaths(manifest: ToolManifest): string[] {
|
|
150
|
+
const agents = manifest.includes.agents ?? [];
|
|
151
|
+
return agents.map((agent) => `./agents/${agent}.md`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get repo-root-relative paths to skill files for combined plugin.json.
|
|
156
|
+
*/
|
|
157
|
+
function getSkillPathsFromRoot(manifest: ToolManifest, toolDir: string): string[] {
|
|
158
|
+
const skills = manifest.includes.skills ?? [];
|
|
159
|
+
return skills.map((skill) => `./${toolDir}/skills/${skill.name}/SKILL.md`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get repo-root-relative paths to command files for combined plugin.json.
|
|
164
|
+
* Excludes alias commands since they're just pointers to the main command.
|
|
165
|
+
*/
|
|
166
|
+
function getCommandPathsFromRoot(manifest: ToolManifest, toolDir: string): string[] {
|
|
167
|
+
const commands = manifest.includes.commands ?? [];
|
|
168
|
+
return commands
|
|
169
|
+
.filter((cmd) => !cmd.is_alias)
|
|
170
|
+
.map((cmd) => `./${toolDir}/commands/${cmd.name}.md`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get repo-root-relative paths to agent files for combined plugin.json.
|
|
175
|
+
*/
|
|
176
|
+
function getAgentPathsFromRoot(manifest: ToolManifest, toolDir: string): string[] {
|
|
177
|
+
const agents = manifest.includes.agents ?? [];
|
|
178
|
+
return agents.map((agent) => `./${toolDir}/agents/${agent}.md`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get the droid tool version for the combined plugin.json.
|
|
183
|
+
*/
|
|
184
|
+
function getDroidVersion(toolDirs: string[]): string {
|
|
185
|
+
const droidDir = toolDirs.find((dir) => basename(dir) === 'droid');
|
|
186
|
+
if (droidDir) {
|
|
187
|
+
const manifest = loadToolManifest(droidDir);
|
|
188
|
+
if (manifest) return manifest.version;
|
|
189
|
+
}
|
|
190
|
+
return '0.0.0';
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Build combined plugin.json at repo root for marketplace installations.
|
|
195
|
+
* Aggregates all tools' content with repo-root-relative paths.
|
|
196
|
+
*/
|
|
197
|
+
function buildCombinedPlugin(toolDirs: string[]): void {
|
|
198
|
+
const allSkills: string[] = [];
|
|
199
|
+
const allCommands: string[] = [];
|
|
200
|
+
const allAgents: string[] = [];
|
|
201
|
+
|
|
202
|
+
for (const toolDir of toolDirs) {
|
|
203
|
+
const manifest = loadToolManifest(toolDir);
|
|
204
|
+
if (!manifest) continue;
|
|
205
|
+
|
|
206
|
+
allSkills.push(...getSkillPathsFromRoot(manifest, toolDir));
|
|
207
|
+
allCommands.push(...getCommandPathsFromRoot(manifest, toolDir));
|
|
208
|
+
allAgents.push(...getAgentPathsFromRoot(manifest, toolDir));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Ensure directory exists
|
|
212
|
+
const marketplaceDir = '.claude-plugin';
|
|
213
|
+
mkdirSync(marketplaceDir, { recursive: true });
|
|
214
|
+
|
|
215
|
+
const combinedPlugin: PluginJson = {
|
|
216
|
+
name: 'droid',
|
|
217
|
+
version: getDroidVersion(toolDirs),
|
|
218
|
+
description: 'AI-powered development tools for Claude Code',
|
|
219
|
+
author: AUTHOR,
|
|
220
|
+
repository: REPO,
|
|
221
|
+
license: 'MIT',
|
|
222
|
+
keywords: ['droid', 'ai', 'tools'],
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
if (allSkills.length > 0) combinedPlugin.skills = allSkills;
|
|
226
|
+
if (allCommands.length > 0) combinedPlugin.commands = allCommands;
|
|
227
|
+
if (allAgents.length > 0) combinedPlugin.agents = allAgents;
|
|
228
|
+
|
|
229
|
+
writeFileSync(
|
|
230
|
+
join(marketplaceDir, 'plugin.json'),
|
|
231
|
+
JSON.stringify(combinedPlugin, null, 2) + '\n'
|
|
232
|
+
);
|
|
233
|
+
console.log(`Combined plugin.json created at .claude-plugin/plugin.json`);
|
|
115
234
|
}
|
|
116
235
|
|
|
117
236
|
function createPluginJson(manifest: ToolManifest, pluginName: string): PluginJson {
|
|
118
|
-
|
|
237
|
+
const json: PluginJson = {
|
|
119
238
|
name: pluginName,
|
|
120
239
|
version: manifest.version,
|
|
121
240
|
description: manifest.description,
|
|
@@ -124,6 +243,26 @@ function createPluginJson(manifest: ToolManifest, pluginName: string): PluginJso
|
|
|
124
243
|
license: 'MIT',
|
|
125
244
|
keywords: [...new Set(['droid', 'ai', manifest.name])],
|
|
126
245
|
};
|
|
246
|
+
|
|
247
|
+
// Add skills if present
|
|
248
|
+
const skills = getSkillPaths(manifest);
|
|
249
|
+
if (skills.length > 0) {
|
|
250
|
+
json.skills = skills;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Add commands if present
|
|
254
|
+
const commands = getCommandPaths(manifest);
|
|
255
|
+
if (commands.length > 0) {
|
|
256
|
+
json.commands = commands;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Add agents if present
|
|
260
|
+
const agents = getAgentPaths(manifest);
|
|
261
|
+
if (agents.length > 0) {
|
|
262
|
+
json.agents = agents;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return json;
|
|
127
266
|
}
|
|
128
267
|
|
|
129
268
|
function buildPluginManifest(toolDir: string): MarketplacePlugin | null {
|
|
@@ -165,15 +304,21 @@ function buildMarketplace(plugins: MarketplacePlugin[]): void {
|
|
|
165
304
|
const marketplaceDir = '.claude-plugin';
|
|
166
305
|
mkdirSync(marketplaceDir, { recursive: true });
|
|
167
306
|
|
|
307
|
+
// Only advertise "droid" in marketplace - Claude Code ignores the path field
|
|
308
|
+
// and always reads from repo root, so per-tool entries would fail with name
|
|
309
|
+
// mismatch errors. Users install "droid" to get all tools.
|
|
310
|
+
// Per-tool plugin.json files still exist for direct installs via --path.
|
|
311
|
+
const marketplacePlugins = plugins.filter((p) => p.name === 'droid');
|
|
312
|
+
|
|
168
313
|
const marketplace: MarketplaceJson = {
|
|
169
314
|
name: 'droid',
|
|
170
315
|
description: 'AI-powered development tools for Claude Code',
|
|
171
316
|
owner: AUTHOR,
|
|
172
|
-
plugins:
|
|
317
|
+
plugins: marketplacePlugins,
|
|
173
318
|
};
|
|
174
319
|
|
|
175
320
|
writeFileSync(join(marketplaceDir, 'marketplace.json'), JSON.stringify(marketplace, null, 2) + '\n');
|
|
176
|
-
console.log(`\nMarketplace manifest created at .claude-plugin/marketplace.json with ${
|
|
321
|
+
console.log(`\nMarketplace manifest created at .claude-plugin/marketplace.json with ${marketplacePlugins.length} plugin(s)`);
|
|
177
322
|
}
|
|
178
323
|
|
|
179
324
|
function main(): void {
|
|
@@ -193,6 +338,9 @@ function main(): void {
|
|
|
193
338
|
// Build marketplace manifest
|
|
194
339
|
buildMarketplace(plugins);
|
|
195
340
|
|
|
341
|
+
// Build combined plugin.json for marketplace installations
|
|
342
|
+
buildCombinedPlugin(toolDirs);
|
|
343
|
+
|
|
196
344
|
console.log('\nPlugin manifest generation complete!');
|
|
197
345
|
console.log(`\nTo test locally:`);
|
|
198
346
|
console.log(` /plugin marketplace add ${process.cwd()}`);
|
package/src/bin/droid.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { program } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
4
5
|
import { setupCommand } from '../commands/setup';
|
|
5
6
|
import { configCommand } from '../commands/config';
|
|
6
7
|
import { skillsCommand } from '../commands/skills';
|
|
@@ -16,6 +17,8 @@ import {
|
|
|
16
17
|
reposGetCommand,
|
|
17
18
|
} from '../commands/repos';
|
|
18
19
|
import { getVersion } from '../lib/version';
|
|
20
|
+
import { loadConfig, saveConfig, configExists } from '../lib/config';
|
|
21
|
+
import { syncNewPlatforms } from '../lib/platforms';
|
|
19
22
|
|
|
20
23
|
const version = getVersion();
|
|
21
24
|
|
|
@@ -106,6 +109,19 @@ program
|
|
|
106
109
|
.allowUnknownOption()
|
|
107
110
|
.action(execCommand);
|
|
108
111
|
|
|
112
|
+
// Sync new platforms before running any command
|
|
113
|
+
// This ensures that newly installed platforms (e.g., Codex) get all existing tools
|
|
114
|
+
if (configExists()) {
|
|
115
|
+
const config = loadConfig();
|
|
116
|
+
const newPlatforms = syncNewPlatforms(config);
|
|
117
|
+
|
|
118
|
+
if (newPlatforms.length > 0) {
|
|
119
|
+
console.log(chalk.green(`✓ Detected new platform(s): ${newPlatforms.join(', ')}`));
|
|
120
|
+
console.log(chalk.gray(' Synced installed tools to new platform(s)\n'));
|
|
121
|
+
saveConfig(config);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
109
125
|
// If no command provided, launch TUI
|
|
110
126
|
if (process.argv.length === 2) {
|
|
111
127
|
tuiCommand();
|
package/src/commands/setup.ts
CHANGED
|
@@ -4,10 +4,11 @@ import { execSync } from 'child_process';
|
|
|
4
4
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
5
5
|
import { join } from 'path';
|
|
6
6
|
import { homedir } from 'os';
|
|
7
|
-
import { loadConfig, saveConfig, configExists } from '../lib/config';
|
|
7
|
+
import { loadConfig, saveConfig, configExists, getConfigDir } from '../lib/config';
|
|
8
8
|
import { getBundledSkills } from '../lib/skills';
|
|
9
9
|
import { Platform, BuiltInOutput, type DroidConfig, type OutputPreference } from '../lib/types';
|
|
10
|
-
import { detectAllPlatforms } from '../lib/platforms';
|
|
10
|
+
import { detectAllPlatforms, createCodexSymlink } from '../lib/platforms';
|
|
11
|
+
import { getPlatformTools } from '../lib/types';
|
|
11
12
|
|
|
12
13
|
// Re-export for external use
|
|
13
14
|
export { detectAllPlatforms, getActivePlatforms } from '../lib/platforms';
|
|
@@ -16,6 +17,7 @@ const PLATFORM_LABELS: Record<Platform, string> = {
|
|
|
16
17
|
[Platform.ClaudeCode]: 'Claude Code',
|
|
17
18
|
[Platform.Cursor]: 'Cursor',
|
|
18
19
|
[Platform.OpenCode]: 'OpenCode',
|
|
20
|
+
[Platform.OpenAICodex]: 'Codex',
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
/**
|
|
@@ -29,6 +31,89 @@ const DROID_PERMISSIONS = [
|
|
|
29
31
|
'Grep(~/.droid/**)',
|
|
30
32
|
];
|
|
31
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Template content for skill overrides
|
|
36
|
+
*/
|
|
37
|
+
const SKILL_OVERRIDES_TEMPLATE = `---
|
|
38
|
+
overrides: []
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
# Skill Override Template
|
|
42
|
+
|
|
43
|
+
Copy this file to \`{skill_name}.md\` to override a skill's behaviour.
|
|
44
|
+
|
|
45
|
+
## Format
|
|
46
|
+
|
|
47
|
+
\`\`\`yaml
|
|
48
|
+
---
|
|
49
|
+
overrides: [command1, command2]
|
|
50
|
+
---
|
|
51
|
+
\`\`\`
|
|
52
|
+
|
|
53
|
+
Then add sections for each command you're overriding:
|
|
54
|
+
|
|
55
|
+
\`\`\`markdown
|
|
56
|
+
## {command1}
|
|
57
|
+
|
|
58
|
+
Your custom instructions for this command...
|
|
59
|
+
\`\`\`
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Example: Override brain search with qmd
|
|
64
|
+
|
|
65
|
+
Create \`brain.md\` with:
|
|
66
|
+
|
|
67
|
+
\`\`\`yaml
|
|
68
|
+
---
|
|
69
|
+
overrides: [search]
|
|
70
|
+
---
|
|
71
|
+
\`\`\`
|
|
72
|
+
|
|
73
|
+
## search
|
|
74
|
+
|
|
75
|
+
Use qmd for semantic search:
|
|
76
|
+
|
|
77
|
+
1. Run \`qmd query "{query}" -c brain -n 10 --files\`
|
|
78
|
+
2. Parse CSV output, extract filepath (field 3)
|
|
79
|
+
3. If qmd fails, fall back to Glob
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Registration
|
|
84
|
+
|
|
85
|
+
After creating an override file, ask droid to register it:
|
|
86
|
+
|
|
87
|
+
> "Register my brain override"
|
|
88
|
+
|
|
89
|
+
Droid will:
|
|
90
|
+
1. Parse the frontmatter to find which commands are overridden
|
|
91
|
+
2. Update config.yaml with override metadata
|
|
92
|
+
3. The skill will use your override on next invocation
|
|
93
|
+
`;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Create skill_overrides directory with template
|
|
97
|
+
*/
|
|
98
|
+
function createSkillOverridesDir(): { created: boolean; alreadyExists: boolean } {
|
|
99
|
+
const overridesDir = join(getConfigDir(), 'skill_overrides');
|
|
100
|
+
const templatePath = join(overridesDir, '_template.md');
|
|
101
|
+
|
|
102
|
+
// Check if directory already exists with template
|
|
103
|
+
if (existsSync(templatePath)) {
|
|
104
|
+
return { created: false, alreadyExists: true };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Create directory if needed
|
|
108
|
+
if (!existsSync(overridesDir)) {
|
|
109
|
+
mkdirSync(overridesDir, { recursive: true });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Write template
|
|
113
|
+
writeFileSync(templatePath, SKILL_OVERRIDES_TEMPLATE, 'utf-8');
|
|
114
|
+
return { created: true, alreadyExists: false };
|
|
115
|
+
}
|
|
116
|
+
|
|
32
117
|
/**
|
|
33
118
|
* Try to get git username
|
|
34
119
|
*/
|
|
@@ -261,6 +346,14 @@ export async function setupCommand(): Promise<void> {
|
|
|
261
346
|
|
|
262
347
|
console.log(chalk.green('\n✓ Config saved to ~/.droid/config.yaml'));
|
|
263
348
|
|
|
349
|
+
// Create skill_overrides directory with template
|
|
350
|
+
const { created: overridesCreated, alreadyExists: overridesExist } = createSkillOverridesDir();
|
|
351
|
+
if (overridesCreated) {
|
|
352
|
+
console.log(chalk.green('✓ Created ~/.droid/skill_overrides/ with template'));
|
|
353
|
+
} else if (overridesExist) {
|
|
354
|
+
console.log(chalk.gray(' Skill overrides directory already exists'));
|
|
355
|
+
}
|
|
356
|
+
|
|
264
357
|
// Configure permissions for ALL active platforms
|
|
265
358
|
for (const platform of activePlatforms) {
|
|
266
359
|
const { added, alreadyPresent, error } = configurePlatformPermissions(platform);
|
|
@@ -277,6 +370,18 @@ export async function setupCommand(): Promise<void> {
|
|
|
277
370
|
}
|
|
278
371
|
}
|
|
279
372
|
|
|
373
|
+
// Create Codex symlinks for tracked tools only (not all skills in directory)
|
|
374
|
+
if (activePlatforms.includes(Platform.OpenAICodex)) {
|
|
375
|
+
const trackedTools = getPlatformTools(config);
|
|
376
|
+
const toolNames = Object.keys(trackedTools);
|
|
377
|
+
if (toolNames.length > 0) {
|
|
378
|
+
for (const skillName of toolNames) {
|
|
379
|
+
createCodexSymlink(skillName);
|
|
380
|
+
}
|
|
381
|
+
console.log(chalk.green('✓ Created Codex symlinks for installed tools'));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
280
385
|
// Show summary if multiple platforms
|
|
281
386
|
if (activePlatforms.length > 1) {
|
|
282
387
|
console.log(chalk.green(`\n✓ Will install to ${activePlatforms.length} platforms: ${activePlatforms.map(p => PLATFORM_LABELS[p]).join(', ')}`));
|
|
@@ -5,6 +5,7 @@ const PLATFORM_INFO: Record<Platform, { color: string; label: string }> = {
|
|
|
5
5
|
[Platform.ClaudeCode]: { color: '#da7756', label: 'Claude' },
|
|
6
6
|
[Platform.Cursor]: { color: '#22d3ee', label: 'Cursor' },
|
|
7
7
|
[Platform.OpenCode]: { color: '#4ade80', label: 'OpenCode' },
|
|
8
|
+
[Platform.OpenAICodex]: { color: '#10b981', label: 'Codex' },
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
export function PlatformBadges({
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { useState, useMemo } from 'react';
|
|
2
2
|
import { useApp } from 'ink';
|
|
3
|
+
import { spawnSync } from 'child_process';
|
|
3
4
|
import { getUpdateInfo, runUpdate, type UpdateInfo } from '../../../lib/version';
|
|
4
|
-
import { setAutoUpdateConfig } from '../../../lib/config';
|
|
5
|
+
import { setAutoUpdateConfig, getAutoUpdateConfig } from '../../../lib/config';
|
|
5
6
|
|
|
6
7
|
export interface UseAppUpdateOptions {
|
|
7
8
|
onUpdateSuccess: (message: string) => void;
|
|
@@ -31,6 +32,24 @@ export function useAppUpdate({ onUpdateSuccess, onUpdateFailure }: UseAppUpdateO
|
|
|
31
32
|
const blue = '\x1b[38;2;99;102;241m'; // #6366f1
|
|
32
33
|
const dim = '\x1b[38;2;106;106;106m';
|
|
33
34
|
const reset = '\x1b[0m';
|
|
35
|
+
|
|
36
|
+
// Check if auto-update tools is enabled
|
|
37
|
+
const autoUpdateConfig = getAutoUpdateConfig();
|
|
38
|
+
let toolStatus = `${blue}App updated.${reset}`;
|
|
39
|
+
|
|
40
|
+
if (autoUpdateConfig.tools) {
|
|
41
|
+
// Spawn NEW binary to sync tools (has new bundled manifests)
|
|
42
|
+
console.log('\nSyncing tools...');
|
|
43
|
+
const toolResult = spawnSync('droid', ['update', '--tools'], {
|
|
44
|
+
stdio: 'inherit',
|
|
45
|
+
timeout: 60000, // 60s timeout for tool sync
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const toolsSynced = !toolResult.error && toolResult.status === 0;
|
|
49
|
+
toolStatus = toolsSynced
|
|
50
|
+
? `${blue}App and tools updated.${reset}`
|
|
51
|
+
: `${blue}App updated.${reset} Tools sync incomplete - run ${blue}droid update --tools${reset} to retry.`;
|
|
52
|
+
}
|
|
34
53
|
const message = `
|
|
35
54
|
${dim}────────────────────────────────────────────────────────${reset}
|
|
36
55
|
|
|
@@ -38,6 +57,7 @@ ${dim}────────────────────────
|
|
|
38
57
|
${dim}║${reset} ${blue}●${reset} ${blue}●${reset} ${dim}║${reset} ${blue}"It's quite possible this system${reset}
|
|
39
58
|
${dim}╚═╦═╦═╝${reset} ${blue}is now fully operational."${reset}
|
|
40
59
|
|
|
60
|
+
${toolStatus}
|
|
41
61
|
Run ${blue}droid${reset} to start the new version.
|
|
42
62
|
|
|
43
63
|
${dim}────────────────────────────────────────────────────────${reset}
|
|
@@ -3,9 +3,10 @@ import TextInput from 'ink-text-input';
|
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import { colors } from '../constants';
|
|
5
5
|
import type { SetupStep } from '../types';
|
|
6
|
-
import { Platform, BuiltInOutput, type DroidConfig } from '../../../lib/types';
|
|
6
|
+
import { Platform, BuiltInOutput, type DroidConfig, getPlatformTools } from '../../../lib/types';
|
|
7
7
|
import { loadConfig, saveConfig, getAutoUpdateConfig, setAutoUpdateConfig } from '../../../lib/config';
|
|
8
8
|
import { configurePlatformPermissions } from '../../setup';
|
|
9
|
+
import { createCodexSymlink } from '../../../lib/platforms';
|
|
9
10
|
|
|
10
11
|
export interface SetupScreenProps {
|
|
11
12
|
onComplete: () => void;
|
|
@@ -18,6 +19,7 @@ const PLATFORM_LABELS: Record<Platform, string> = {
|
|
|
18
19
|
[Platform.ClaudeCode]: 'Claude Code',
|
|
19
20
|
[Platform.Cursor]: 'Cursor',
|
|
20
21
|
[Platform.OpenCode]: 'OpenCode',
|
|
22
|
+
[Platform.OpenAICodex]: 'Codex',
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
export function SetupScreen({ onComplete, onSkip, initialConfig, detectedPlatforms }: SetupScreenProps) {
|
|
@@ -94,6 +96,13 @@ export function SetupScreen({ onComplete, onSkip, initialConfig, detectedPlatfor
|
|
|
94
96
|
for (const platform of detectedPlatforms) {
|
|
95
97
|
configurePlatformPermissions(platform);
|
|
96
98
|
}
|
|
99
|
+
// Create Codex symlinks for tracked tools only (not all skills in directory)
|
|
100
|
+
if (detectedPlatforms.includes(Platform.OpenAICodex)) {
|
|
101
|
+
const trackedTools = getPlatformTools(config);
|
|
102
|
+
for (const skillName of Object.keys(trackedTools)) {
|
|
103
|
+
createCodexSymlink(skillName);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
97
106
|
onComplete();
|
|
98
107
|
}
|
|
99
108
|
}
|