@snapcommit/cli 2.4.0 → 2.6.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.
@@ -85,7 +85,8 @@ async function handleAICommand(userInput) {
85
85
  return;
86
86
  }
87
87
  // For commits, generate AI message first
88
- if (intent.action === 'commit') {
88
+ if (intent.action === 'commit' || intent.action === 'push' ||
89
+ (intent.gitCommands && intent.gitCommands.some((cmd) => cmd.includes('commit')))) {
89
90
  await executeCommitWithAI(intent);
90
91
  return;
91
92
  }
@@ -95,7 +96,10 @@ async function handleAICommand(userInput) {
95
96
  console.log(chalk_1.default.green('✓ Done\n'));
96
97
  }
97
98
  else {
98
- console.log(chalk_1.default.yellow('⚠️ No commands to execute\n'));
99
+ // Debug: show what we got
100
+ console.log(chalk_1.default.yellow('⚠️ No commands to execute'));
101
+ console.log(chalk_1.default.gray(`Intent action: ${intent.action || 'none'}`));
102
+ console.log(chalk_1.default.gray(`Git commands: ${intent.gitCommands?.length || 0}\n`));
99
103
  }
100
104
  }
101
105
  else if (intent.type === 'github') {
@@ -129,69 +133,137 @@ async function showStatus() {
129
133
  }
130
134
  /**
131
135
  * Execute commit with AI-generated message
132
- * Shows message and allows editing (like Cursor!)
136
+ * Natural language interactive flow - like talking to Cursor!
133
137
  */
134
138
  async function executeCommitWithAI(intent) {
135
139
  const status = (0, git_1.getGitStatus)();
136
140
  const hasChanges = status.staged > 0 || status.unstaged > 0 || status.untracked > 0;
137
141
  if (!hasChanges) {
138
- console.log(chalk_1.default.gray('✓ Branch clean'));
142
+ console.log(chalk_1.default.gray('\n✓ Branch clean\n'));
139
143
  return;
140
144
  }
141
- // Stage all
145
+ // Show ALL changed files with details
146
+ console.log(chalk_1.default.blue('\n📦 Files changed:\n'));
147
+ try {
148
+ const output = (0, child_process_1.execSync)('git status --short', { encoding: 'utf-8' });
149
+ output.split('\n').filter(line => line.trim()).forEach(line => {
150
+ const status = line.substring(0, 2);
151
+ const file = line.substring(3);
152
+ if (status.includes('M')) {
153
+ console.log(chalk_1.default.yellow(` ✎ ${file}`));
154
+ }
155
+ else if (status.includes('?')) {
156
+ console.log(chalk_1.default.green(` + ${file}`));
157
+ }
158
+ else if (status.includes('D')) {
159
+ console.log(chalk_1.default.red(` - ${file}`));
160
+ }
161
+ });
162
+ }
163
+ catch {
164
+ if (status.unstaged > 0)
165
+ console.log(chalk_1.default.yellow(` • ${status.unstaged} modified`));
166
+ if (status.untracked > 0)
167
+ console.log(chalk_1.default.green(` • ${status.untracked} new`));
168
+ }
169
+ console.log();
170
+ // Natural language file selection
171
+ const readline = await Promise.resolve().then(() => __importStar(require('readline')));
172
+ const rl = readline.createInterface({
173
+ input: process.stdin,
174
+ output: process.stdout,
175
+ });
176
+ const fileChoice = await new Promise((resolve) => {
177
+ rl.question(chalk_1.default.cyan('What do you want to do? ') + chalk_1.default.gray('(commit all / select files / cancel): '), (ans) => {
178
+ rl.close();
179
+ resolve(ans.toLowerCase().trim());
180
+ });
181
+ });
182
+ if (fileChoice.includes('cancel') || fileChoice === 'n' || fileChoice === 'no') {
183
+ console.log(chalk_1.default.gray('\n✗ Cancelled\n'));
184
+ return;
185
+ }
186
+ if (fileChoice.includes('select')) {
187
+ console.log(chalk_1.default.yellow('\n💡 Use: ') + chalk_1.default.cyan('git add <files>') + chalk_1.default.yellow(' to stage specific files'));
188
+ console.log(chalk_1.default.gray(' Then run: ') + chalk_1.default.cyan('snap') + chalk_1.default.gray(' and try again\n'));
189
+ return;
190
+ }
191
+ // Stage all (default for "commit all" or just pressing Enter)
142
192
  try {
143
193
  (0, git_1.stageAllChanges)();
144
194
  }
145
195
  catch (error) {
146
- console.log(chalk_1.default.red(`❌ ${error.message}`));
196
+ console.log(chalk_1.default.red(`\n❌ ${error.message}\n`));
147
197
  return;
148
198
  }
149
199
  // Generate AI commit message
200
+ console.log(chalk_1.default.blue('🤖 Generating commit message...\n'));
150
201
  const diff = (0, git_1.getGitDiff)(true);
151
202
  let commitMessage = await generateCommitMessage(diff);
152
- // Show message and ask if they want to edit (like Cursor!)
153
- console.log(chalk_1.default.cyan('\n📝 Commit message:'));
154
- console.log(chalk_1.default.white(` ${commitMessage.split('\n')[0]}\n`));
155
- const readline = await Promise.resolve().then(() => __importStar(require('readline')));
156
- const rl = readline.createInterface({
203
+ // Show message with natural language prompt
204
+ console.log(chalk_1.default.cyan('📝 AI generated this commit message:'));
205
+ console.log(chalk_1.default.white.bold(` "${commitMessage.split('\n')[0]}"\n`));
206
+ const rl2 = readline.createInterface({
157
207
  input: process.stdin,
158
208
  output: process.stdout,
159
209
  });
160
- const answer = await new Promise((resolve) => {
161
- rl.question(chalk_1.default.gray('Press Enter to commit, or type new message: '), (ans) => {
162
- rl.close();
163
- resolve(ans);
210
+ const messageAction = await new Promise((resolve) => {
211
+ rl2.question(chalk_1.default.cyan('What next? ') + chalk_1.default.gray('(looks good / edit / type new message / cancel): '), (ans) => {
212
+ rl2.close();
213
+ resolve(ans.toLowerCase().trim());
164
214
  });
165
215
  });
166
- // If user typed something, use that instead
167
- if (answer.trim()) {
168
- commitMessage = answer.trim();
216
+ // Handle response naturally
217
+ if (messageAction.includes('cancel') || messageAction === 'no' || messageAction === 'n') {
218
+ console.log(chalk_1.default.gray('\n✗ Cancelled\n'));
219
+ return;
220
+ }
221
+ if (messageAction.includes('edit') || messageAction.includes('change')) {
222
+ const rl3 = readline.createInterface({
223
+ input: process.stdin,
224
+ output: process.stdout,
225
+ });
226
+ commitMessage = await new Promise((resolve) => {
227
+ rl3.question(chalk_1.default.cyan('Your message: '), (ans) => {
228
+ rl3.close();
229
+ resolve(ans.trim() || commitMessage);
230
+ });
231
+ });
169
232
  console.log(chalk_1.default.green('\n✓ Message updated\n'));
170
233
  }
234
+ else if (messageAction && !messageAction.includes('good') && !messageAction.includes('yes') && !messageAction.includes('ok')) {
235
+ // They typed a custom message directly
236
+ commitMessage = messageAction;
237
+ console.log(chalk_1.default.green('\n✓ Using your message\n'));
238
+ }
171
239
  // Commit
172
240
  try {
173
241
  (0, child_process_1.execSync)(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { encoding: 'utf-8', stdio: 'pipe' });
174
- console.log(chalk_1.default.green(`✓ Committed`));
242
+ console.log(chalk_1.default.green(`✓ ${commitMessage.split('\n')[0]}`));
175
243
  }
176
244
  catch (error) {
177
- console.log(chalk_1.default.red(`❌ Commit failed`));
245
+ console.log(chalk_1.default.red(`\n❌ Commit failed: ${error.message}\n`));
178
246
  return;
179
247
  }
180
248
  // Push if requested
181
- if (intent.shouldPush || intent.gitCommands?.some((cmd) => cmd.includes('push'))) {
249
+ const shouldPush = intent.shouldPush || intent.gitCommands?.some((cmd) => cmd.includes('push'));
250
+ if (shouldPush) {
182
251
  try {
183
252
  (0, child_process_1.execSync)('git push', { encoding: 'utf-8', stdio: 'pipe' });
184
- console.log(chalk_1.default.green('✓ Pushed'));
253
+ console.log(chalk_1.default.green('✓ Pushed\n'));
185
254
  }
186
255
  catch (error) {
187
256
  if (error.message.includes('no configured push destination')) {
188
- console.log(chalk_1.default.gray('✓ Committed locally (no remote)'));
257
+ console.log(chalk_1.default.gray('✓ Committed locally (no remote)\n'));
189
258
  }
190
259
  else {
191
- console.log(chalk_1.default.yellow(`⚠️ ${error.message}`));
260
+ console.log(chalk_1.default.yellow(`⚠️ Push failed: ${error.message}\n`));
192
261
  }
193
262
  }
194
263
  }
264
+ else {
265
+ console.log();
266
+ }
195
267
  }
196
268
  /**
197
269
  * Execute Git commands with auto-retry on errors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapcommit/cli",
3
- "version": "2.4.0",
3
+ "version": "2.6.0",
4
4
  "description": "Instant AI commits. Beautiful progress tracking. Never write commit messages again.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {