dotai-cli 1.0.1 ā 1.0.2
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/package.json +1 -1
- package/src/commands/create.js +36 -61
package/package.json
CHANGED
package/src/commands/create.js
CHANGED
|
@@ -10,17 +10,18 @@ import { createSkill } from '../lib/skills.js';
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Read multiline input from stdin until two empty lines or Ctrl+D
|
|
13
|
+
* Handles large paste operations properly by buffering input
|
|
13
14
|
*/
|
|
14
15
|
async function readMultilineInput() {
|
|
15
16
|
return new Promise((resolve) => {
|
|
16
17
|
const lines = [];
|
|
17
18
|
let emptyLineCount = 0;
|
|
18
19
|
|
|
19
|
-
// Disable echo by using terminal: false
|
|
20
20
|
const rl = readline.createInterface({
|
|
21
21
|
input: process.stdin,
|
|
22
22
|
output: process.stdout,
|
|
23
|
-
terminal:
|
|
23
|
+
terminal: process.stdin.isTTY,
|
|
24
|
+
crlfDelay: Infinity
|
|
24
25
|
});
|
|
25
26
|
|
|
26
27
|
rl.on('line', (line) => {
|
|
@@ -47,6 +48,17 @@ async function readMultilineInput() {
|
|
|
47
48
|
}
|
|
48
49
|
resolve(lines.join('\n'));
|
|
49
50
|
});
|
|
51
|
+
|
|
52
|
+
// Handle SIGINT (Ctrl+C) gracefully
|
|
53
|
+
rl.on('SIGINT', () => {
|
|
54
|
+
rl.close();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Handle errors
|
|
58
|
+
rl.on('error', (err) => {
|
|
59
|
+
console.error(chalk.red(`Input error: ${err.message}`));
|
|
60
|
+
rl.close();
|
|
61
|
+
});
|
|
50
62
|
});
|
|
51
63
|
}
|
|
52
64
|
|
|
@@ -104,41 +116,13 @@ function copyToClipboard(text) {
|
|
|
104
116
|
/**
|
|
105
117
|
* Generate AI prompt for skill creation
|
|
106
118
|
*/
|
|
107
|
-
function generateAIPrompt(skillName, description,
|
|
108
|
-
return `Create a SKILL.md
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
**Short Description:** ${description}
|
|
112
|
-
|
|
113
|
-
**What this skill should do:**
|
|
114
|
-
${detailedDescription}
|
|
119
|
+
function generateAIPrompt(skillName, description, details) {
|
|
120
|
+
return `Create a SKILL.md for: ${skillName}
|
|
121
|
+
${description}
|
|
122
|
+
${details}
|
|
115
123
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
Please generate a complete SKILL.md file with:
|
|
119
|
-
|
|
120
|
-
1. **YAML Frontmatter** at the top:
|
|
121
|
-
\`\`\`yaml
|
|
122
|
-
---
|
|
123
|
-
name: ${skillName}
|
|
124
|
-
description: ${description}
|
|
125
|
-
---
|
|
126
|
-
\`\`\`
|
|
127
|
-
|
|
128
|
-
2. **Detailed Instructions** including:
|
|
129
|
-
- When to use this skill (specific scenarios/triggers)
|
|
130
|
-
- Step-by-step guidance for the AI to follow
|
|
131
|
-
- Best practices and conventions
|
|
132
|
-
- Common pitfalls to avoid
|
|
133
|
-
- Example inputs and expected outputs
|
|
134
|
-
|
|
135
|
-
3. **Format Requirements:**
|
|
136
|
-
- Use clear, actionable language
|
|
137
|
-
- Include code examples where relevant
|
|
138
|
-
- Keep instructions concise but comprehensive
|
|
139
|
-
- Use markdown formatting (headers, lists, code blocks)
|
|
140
|
-
|
|
141
|
-
Generate the complete SKILL.md content now:`;
|
|
124
|
+
Format: YAML frontmatter (name, description) + markdown instructions.
|
|
125
|
+
Keep it short and actionable (under 100 lines).`;
|
|
142
126
|
}
|
|
143
127
|
|
|
144
128
|
export async function createCommand(name, options) {
|
|
@@ -181,62 +165,55 @@ export async function createCommand(name, options) {
|
|
|
181
165
|
name: 'method',
|
|
182
166
|
message: 'How do you want to write the skill instructions?',
|
|
183
167
|
choices: [
|
|
184
|
-
{ name: 'ai', message: 'š¤ Generate with AI (
|
|
168
|
+
{ name: 'ai', message: 'š¤ Generate with AI (ChatGPT, Claude, Gemini, etc)' },
|
|
185
169
|
{ name: 'manual', message: 'āļø Write manually (opens editor with template)' }
|
|
186
170
|
]
|
|
187
171
|
});
|
|
188
172
|
|
|
189
173
|
if (method === 'ai') {
|
|
190
|
-
|
|
191
|
-
const { detailedDescription } = await prompt({
|
|
174
|
+
const { details } = await prompt({
|
|
192
175
|
type: 'input',
|
|
193
|
-
name: '
|
|
194
|
-
message: 'What should
|
|
195
|
-
validate: (value) => value.length > 10 ? true : 'Please provide more detail (at least 10 characters)'
|
|
176
|
+
name: 'details',
|
|
177
|
+
message: 'What should this skill do?'
|
|
196
178
|
});
|
|
197
179
|
|
|
198
|
-
const aiPrompt = generateAIPrompt(skillName, description,
|
|
199
|
-
|
|
200
|
-
console.log(chalk.bold('\nš AI Prompt Generated!\n'));
|
|
180
|
+
const aiPrompt = generateAIPrompt(skillName, description, details || '');
|
|
201
181
|
|
|
202
182
|
// Try to copy to clipboard
|
|
203
183
|
const copied = copyToClipboard(aiPrompt);
|
|
204
184
|
|
|
205
185
|
if (copied) {
|
|
206
|
-
console.log(chalk.green('ā Prompt copied to clipboard!\n'));
|
|
186
|
+
console.log(chalk.green('\nā Prompt copied to clipboard!\n'));
|
|
207
187
|
} else {
|
|
208
|
-
console.log(chalk.yellow('
|
|
209
|
-
console.log(chalk.dim('ā'.repeat(
|
|
188
|
+
console.log(chalk.yellow('\nPrompt:\n'));
|
|
189
|
+
console.log(chalk.dim('ā'.repeat(40)));
|
|
210
190
|
console.log(aiPrompt);
|
|
211
|
-
console.log(chalk.dim('ā'.repeat(
|
|
191
|
+
console.log(chalk.dim('ā'.repeat(40)));
|
|
212
192
|
}
|
|
213
193
|
|
|
214
|
-
console.log(
|
|
215
|
-
console.log(' 1. Paste this prompt into ChatGPT, Claude, or any LLM');
|
|
216
|
-
console.log(' 2. Copy the generated SKILL.md content');
|
|
217
|
-
console.log(' 3. Run this command again and paste the result\n');
|
|
194
|
+
console.log('Paste into any AI (ChatGPT, Claude, Gemini, etc), then paste the result here.\n');
|
|
218
195
|
|
|
219
196
|
const { hasContent } = await prompt({
|
|
220
197
|
type: 'confirm',
|
|
221
198
|
name: 'hasContent',
|
|
222
|
-
message: '
|
|
199
|
+
message: 'Ready to paste AI-generated content?',
|
|
223
200
|
initial: false
|
|
224
201
|
});
|
|
225
202
|
|
|
226
203
|
if (hasContent) {
|
|
227
|
-
console.log(chalk.dim('\nPaste
|
|
204
|
+
console.log(chalk.dim('\nPaste content, then press Enter twice:\n'));
|
|
228
205
|
|
|
229
206
|
// Read multiline input using readline
|
|
230
207
|
const content = await readMultilineInput();
|
|
231
208
|
|
|
232
209
|
if (content && content.trim()) {
|
|
233
|
-
const spinner = ora('Creating skill
|
|
210
|
+
const spinner = ora('Creating skill...').start();
|
|
234
211
|
try {
|
|
235
212
|
const result = await createSkill(skillName, description, '');
|
|
236
213
|
// Write the pasted content directly
|
|
237
214
|
await fs.writeFile(result.skillMdPath, content.trim(), 'utf-8');
|
|
238
|
-
spinner.succeed(chalk.green(`Skill '${skillName}' created
|
|
239
|
-
console.log(chalk.dim(
|
|
215
|
+
spinner.succeed(chalk.green(`Skill '${skillName}' created!`));
|
|
216
|
+
console.log(chalk.dim(`Location: ${result.path}`));
|
|
240
217
|
console.log(chalk.yellow('\nInstall with:'));
|
|
241
218
|
console.log(` ${chalk.cyan(`dotai skill install ${skillName}`)}\n`);
|
|
242
219
|
} catch (err) {
|
|
@@ -247,9 +224,7 @@ export async function createCommand(name, options) {
|
|
|
247
224
|
await createWithTemplate(skillName, description);
|
|
248
225
|
}
|
|
249
226
|
} else {
|
|
250
|
-
console.log(chalk.dim(
|
|
251
|
-
console.log(` 1. Create the skill: ${chalk.cyan(`dotai skill create ${skillName} -d "${description}"`)}`);
|
|
252
|
-
console.log(` 2. Or manually create: ${chalk.cyan(`~/.dotai/skills/${skillName}/SKILL.md`)}\n`);
|
|
227
|
+
console.log(chalk.dim(`\nRun again when ready: ${chalk.cyan(`dotai skill create ${skillName}`)}\n`));
|
|
253
228
|
}
|
|
254
229
|
} else {
|
|
255
230
|
// Manual creation
|