@orderful/droid 0.10.1 → 0.10.3
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/CHANGELOG.md +22 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +3 -1
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +3 -5
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +3 -1
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/tui.d.ts.map +1 -1
- package/dist/commands/tui.js +38 -41
- package/dist/commands/tui.js.map +1 -1
- package/dist/skills/brain/SKILL.md +41 -17
- package/dist/skills/brain/commands/brain.md +1 -0
- package/dist/skills/brain/commands/scratchpad.md +1 -0
- package/dist/skills/brain/references/metadata.md +14 -13
- package/dist/skills/brain/references/naming.md +12 -10
- package/dist/skills/brain/references/templates.md +5 -5
- package/dist/skills/brain/references/workflows.md +48 -24
- package/dist/skills/comments/SKILL.md +21 -13
- package/dist/skills/comments/SKILL.yaml +1 -1
- package/package.json +1 -1
- package/src/commands/install.ts +5 -1
- package/src/commands/setup.ts +3 -5
- package/src/commands/skills.ts +5 -1
- package/src/commands/tui.tsx +37 -65
- package/src/skills/brain/SKILL.md +41 -17
- package/src/skills/brain/commands/brain.md +1 -0
- package/src/skills/brain/commands/scratchpad.md +1 -0
- package/src/skills/brain/references/metadata.md +14 -13
- package/src/skills/brain/references/naming.md +12 -10
- package/src/skills/brain/references/templates.md +5 -5
- package/src/skills/brain/references/workflows.md +48 -24
- package/src/skills/comments/SKILL.md +21 -13
- package/src/skills/comments/SKILL.yaml +1 -1
|
@@ -8,14 +8,18 @@ Detailed procedures for each brain operation.
|
|
|
8
8
|
|
|
9
9
|
**Steps:**
|
|
10
10
|
|
|
11
|
-
1. **Read config first**
|
|
12
|
-
- Read `~/.droid/skills/brain/overrides.yaml`
|
|
13
|
-
-
|
|
11
|
+
1. **Read config first (MANDATORY)**
|
|
12
|
+
- Use the Read tool on `~/.droid/skills/brain/overrides.yaml`
|
|
13
|
+
- If file exists and contains `brain_dir:`, use that path
|
|
14
|
+
- Only use defaults if the file doesn't exist or `brain_dir` is not set
|
|
15
|
+
- **Do NOT skip this step or assume defaults**
|
|
14
16
|
|
|
15
17
|
2. **Search for matches**
|
|
18
|
+
|
|
16
19
|
```
|
|
17
20
|
Glob: {brain_dir}/**/*{topic}*.md
|
|
18
21
|
```
|
|
22
|
+
|
|
19
23
|
Fuzzy match the topic against doc filenames
|
|
20
24
|
|
|
21
25
|
3. **Handle results:**
|
|
@@ -37,10 +41,12 @@ Detailed procedures for each brain operation.
|
|
|
37
41
|
|
|
38
42
|
**Steps:**
|
|
39
43
|
|
|
40
|
-
1. **Read config first**
|
|
41
|
-
- Read `~/.droid/skills/brain/overrides.yaml`
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
+
1. **Read config first (MANDATORY)**
|
|
45
|
+
- Use the Read tool on `~/.droid/skills/brain/overrides.yaml`
|
|
46
|
+
- If file exists and contains `brain_dir:`, use that path
|
|
47
|
+
- Only use defaults if the file doesn't exist or `brain_dir` is not set
|
|
48
|
+
- Also check for `inbox_folder` setting
|
|
49
|
+
- **Do NOT skip this step or assume defaults**
|
|
44
50
|
|
|
45
51
|
2. **Generate filename** using naming conventions (see `naming.md`):
|
|
46
52
|
- Format: `{type}-{topic-slug}.md`
|
|
@@ -59,11 +65,16 @@ Detailed procedures for each brain operation.
|
|
|
59
65
|
- Any constraints or requirements mentioned?
|
|
60
66
|
- Related work or prior decisions?
|
|
61
67
|
|
|
62
|
-
7. **
|
|
68
|
+
7. **Add placeholder comments** for sections needing user input:
|
|
69
|
+
- Read user's mention from `~/.droid/config.yaml` → `user_mention`
|
|
70
|
+
- Use `> @{user_mention}` for placeholders (e.g., `> @fry - Please provide requirements`)
|
|
71
|
+
- **CRITICAL:** NEVER use `@droid` - that's for user-to-AI comments, not AI-to-user
|
|
63
72
|
|
|
64
|
-
8. **
|
|
73
|
+
8. **Write the doc** with template structure and initial context
|
|
65
74
|
|
|
66
|
-
9. **
|
|
75
|
+
9. **Set as active doc**
|
|
76
|
+
|
|
77
|
+
10. **Confirm creation** and summarize what was captured
|
|
67
78
|
|
|
68
79
|
## Notes
|
|
69
80
|
|
|
@@ -71,10 +82,12 @@ Detailed procedures for each brain operation.
|
|
|
71
82
|
|
|
72
83
|
**Steps:**
|
|
73
84
|
|
|
74
|
-
1. **Read config first**
|
|
75
|
-
- Read `~/.droid/skills/brain/overrides.yaml`
|
|
76
|
-
-
|
|
77
|
-
-
|
|
85
|
+
1. **Read config first (MANDATORY)**
|
|
86
|
+
- Use the Read tool on `~/.droid/skills/brain/overrides.yaml`
|
|
87
|
+
- If file exists and contains `brain_dir:`, use that path
|
|
88
|
+
- Only use defaults if the file doesn't exist or `brain_dir` is not set
|
|
89
|
+
- Also check for `inbox_folder` setting
|
|
90
|
+
- **Do NOT skip this step or assume defaults**
|
|
78
91
|
|
|
79
92
|
2. **Generate filename:**
|
|
80
93
|
- Format: `note-{date}-{slug}.md` where date is `YYYYMMDD`
|
|
@@ -105,8 +118,8 @@ Detailed procedures for each brain operation.
|
|
|
105
118
|
2. **Read current content** of active doc
|
|
106
119
|
|
|
107
120
|
3. **Append new section:**
|
|
108
|
-
```markdown
|
|
109
121
|
|
|
122
|
+
```markdown
|
|
110
123
|
---
|
|
111
124
|
|
|
112
125
|
## Update ({date})
|
|
@@ -133,18 +146,25 @@ Detailed procedures for each brain operation.
|
|
|
133
146
|
|
|
134
147
|
2. **Read active doc**
|
|
135
148
|
|
|
136
|
-
3. **
|
|
149
|
+
3. **Check preserve_comments setting:**
|
|
150
|
+
- Read `~/.droid/skills/comments/overrides.yaml` if it exists
|
|
151
|
+
- Look for `preserve_comments` (default: `true`)
|
|
152
|
+
|
|
153
|
+
4. **Find all `> @droid` comments**
|
|
137
154
|
- Pattern: Lines starting with `> @droid` (blockquote with mention)
|
|
138
155
|
|
|
139
|
-
|
|
156
|
+
5. **For each comment:**
|
|
140
157
|
- Show the comment and surrounding context
|
|
141
158
|
- Address the question/request
|
|
142
|
-
- Add response as `> @{user_mention}`
|
|
143
|
-
-
|
|
159
|
+
- Add response as blockquote with user's mention: `> @{user_mention} Your response here`
|
|
160
|
+
- Example: `> @fry Yes, the index covers that query pattern.`
|
|
161
|
+
- **CRITICAL:** NEVER use `@droid` in your responses. Use `@{user_mention}` from config (e.g., `@fry`)
|
|
162
|
+
- **CRITICAL:** Always include the `>` prefix to maintain blockquote formatting
|
|
163
|
+
- **CRITICAL:** If `preserve_comments: true`, keep the original `@droid` comment and add your response below it. Do NOT remove the original comment.
|
|
144
164
|
|
|
145
|
-
|
|
165
|
+
6. **Update the doc** with responses
|
|
146
166
|
|
|
147
|
-
|
|
167
|
+
7. **Summarize** what was addressed
|
|
148
168
|
|
|
149
169
|
## Finalizing
|
|
150
170
|
|
|
@@ -177,14 +197,18 @@ Detailed procedures for each brain operation.
|
|
|
177
197
|
|
|
178
198
|
**Steps:**
|
|
179
199
|
|
|
180
|
-
1. **Read config first**
|
|
181
|
-
- Read `~/.droid/skills/brain/overrides.yaml`
|
|
182
|
-
-
|
|
200
|
+
1. **Read config first (MANDATORY)**
|
|
201
|
+
- Use the Read tool on `~/.droid/skills/brain/overrides.yaml`
|
|
202
|
+
- If file exists and contains `brain_dir:`, use that path
|
|
203
|
+
- Only use defaults if the file doesn't exist or `brain_dir` is not set
|
|
204
|
+
- **Do NOT skip this step or assume defaults**
|
|
183
205
|
|
|
184
206
|
2. **Find recent docs:**
|
|
207
|
+
|
|
185
208
|
```
|
|
186
209
|
Glob: {brain_dir}/**/*.md
|
|
187
210
|
```
|
|
211
|
+
|
|
188
212
|
Sort by modification time, limit to 10-15
|
|
189
213
|
|
|
190
214
|
3. **Present list** with:
|
|
@@ -31,21 +31,23 @@ The AI will respond with `> @{user_mention}` (configured in droid setup, e.g., `
|
|
|
31
31
|
**CRITICAL: The `@mention` is who you're talking TO, not who is speaking.**
|
|
32
32
|
|
|
33
33
|
Think of it like addressing someone in conversation:
|
|
34
|
+
|
|
34
35
|
- "Hey @droid, what do you think?" → User talking TO the AI
|
|
35
36
|
- "Good point @fry, here's my take..." → AI talking TO the user
|
|
36
37
|
|
|
37
38
|
| When you see... | Who wrote it | Who it's addressed to |
|
|
38
|
-
|
|
39
|
-
| `> @droid ...` | User | AI (droid)
|
|
40
|
-
| `> @fry ...` | AI | User (fry)
|
|
39
|
+
| --------------- | ------------ | --------------------- |
|
|
40
|
+
| `> @droid ...` | User | AI (droid) |
|
|
41
|
+
| `> @fry ...` | AI | User (fry) |
|
|
41
42
|
|
|
42
43
|
**Examples:**
|
|
44
|
+
|
|
43
45
|
```markdown
|
|
44
|
-
> @droid Can you explain this function?
|
|
46
|
+
> @droid Can you explain this function? ← User asking AI
|
|
45
47
|
> @fry This function calculates the hash... ← AI responding to user
|
|
46
48
|
|
|
47
|
-
> @droid Should we refactor this?
|
|
48
|
-
> @fry Yes, I'd suggest extracting...
|
|
49
|
+
> @droid Should we refactor this? ← User asking AI
|
|
50
|
+
> @fry Yes, I'd suggest extracting... ← AI responding to user
|
|
49
51
|
```
|
|
50
52
|
|
|
51
53
|
**Never flip this.** When responding to a `@droid` comment, always use `@{user}` (e.g., `@fry`) because you're addressing the user, not yourself.
|
|
@@ -76,13 +78,19 @@ When you find a `@droid` marker:
|
|
|
76
78
|
## Behavior
|
|
77
79
|
|
|
78
80
|
### On `/comments check`:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
|
|
82
|
+
1. **Read config first:** Check `~/.droid/skills/comments/overrides.yaml` for `preserve_comments` setting (default: `true`)
|
|
83
|
+
2. Search for `> @droid` (and any configured `ai_mentions`) in the specified scope
|
|
84
|
+
3. If there's a `git diff`, check those files first for relevant context
|
|
85
|
+
4. For each comment, determine intent:
|
|
86
|
+
- **Action request** ("do X", "add Y", "fix Z") → Execute the action
|
|
87
|
+
- **Question** ("what do you think", "should we") → Respond with `> @{user_mention}`
|
|
88
|
+
5. **Handle original comment based on `preserve_comments`:**
|
|
89
|
+
- If `preserve_comments: true` → Keep the original `@droid` comment (add response below it)
|
|
90
|
+
- If `preserve_comments: false` → Remove the original comment after addressing
|
|
84
91
|
|
|
85
92
|
### On `/comments cleanup`:
|
|
93
|
+
|
|
86
94
|
1. Find AI tag and `> @{user_mention}` pairs where conversation appears resolved
|
|
87
95
|
2. Remove both markers
|
|
88
96
|
3. Output a summary of what was discussed/decided
|
|
@@ -98,8 +106,8 @@ user_mention: "@fry"
|
|
|
98
106
|
# Additional AI mentions to recognize (e.g., if you're used to @claude)
|
|
99
107
|
ai_mentions: "@claude"
|
|
100
108
|
|
|
101
|
-
# Keep comments after addressing them (default:
|
|
102
|
-
preserve_comments:
|
|
109
|
+
# Keep comments after addressing them (default: true)
|
|
110
|
+
preserve_comments: true
|
|
103
111
|
```
|
|
104
112
|
|
|
105
113
|
## File Type Support
|
package/package.json
CHANGED
package/src/commands/install.ts
CHANGED
|
@@ -34,7 +34,11 @@ export async function installCommand(skillName: string): Promise<void> {
|
|
|
34
34
|
// Check if skill has configurable options
|
|
35
35
|
const manifest = loadSkillManifest(join(getBundledSkillsDir(), skillName));
|
|
36
36
|
if (manifest?.config_schema && Object.keys(manifest.config_schema).length > 0) {
|
|
37
|
-
|
|
37
|
+
// If any config option lacks a default, go straight to config (it's required)
|
|
38
|
+
const hasRequiredConfig = Object.values(manifest.config_schema).some(
|
|
39
|
+
(option) => option.default === undefined
|
|
40
|
+
);
|
|
41
|
+
await promptForSkillConfig(skillName, manifest.config_schema, !hasRequiredConfig);
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
// Show next steps
|
package/src/commands/setup.ts
CHANGED
|
@@ -240,11 +240,9 @@ export async function setupCommand(): Promise<void> {
|
|
|
240
240
|
name: 'user_mention',
|
|
241
241
|
message: 'What @mention should be used for you?',
|
|
242
242
|
default: '@user',
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
return true;
|
|
243
|
+
filter: (input: string) => {
|
|
244
|
+
// Auto-add @ prefix if missing
|
|
245
|
+
return input.startsWith('@') ? input : `@${input}`;
|
|
248
246
|
},
|
|
249
247
|
},
|
|
250
248
|
{
|
package/src/commands/skills.ts
CHANGED
|
@@ -127,7 +127,11 @@ export async function skillsCommand(): Promise<void> {
|
|
|
127
127
|
// Prompt for config if skill has options
|
|
128
128
|
const manifest = loadSkillManifest(join(getBundledSkillsDir(), skill.name));
|
|
129
129
|
if (manifest?.config_schema && Object.keys(manifest.config_schema).length > 0) {
|
|
130
|
-
|
|
130
|
+
// If any config option lacks a default, go straight to config (it's required)
|
|
131
|
+
const hasRequiredConfig = Object.values(manifest.config_schema).some(
|
|
132
|
+
(option) => option.default === undefined
|
|
133
|
+
);
|
|
134
|
+
await promptForSkillConfig(skill.name, manifest.config_schema, !hasRequiredConfig);
|
|
131
135
|
}
|
|
132
136
|
} else {
|
|
133
137
|
console.log(chalk.red(`\n✗ ${result.message}`));
|
package/src/commands/tui.tsx
CHANGED
|
@@ -23,7 +23,7 @@ import { getRandomQuote } from '../lib/quotes.js';
|
|
|
23
23
|
|
|
24
24
|
type Tab = 'skills' | 'commands' | 'agents' | 'settings';
|
|
25
25
|
type View = 'welcome' | 'setup' | 'menu' | 'detail' | 'configure' | 'readme';
|
|
26
|
-
type SetupStep = 'ai_tool' | 'user_mention' | '
|
|
26
|
+
type SetupStep = 'ai_tool' | 'user_mention' | 'confirm';
|
|
27
27
|
|
|
28
28
|
const colors = {
|
|
29
29
|
primary: '#6366f1',
|
|
@@ -101,20 +101,28 @@ function getCommandsFromSkills(): Command[] {
|
|
|
101
101
|
return commands;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
function
|
|
104
|
+
function detectInstalledAITools(): Set<AITool> {
|
|
105
|
+
const installed = new Set<AITool>();
|
|
105
106
|
try {
|
|
106
107
|
execSync('claude --version', { stdio: 'ignore' });
|
|
107
|
-
|
|
108
|
+
installed.add(AITool.ClaudeCode);
|
|
108
109
|
} catch {
|
|
109
110
|
// Claude Code not found
|
|
110
111
|
}
|
|
111
112
|
try {
|
|
112
113
|
execSync('opencode --version', { stdio: 'ignore' });
|
|
113
|
-
|
|
114
|
+
installed.add(AITool.OpenCode);
|
|
114
115
|
} catch {
|
|
115
116
|
// OpenCode not found
|
|
116
117
|
}
|
|
117
|
-
return
|
|
118
|
+
return installed;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function getDefaultAITool(): AITool {
|
|
122
|
+
const installed = detectInstalledAITools();
|
|
123
|
+
if (installed.has(AITool.ClaudeCode)) return AITool.ClaudeCode;
|
|
124
|
+
if (installed.has(AITool.OpenCode)) return AITool.OpenCode;
|
|
125
|
+
return AITool.ClaudeCode;
|
|
118
126
|
}
|
|
119
127
|
|
|
120
128
|
function getOutputOptions(): Array<{ label: string; value: OutputPreference }> {
|
|
@@ -320,33 +328,29 @@ interface SetupScreenProps {
|
|
|
320
328
|
function SetupScreen({ onComplete, onSkip, initialConfig }: SetupScreenProps) {
|
|
321
329
|
const [step, setStep] = useState<SetupStep>('ai_tool');
|
|
322
330
|
const [aiTool, setAITool] = useState<AITool>(
|
|
323
|
-
initialConfig?.ai_tool ||
|
|
331
|
+
initialConfig?.ai_tool || getDefaultAITool()
|
|
324
332
|
);
|
|
325
333
|
const [userMention, setUserMention] = useState(initialConfig?.user_mention || '@user');
|
|
326
|
-
const [outputPreference, setOutputPreference] = useState<OutputPreference>(
|
|
327
|
-
initialConfig?.output_preference || BuiltInOutput.Terminal
|
|
328
|
-
);
|
|
329
334
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
330
335
|
const [error, setError] = useState<string | null>(null);
|
|
331
336
|
|
|
337
|
+
// Cache detection results once on mount (avoids re-running execSync on every render)
|
|
338
|
+
const installedTools = useMemo(() => detectInstalledAITools(), []);
|
|
332
339
|
const aiToolOptions = useMemo(() => [
|
|
333
340
|
{ label: 'Claude Code', value: AITool.ClaudeCode },
|
|
334
341
|
{ label: 'OpenCode', value: AITool.OpenCode },
|
|
335
342
|
], []);
|
|
336
|
-
const outputOptions = useMemo(() => getOutputOptions(), []);
|
|
337
343
|
|
|
338
|
-
const steps: SetupStep[] = ['ai_tool', 'user_mention', '
|
|
344
|
+
const steps: SetupStep[] = ['ai_tool', 'user_mention', 'confirm'];
|
|
339
345
|
const stepIndex = steps.indexOf(step);
|
|
340
346
|
const totalSteps = steps.length - 1; // Don't count confirm as a step
|
|
341
347
|
|
|
342
348
|
const handleUserMentionSubmit = () => {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
}
|
|
349
|
+
// Auto-add @ prefix if missing
|
|
350
|
+
const mention = userMention.startsWith('@') ? userMention : `@${userMention}`;
|
|
351
|
+
setUserMention(mention);
|
|
347
352
|
setError(null);
|
|
348
|
-
setStep('
|
|
349
|
-
setSelectedIndex(0);
|
|
353
|
+
setStep('confirm');
|
|
350
354
|
};
|
|
351
355
|
|
|
352
356
|
// Handle escape during text input (only intercept escape, nothing else)
|
|
@@ -362,11 +366,8 @@ function SetupScreen({ onComplete, onSkip, initialConfig }: SetupScreenProps) {
|
|
|
362
366
|
if (key.escape) {
|
|
363
367
|
if (step === 'ai_tool') {
|
|
364
368
|
onSkip();
|
|
365
|
-
} else if (step === 'output_preference') {
|
|
366
|
-
setStep('user_mention');
|
|
367
369
|
} else if (step === 'confirm') {
|
|
368
|
-
setStep('
|
|
369
|
-
setSelectedIndex(0);
|
|
370
|
+
setStep('user_mention');
|
|
370
371
|
}
|
|
371
372
|
return;
|
|
372
373
|
}
|
|
@@ -378,20 +379,13 @@ function SetupScreen({ onComplete, onSkip, initialConfig }: SetupScreenProps) {
|
|
|
378
379
|
setAITool(aiToolOptions[selectedIndex].value);
|
|
379
380
|
setStep('user_mention');
|
|
380
381
|
}
|
|
381
|
-
} else if (step === 'output_preference') {
|
|
382
|
-
if (key.upArrow) setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
383
|
-
if (key.downArrow) setSelectedIndex((prev) => Math.min(outputOptions.length - 1, prev + 1));
|
|
384
|
-
if (key.return) {
|
|
385
|
-
setOutputPreference(outputOptions[selectedIndex].value);
|
|
386
|
-
setStep('confirm');
|
|
387
|
-
}
|
|
388
382
|
} else if (step === 'confirm') {
|
|
389
383
|
if (key.return) {
|
|
390
384
|
const config: DroidConfig = {
|
|
391
385
|
...loadConfig(),
|
|
392
386
|
ai_tool: aiTool,
|
|
393
387
|
user_mention: userMention,
|
|
394
|
-
output_preference:
|
|
388
|
+
output_preference: BuiltInOutput.Terminal, // Default to terminal
|
|
395
389
|
};
|
|
396
390
|
saveConfig(config);
|
|
397
391
|
configureAIToolPermissions(aiTool);
|
|
@@ -424,7 +418,7 @@ function SetupScreen({ onComplete, onSkip, initialConfig }: SetupScreenProps) {
|
|
|
424
418
|
<Text key={option.value}>
|
|
425
419
|
<Text color={colors.textDim}>{index === selectedIndex ? '>' : ' '} </Text>
|
|
426
420
|
<Text color={index === selectedIndex ? colors.text : colors.textMuted}>{option.label}</Text>
|
|
427
|
-
{option.value
|
|
421
|
+
{installedTools.has(option.value) && <Text color={colors.success}> (detected)</Text>}
|
|
428
422
|
</Text>
|
|
429
423
|
))}
|
|
430
424
|
</Box>
|
|
@@ -461,26 +455,6 @@ function SetupScreen({ onComplete, onSkip, initialConfig }: SetupScreenProps) {
|
|
|
461
455
|
);
|
|
462
456
|
}
|
|
463
457
|
|
|
464
|
-
if (step === 'output_preference') {
|
|
465
|
-
return (
|
|
466
|
-
<Box flexDirection="column" padding={1}>
|
|
467
|
-
{renderHeader()}
|
|
468
|
-
<Text color={colors.text}>Default output preference for skill results?</Text>
|
|
469
|
-
<Box flexDirection="column" marginTop={1}>
|
|
470
|
-
{outputOptions.map((option, index) => (
|
|
471
|
-
<Text key={option.value}>
|
|
472
|
-
<Text color={colors.textDim}>{index === selectedIndex ? '>' : ' '} </Text>
|
|
473
|
-
<Text color={index === selectedIndex ? colors.text : colors.textMuted}>{option.label}</Text>
|
|
474
|
-
</Text>
|
|
475
|
-
))}
|
|
476
|
-
</Box>
|
|
477
|
-
<Box marginTop={1}>
|
|
478
|
-
<Text color={colors.textDim}>↑↓ select · enter next · esc back</Text>
|
|
479
|
-
</Box>
|
|
480
|
-
</Box>
|
|
481
|
-
);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
458
|
// Confirm step
|
|
485
459
|
return (
|
|
486
460
|
<Box flexDirection="column" padding={1}>
|
|
@@ -495,10 +469,6 @@ function SetupScreen({ onComplete, onSkip, initialConfig }: SetupScreenProps) {
|
|
|
495
469
|
<Text color={colors.textDim}>Your @mention: </Text>
|
|
496
470
|
<Text color={colors.text}>{userMention}</Text>
|
|
497
471
|
</Text>
|
|
498
|
-
<Text>
|
|
499
|
-
<Text color={colors.textDim}>Output: </Text>
|
|
500
|
-
<Text color={colors.text}>{outputOptions.find((o) => o.value === outputPreference)?.label || outputPreference}</Text>
|
|
501
|
-
</Text>
|
|
502
472
|
</Box>
|
|
503
473
|
<Box marginTop={2}>
|
|
504
474
|
<Text backgroundColor={colors.primary} color="#ffffff" bold>
|
|
@@ -1032,12 +1002,6 @@ function SettingsDetails({
|
|
|
1032
1002
|
<Text color={colors.textDim}>Your @mention: </Text>
|
|
1033
1003
|
<Text color={colors.text}>{config.user_mention}</Text>
|
|
1034
1004
|
</Text>
|
|
1035
|
-
<Text>
|
|
1036
|
-
<Text color={colors.textDim}>Output: </Text>
|
|
1037
|
-
<Text color={colors.text}>
|
|
1038
|
-
{outputOptions.find((o) => o.value === config.output_preference)?.label || config.output_preference}
|
|
1039
|
-
</Text>
|
|
1040
|
-
</Text>
|
|
1041
1005
|
</Box>
|
|
1042
1006
|
|
|
1043
1007
|
<Box marginTop={1}>
|
|
@@ -1389,8 +1353,6 @@ function App() {
|
|
|
1389
1353
|
useInput((input, key) => {
|
|
1390
1354
|
if (message) setMessage(null);
|
|
1391
1355
|
|
|
1392
|
-
if (view === 'welcome') return;
|
|
1393
|
-
|
|
1394
1356
|
if (input === 'q') {
|
|
1395
1357
|
exit();
|
|
1396
1358
|
return;
|
|
@@ -1528,8 +1490,18 @@ function App() {
|
|
|
1528
1490
|
type: result.success ? 'success' : 'error',
|
|
1529
1491
|
});
|
|
1530
1492
|
if (result.success) {
|
|
1531
|
-
|
|
1532
|
-
|
|
1493
|
+
// Check if skill has required config (options without defaults)
|
|
1494
|
+
const configSchema = skill.config_schema || {};
|
|
1495
|
+
const hasRequiredConfig = Object.values(configSchema).some(
|
|
1496
|
+
(option) => (option as ConfigOption).default === undefined
|
|
1497
|
+
);
|
|
1498
|
+
if (hasRequiredConfig) {
|
|
1499
|
+
// Go to configure view for required setup
|
|
1500
|
+
setView('configure');
|
|
1501
|
+
} else {
|
|
1502
|
+
setView('menu');
|
|
1503
|
+
setSelectedAction(0);
|
|
1504
|
+
}
|
|
1533
1505
|
}
|
|
1534
1506
|
}
|
|
1535
1507
|
}
|
|
@@ -1590,7 +1562,7 @@ function App() {
|
|
|
1590
1562
|
}
|
|
1591
1563
|
}
|
|
1592
1564
|
}
|
|
1593
|
-
});
|
|
1565
|
+
}, { isActive: view !== 'welcome' && view !== 'setup' && view !== 'configure' });
|
|
1594
1566
|
|
|
1595
1567
|
const selectedSkill = activeTab === 'skills' ? skills[selectedIndex] ?? null : null;
|
|
1596
1568
|
const selectedCommand = activeTab === 'commands' ? commands[selectedIndex] ?? null : null;
|
|
@@ -38,12 +38,13 @@ Ideas develop through iteration, not single prompts.
|
|
|
38
38
|
|
|
39
39
|
**IMPORTANT:** Before using any default paths, ALWAYS read `~/.droid/skills/brain/overrides.yaml` first. If `brain_dir` is configured there, use that path. Only fall back to defaults if the file doesn't exist or lacks a `brain_dir` setting.
|
|
40
40
|
|
|
41
|
-
| Setting
|
|
42
|
-
|
|
43
|
-
| `brain_dir`
|
|
44
|
-
| `inbox_folder` | (empty)
|
|
41
|
+
| Setting | Default | Description |
|
|
42
|
+
| -------------- | ----------- | --------------------------------------------------------- |
|
|
43
|
+
| `brain_dir` | (see below) | Where docs are stored |
|
|
44
|
+
| `inbox_folder` | (empty) | Optional subfolder for new docs (omit for flat structure) |
|
|
45
45
|
|
|
46
46
|
Default `brain_dir` by AI tool (only if not configured):
|
|
47
|
+
|
|
47
48
|
- **claude-code**: `~/.claude/brain`
|
|
48
49
|
- **opencode**: `~/.config/opencode/brain`
|
|
49
50
|
|
|
@@ -52,28 +53,44 @@ Default `brain_dir` by AI tool (only if not configured):
|
|
|
52
53
|
**Active doc:** Opening or creating a brain doc makes it "active" for the session. Subsequent `/brain add` commands append to it without specifying a path.
|
|
53
54
|
|
|
54
55
|
**Doc types:**
|
|
56
|
+
|
|
55
57
|
- `plan` - Structured: Context → Exploration → Decision → Next Steps
|
|
56
58
|
- `research` - Open-ended exploration of a topic
|
|
57
59
|
- `review` - Code review, document review, or any evaluation task
|
|
58
60
|
- `note` - Quick capture (fire-and-forget, doesn't become active)
|
|
59
61
|
|
|
60
|
-
**Comment conventions:**
|
|
62
|
+
**Comment conventions:** In markdown files, ALWAYS use blockquote `>` prefix for @mention comments:
|
|
63
|
+
|
|
64
|
+
- `> @droid` - **User** leaves comment for AI to address
|
|
65
|
+
- `> @{user}` - **AI** leaves comment for user to address
|
|
66
|
+
|
|
67
|
+
**CRITICAL:** When YOU (the AI) respond to a comment or create a placeholder, you MUST use `> @{user_mention}` (e.g., `> @fry`). NEVER use `@droid` for your own responses - that tag is for the USER to address YOU.
|
|
68
|
+
|
|
69
|
+
Example conversation:
|
|
70
|
+
|
|
71
|
+
```markdown
|
|
72
|
+
> @droid Should we add caching here?
|
|
73
|
+
|
|
74
|
+
> @fry Yes, Redis would work well for this use case.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Read user's configured mention from `~/.droid/config.yaml` → `user_mention` (e.g., `@fry`). If droid's `comments` skill is installed, use `/comments check` for full support.
|
|
61
78
|
|
|
62
79
|
**Status lifecycle:** `exploring` → `drafting` → `decided` → `done`
|
|
63
80
|
|
|
64
81
|
## Commands
|
|
65
82
|
|
|
66
|
-
| Command
|
|
67
|
-
|
|
68
|
-
| `/brain`
|
|
69
|
-
| `/brain {topic}`
|
|
70
|
-
| `/brain plan {topic}`
|
|
71
|
-
| `/brain research {topic}` | Create research doc (requires `research` keyword)
|
|
72
|
-
| `/brain review {topic}`
|
|
73
|
-
| `/brain note {text}`
|
|
74
|
-
| `/brain add {text}`
|
|
75
|
-
| `/brain check`
|
|
76
|
-
| `/brain done`
|
|
83
|
+
| Command | Action |
|
|
84
|
+
| ------------------------- | ---------------------------------------------------------- |
|
|
85
|
+
| `/brain` | List recent docs or create new |
|
|
86
|
+
| `/brain {topic}` | **Search** for existing doc (fuzzy match) → becomes active |
|
|
87
|
+
| `/brain plan {topic}` | Create planning doc (requires `plan` keyword) |
|
|
88
|
+
| `/brain research {topic}` | Create research doc (requires `research` keyword) |
|
|
89
|
+
| `/brain review {topic}` | Create review doc (requires `review` keyword) |
|
|
90
|
+
| `/brain note {text}` | Quick capture (standalone, doesn't become active) |
|
|
91
|
+
| `/brain add {text}` | Append to active doc |
|
|
92
|
+
| `/brain check` | Address @droid comments in active doc |
|
|
93
|
+
| `/brain done` | Finalize active doc, update status |
|
|
77
94
|
|
|
78
95
|
**IMPORTANT:** The default action for `/brain {topic}` is to **SEARCH** for existing docs, NOT create. Only use `/brain plan {topic}` or `/brain research {topic}` when the user explicitly wants to create a new doc.
|
|
79
96
|
|
|
@@ -115,7 +132,7 @@ Full procedure: `references/workflows.md` § Adding
|
|
|
115
132
|
|
|
116
133
|
**Trigger:** `/brain check`
|
|
117
134
|
|
|
118
|
-
**TLDR:** Find `> @droid` comments in active doc, address each one.
|
|
135
|
+
**TLDR:** Find `> @droid` comments in active doc, address each one with `> @{user_mention}` response (always use blockquote `>`).
|
|
119
136
|
|
|
120
137
|
Full procedure: `references/workflows.md` § Checking
|
|
121
138
|
|
|
@@ -132,11 +149,18 @@ Full procedure: `references/workflows.md` § Finalizing
|
|
|
132
149
|
Before creating or modifying brain docs, check if any `brain-*` extension skills are installed:
|
|
133
150
|
|
|
134
151
|
```
|
|
152
|
+
# Claude Code
|
|
135
153
|
~/.claude/skills/brain-*/SKILL.md
|
|
154
|
+
|
|
155
|
+
# OpenCode
|
|
156
|
+
~/.config/opencode/skills/brain-*/SKILL.md
|
|
157
|
+
|
|
158
|
+
# Shared (droid config)
|
|
136
159
|
~/.droid/skills/brain-*/SKILL.md
|
|
137
160
|
```
|
|
138
161
|
|
|
139
162
|
If found (e.g., `brain-obsidian`), **ALWAYS** use the extension's templates, workflows, and configuration instead of this skill's defaults. Extensions may provide:
|
|
163
|
+
|
|
140
164
|
- Alternative template formats (YAML frontmatter, wikilinks)
|
|
141
165
|
- Folder organization (PARA structure)
|
|
142
166
|
- Additional commands or integrations
|
|
@@ -20,12 +20,12 @@ Simple and portable. Works anywhere markdown is supported.
|
|
|
20
20
|
|
|
21
21
|
## Fields
|
|
22
22
|
|
|
23
|
-
| Field
|
|
24
|
-
|
|
25
|
-
| `Type`
|
|
26
|
-
| `Status`
|
|
27
|
-
| `Created` | Yes
|
|
28
|
-
| `Updated` | No
|
|
23
|
+
| Field | Required | Description |
|
|
24
|
+
| --------- | ------------------ | ------------------------------------------------- |
|
|
25
|
+
| `Type` | Yes | Doc type: `plan`, `research`, `review`, or `note` |
|
|
26
|
+
| `Status` | Yes (except notes) | Current lifecycle stage |
|
|
27
|
+
| `Created` | Yes | Creation date |
|
|
28
|
+
| `Updated` | No | Last modification date (add when doc changes) |
|
|
29
29
|
|
|
30
30
|
## Status Lifecycle
|
|
31
31
|
|
|
@@ -37,13 +37,13 @@ exploring → drafting → decided → done
|
|
|
37
37
|
|
|
38
38
|
### Status Definitions
|
|
39
39
|
|
|
40
|
-
| Status
|
|
41
|
-
|
|
42
|
-
| `exploring` | Initial discovery, gathering information | Research, ask questions, explore options
|
|
43
|
-
| `drafting`
|
|
44
|
-
| `decided`
|
|
45
|
-
| `done`
|
|
46
|
-
| `stale`
|
|
40
|
+
| Status | Meaning | Typical Actions |
|
|
41
|
+
| ----------- | ---------------------------------------- | ------------------------------------------------ |
|
|
42
|
+
| `exploring` | Initial discovery, gathering information | Research, ask questions, explore options |
|
|
43
|
+
| `drafting` | Forming opinions, narrowing options | Document trade-offs, propose approaches |
|
|
44
|
+
| `decided` | Decision made, ready to act | Document decision rationale, plan implementation |
|
|
45
|
+
| `done` | Work complete, doc is reference material | Archive or link from project |
|
|
46
|
+
| `stale` | Abandoned or outdated | Review for archival or deletion |
|
|
47
47
|
|
|
48
48
|
### Transitions
|
|
49
49
|
|
|
@@ -55,5 +55,6 @@ exploring → drafting → decided → done
|
|
|
55
55
|
## Updating Metadata
|
|
56
56
|
|
|
57
57
|
When modifying a doc:
|
|
58
|
+
|
|
58
59
|
1. Add or update the `Updated` field to current date
|
|
59
60
|
2. Update `Status` if the work has progressed
|