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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dotai-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Unified CLI for AI coding assistants - manage skills and MCP servers across Claude Code, Gemini CLI, Cursor, VS Code, and more",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -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: false
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, detailedDescription) {
108
- return `Create a SKILL.md file for an AI coding assistant skill with the following specifications:
109
-
110
- **Skill Name:** ${skillName}
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 (creates prompt for ChatGPT/Claude)' },
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
- // AI-assisted creation - use the short description as context, ask for more detail
191
- const { detailedDescription } = await prompt({
174
+ const { details } = await prompt({
192
175
  type: 'input',
193
- name: 'detailedDescription',
194
- message: 'What should the AI do with this skill? (be specific):',
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, detailedDescription);
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('Could not copy to clipboard. Here\'s the prompt:\n'));
209
- console.log(chalk.dim('─'.repeat(60)));
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(60)));
191
+ console.log(chalk.dim('─'.repeat(40)));
212
192
  }
213
193
 
214
- console.log(chalk.bold('Next steps:'));
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: 'Do you have the AI-generated content ready to paste?',
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 the SKILL.md content below, then press Enter twice when done:\n'));
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 with AI-generated content...').start();
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 with AI content!`));
239
- console.log(chalk.dim(`\nLocation: ${result.path}`));
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('\nNo problem! When you have the content ready:'));
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