vnxt 1.4.5 → 1.7.7

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/.vnxtrc.json CHANGED
@@ -4,5 +4,6 @@
4
4
  "requireCleanWorkingDir": false,
5
5
  "autoPush": true,
6
6
  "defaultStageMode": "tracked",
7
- "tagPrefix": "v"
8
- }
7
+ "tagPrefix": "v",
8
+ "colors": true
9
+ }
package/README.md CHANGED
@@ -16,6 +16,8 @@ A lightweight CLI tool for automated version bumping with changelog generation a
16
16
  - šŸ“‹ Release notes generation
17
17
  - āš™ļø Project-level configuration support
18
18
  - šŸ’¬ Interactive mode when no arguments provided
19
+ - šŸŽØ Colored terminal output for better readability
20
+ - 🤫 Quiet mode for CI/CD environments
19
21
 
20
22
  ## <img src="./docs/logos/caret-38x38.png" width="24" align="center"> Installation
21
23
 
@@ -87,12 +89,15 @@ All options work with both `vnxt` and `vx`:
87
89
  -m, --message <msg> Commit message (required unless using interactive mode)
88
90
  -t, --type <type> Version type: patch, minor, major (auto-detected from message)
89
91
  -v, --version <ver> Set specific version (e.g., 2.0.0-beta.1)
92
+ -V, --version Show vnxt version
90
93
  -p, --push Push to remote with tags
94
+ -dnp, --no-push Prevent auto-push (overrides config)
91
95
  -c, --changelog Update CHANGELOG.md
92
96
  -d, --dry-run Show what would happen without making changes
93
97
  -a, --all [mode] Stage files before versioning (prompts if no mode)
94
98
  Modes: tracked, all, interactive (i), patch (p)
95
99
  -r, --release Generate release notes file
100
+ -q, --quiet Minimal output (errors only)
96
101
  -h, --help Show help message
97
102
  ```
98
103
 
@@ -207,6 +212,39 @@ vx -m "fix: typo" -a p # Patch mode (git add -p)
207
212
 
208
213
  **Note:** If you run `vx` without any files staged and without the `-a` flag, vnxt will prompt you interactively to choose a staging mode.
209
214
 
215
+ ### Quiet Mode
216
+
217
+ Minimize terminal output for CI/CD environments:
218
+
219
+ **Bash/PowerShell:**
220
+ ```bash
221
+ vx -m "feat: new feature" -q
222
+ ```
223
+
224
+ In quiet mode:
225
+ - āœ… Errors still display
226
+ - āŒ Progress messages hidden
227
+ - āŒ Summary stats hidden
228
+ - āŒ Git diff output hidden
229
+
230
+ Perfect for automated workflows where you only want to see failures.
231
+
232
+ ### Check Version
233
+
234
+ Display the installed vnxt version:
235
+
236
+ **Bash/PowerShell:**
237
+ ```bash
238
+ vx -V
239
+ # or
240
+ vnxt --version
241
+ ```
242
+
243
+ Output:
244
+ ```
245
+ vnxt v1.7.0
246
+ ```
247
+
210
248
  ### Complete Workflow Example
211
249
 
212
250
  **Bash/PowerShell:**
@@ -228,8 +266,11 @@ Create a `.vnxtrc.json` file in your project root to set defaults:
228
266
  {
229
267
  "autoChangelog": true,
230
268
  "defaultType": "patch",
231
- "requireCleanWorkingDir": true,
232
- "autoPush": false
269
+ "requireCleanWorkingDir": false,
270
+ "autoPush": true,
271
+ "defaultStageMode": "tracked",
272
+ "tagPrefix": "v",
273
+ "colors": true
233
274
  }
234
275
  ```
235
276
 
@@ -237,10 +278,13 @@ Create a `.vnxtrc.json` file in your project root to set defaults:
237
278
 
238
279
  | Option | Type | Default | Description |
239
280
  |--------|------|---------|-------------|
240
- | `autoChangelog` | boolean | `false` | Automatically update CHANGELOG.md on every bump |
281
+ | `autoChangelog` | boolean | `true` | Automatically update CHANGELOG.md on every bump |
241
282
  | `defaultType` | string | `"patch"` | Default version bump type if not auto-detected |
242
- | `requireCleanWorkingDir` | boolean | `true` | Require clean git working directory before bumping |
243
- | `autoPush` | boolean | `false` | Automatically push to remote after bumping |
283
+ | `requireCleanWorkingDir` | boolean | `false` | Require clean git working directory before bumping |
284
+ | `autoPush` | boolean | `true` | Automatically push to remote after bumping |
285
+ | `defaultStageMode` | string | `"tracked"` | Default staging mode when using `-a` flag |
286
+ | `tagPrefix` | string | `"v"` | Prefix for git tags (e.g., "v1.2.3") |
287
+ | `colors` | boolean | `true` | Enable colored terminal output |
244
288
 
245
289
  ## <img src="./docs/logos/caret-38x38.png" width="24" align="center"> Pre-flight Checks
246
290
 
@@ -310,8 +354,37 @@ vx -m "BREAKING: new API structure" -c -r -p
310
354
  vx -m "chore: refactor code" -a
311
355
  ```
312
356
 
357
+ ### CI/CD Pipeline
358
+
359
+ **Bash/PowerShell:**
360
+ ```bash
361
+ # Quiet mode - only shows errors
362
+ vx -m "chore: automated update" -q
363
+ ```
364
+
365
+ ### Check Installed Version
366
+
367
+ **Bash/PowerShell:**
368
+ ```bash
369
+ vx -V
370
+ ```
371
+
313
372
  ## <img src="./docs/logos/caret-38x38.png" width="24" align="center"> Troubleshooting
314
373
 
374
+ ### Not a Git Repository
375
+
376
+ If you see this error:
377
+ ```
378
+ āŒ Not a git repository. Run `git init` first.
379
+ ```
380
+
381
+ You're trying to use vnxt in a directory that isn't a git repository. Initialize git first:
382
+
383
+ **Bash/PowerShell:**
384
+ ```bash
385
+ git init
386
+ ```
387
+
315
388
  ### Permission Denied (Windows PowerShell)
316
389
 
317
390
  If you get execution policy errors:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vnxt",
3
- "version": "1.4.5",
3
+ "version": "1.7.7",
4
4
  "description": "Version incrementation CLI tool with built in git commit, push and changelog generation",
5
5
  "main": "vnxt.js",
6
6
  "bin": {
@@ -43,4 +43,4 @@
43
43
  "devDependencies": {
44
44
  "jest": "^29.7.0"
45
45
  }
46
- }
46
+ }
package/vnxt.js CHANGED
@@ -4,6 +4,45 @@ const {execSync} = require('child_process');
4
4
  const fs = require('fs');
5
5
  const readline = require('readline');
6
6
 
7
+ // ANSI color codes for terminal output
8
+ const colors = {
9
+ reset: '\x1b[0m',
10
+ bright: '\x1b[1m',
11
+ dim: '\x1b[2m',
12
+
13
+ // Foreground colors
14
+ red: '\x1b[31m',
15
+ green: '\x1b[32m',
16
+ yellow: '\x1b[33m',
17
+ blue: '\x1b[34m',
18
+ cyan: '\x1b[36m',
19
+ white: '\x1b[37m',
20
+ gray: '\x1b[90m'
21
+ };
22
+
23
+ // Quiet mode flag
24
+ let quietMode = false;
25
+
26
+ // Helper to log with colors (respects quiet mode and colors config)
27
+ function log(message, color = '') {
28
+ if (quietMode) return;
29
+ if (color && colors[color] && config.colors) {
30
+ console.log(`${colors[color]}${message}${colors.reset}`);
31
+ } else {
32
+ console.log(message);
33
+ }
34
+ }
35
+
36
+ function logError(message) {
37
+ // Errors always show, even in quiet mode
38
+ // Colors can be disabled for errors too
39
+ if (config.colors) {
40
+ console.error(`${colors.red}${message}${colors.reset}`);
41
+ } else {
42
+ console.error(message);
43
+ }
44
+ }
45
+
7
46
  // Parse command line arguments
8
47
  const args = process.argv.slice(2);
9
48
 
@@ -25,7 +64,8 @@ let config = {
25
64
  requireCleanWorkingDir: false,
26
65
  autoPush: true,
27
66
  defaultStageMode: 'tracked',
28
- tagPrefix: 'v'
67
+ tagPrefix: 'v',
68
+ colors: true
29
69
  };
30
70
 
31
71
  if (fs.existsSync('.vnxtrc.json')) {
@@ -33,6 +73,24 @@ if (fs.existsSync('.vnxtrc.json')) {
33
73
  config = {...config, ...userConfig};
34
74
  }
35
75
 
76
+ // Check for --version flag
77
+ if (args.includes('--version') || args.includes('-V')) {
78
+ const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
79
+ console.log(`vnxt v${pkg.version}`);
80
+ process.exit(0);
81
+ }
82
+
83
+ // Check for --quiet flag
84
+ if (args.includes('--quiet') || args.includes('-q')) {
85
+ quietMode = true;
86
+ }
87
+
88
+ // Check if in a git repository
89
+ if (!fs.existsSync('.git')) {
90
+ logError('āŒ Not a git repository. Run `git init` first.');
91
+ process.exit(1);
92
+ }
93
+
36
94
  // Parse arguments
37
95
  let message = getFlag('--message', '-m');
38
96
  let type = getFlag('--type', '-t') || config.defaultType;
@@ -42,10 +100,9 @@ let noPush = hasFlag('--no-push', '-dnp');
42
100
  let push = noPush ? false : (hasFlag('--push', '-p') || config.autoPush);
43
101
  let generateChangelog = hasFlag('--changelog', '-c') || config.autoChangelog;
44
102
  const addAllFlag = getFlag('--all', '-a');
45
- let addMode = null; // Will be set to: 'tracked', 'all', 'interactive', 'patch', or null
46
- let promptForStaging = false; // If true, prompt user for staging mode
103
+ let addMode = null;
104
+ let promptForStaging = false;
47
105
  if (addAllFlag) {
48
- // If -a has a value, use it as the mode
49
106
  if (typeof addAllFlag === 'string') {
50
107
  const mode = addAllFlag.toLowerCase();
51
108
  if (['tracked', 'all', 'a', 'interactive', 'i', 'patch', 'p'].includes(mode)) {
@@ -54,11 +111,10 @@ if (addAllFlag) {
54
111
  else if (mode === 'p') addMode = 'patch';
55
112
  else addMode = mode;
56
113
  } else {
57
- console.error(`Error: Invalid add mode '${addAllFlag}'. Use: tracked, all, interactive (i), or patch (p)`);
114
+ logError(`Error: Invalid add mode '${addAllFlag}'. Use: tracked, all, interactive (i), or patch (p)`);
58
115
  process.exit(1);
59
116
  }
60
117
  } else {
61
- // If -a has no value, we'll prompt the user later
62
118
  promptForStaging = true;
63
119
  }
64
120
  }
@@ -83,11 +139,11 @@ async function main() {
83
139
  try {
84
140
  // Interactive mode if no message provided
85
141
  if (!message) {
86
- console.log('šŸ¤” Interactive mode\n');
142
+ log('šŸ¤” Interactive mode\n', 'cyan');
87
143
 
88
144
  message = await prompt('Commit message: ');
89
145
  if (!message) {
90
- console.error('Error: Commit message is required');
146
+ logError('Error: Commit message is required');
91
147
  process.exit(1);
92
148
  }
93
149
 
@@ -108,55 +164,54 @@ async function main() {
108
164
  const dryRunInput = await prompt('Dry run (preview only)? (y/n) [n]: ');
109
165
  dryRun = dryRunInput.toLowerCase() === 'y' || dryRunInput.toLowerCase() === 'yes';
110
166
 
111
- console.log(''); // Blank line before proceeding
167
+ log(''); // Blank line before proceeding
112
168
  }
113
169
 
114
170
  // Auto-detect version type from conventional commit format
115
171
  if (!customVersion && !getFlag('--type', '-t')) {
116
172
  if (message.startsWith('major:') || message.startsWith('MAJOR:')) {
117
173
  type = 'major';
118
- console.log('šŸ“ Auto-detected: major version bump');
174
+ log('šŸ“ Auto-detected: major version bump', 'cyan');
119
175
  } else if (message.startsWith('minor:') || message.startsWith('MINOR:')) {
120
176
  type = 'minor';
121
- console.log('šŸ“ Auto-detected: minor version bump');
177
+ log('šŸ“ Auto-detected: minor version bump', 'cyan');
122
178
  } else if (message.startsWith('patch:') || message.startsWith('PATCH:')) {
123
179
  type = 'patch';
124
- console.log('šŸ“ Auto-detected: patch version bump');
180
+ log('šŸ“ Auto-detected: patch version bump', 'cyan');
125
181
  } else if (message.startsWith('feat:') || message.startsWith('feature:')) {
126
182
  type = 'minor';
127
- console.log('šŸ“ Auto-detected: minor version bump (feature)');
183
+ log('šŸ“ Auto-detected: minor version bump (feature)', 'cyan');
128
184
  } else if (message.startsWith('fix:')) {
129
185
  type = 'patch';
130
- console.log('šŸ“ Auto-detected: patch version bump (fix)');
186
+ log('šŸ“ Auto-detected: patch version bump (fix)', 'cyan');
131
187
  } else if (message.includes('BREAKING') || message.startsWith('breaking:')) {
132
188
  type = 'major';
133
- console.log('šŸ“ Auto-detected: major version bump (breaking change)');
189
+ log('šŸ“ Auto-detected: major version bump (breaking change)', 'cyan');
134
190
  }
135
191
  }
136
192
 
137
193
  // Validate version type
138
194
  if (!customVersion && !['patch', 'minor', 'major'].includes(type)) {
139
- console.error('Error: Version type must be patch, minor, or major');
195
+ logError('Error: Version type must be patch, minor, or major');
140
196
  process.exit(1);
141
197
  }
142
198
 
143
199
  // PRE-FLIGHT CHECKS
144
- console.log('\nšŸ” Running pre-flight checks...\n');
200
+ log('\nšŸ” Running pre-flight checks...\n', 'cyan');
145
201
 
146
202
  // Check for uncommitted changes OR if user requested staging prompt
147
203
  if ((config.requireCleanWorkingDir && !addMode) || promptForStaging) {
148
204
  const status = execSync('git status --porcelain --untracked-files=no').toString().trim();
149
205
  if (status || promptForStaging) {
150
- // No files staged and changes exist - offer interactive selection
151
206
  if (status) {
152
- console.log('āš ļø You have uncommitted changes.\n');
207
+ log('āš ļø You have uncommitted changes.\n', 'yellow');
153
208
  }
154
- console.log('šŸ“ How would you like to stage files?\n');
155
- console.log(' 1. Tracked files only (git add -u)');
156
- console.log(' 2. All changes (git add -A)');
157
- console.log(' 3. Interactive selection (git add -i)');
158
- console.log(' 4. Patch mode (git add -p)');
159
- console.log(' 5. Skip staging (continue without staging)\n');
209
+ log('šŸ“ How would you like to stage files?\n');
210
+ log(' 1. Tracked files only (git add -u)');
211
+ log(' 2. All changes (git add -A)');
212
+ log(' 3. Interactive selection (git add -i)');
213
+ log(' 4. Patch mode (git add -p)');
214
+ log(' 5. Skip staging (continue without staging)\n');
160
215
 
161
216
  const choice = await prompt('Select [1-5]: ');
162
217
 
@@ -169,19 +224,19 @@ async function main() {
169
224
  } else if (choice === '4') {
170
225
  addMode = 'patch';
171
226
  } else if (choice === '5') {
172
- console.log('āš ļø Skipping file staging. Ensure files are staged manually.');
227
+ log('āš ļø Skipping file staging. Ensure files are staged manually.', 'yellow');
173
228
  } else {
174
- console.error('Invalid choice. Exiting.');
229
+ logError('Invalid choice. Exiting.');
175
230
  process.exit(1);
176
231
  }
177
- console.log('');
232
+ log('');
178
233
  }
179
234
  }
180
235
 
181
236
  // Check current branch
182
237
  const branch = execSync('git branch --show-current').toString().trim();
183
238
  if (branch !== 'main' && branch !== 'master') {
184
- console.log(`āš ļø Warning: You're on branch '${branch}', not main/master`);
239
+ log(`āš ļø Warning: You're on branch '${branch}', not main/master`, 'yellow');
185
240
  }
186
241
 
187
242
  // Check if remote exists
@@ -189,18 +244,18 @@ async function main() {
189
244
  execSync('git remote get-url origin', {stdio: 'pipe'});
190
245
  } catch {
191
246
  if (push) {
192
- console.error('āŒ Error: No remote repository configured, cannot push');
247
+ logError('āŒ Error: No remote repository configured, cannot push');
193
248
  process.exit(1);
194
249
  }
195
- console.log('āš ļø Warning: No remote repository configured');
250
+ log('āš ļø Warning: No remote repository configured', 'yellow');
196
251
  }
197
252
 
198
- console.log('āœ… Pre-flight checks passed\n');
253
+ log('āœ… Pre-flight checks passed\n', 'green');
199
254
 
200
255
  // DRY RUN MODE
201
256
  if (dryRun) {
202
- console.log('šŸ”¬ DRY RUN MODE - No changes will be made\n');
203
- console.log('Would perform the following actions:');
257
+ log('šŸ”¬ DRY RUN MODE - No changes will be made\n', 'yellow');
258
+ log('Would perform the following actions:');
204
259
 
205
260
  if (addMode) {
206
261
  const modeDescriptions = {
@@ -209,56 +264,51 @@ async function main() {
209
264
  'interactive': 'Interactive selection (git add -i)',
210
265
  'patch': 'Patch mode (git add -p)'
211
266
  };
212
- console.log(` 1. ${modeDescriptions[addMode]}`);
213
- }
214
-
215
- if (customVersion) {
216
- console.log(` 2. Set version to: ${customVersion}`);
217
- } else {
218
- console.log(` 2. Bump ${type} version`);
267
+ log(` 1. ${modeDescriptions[addMode]}`);
219
268
  }
220
269
 
221
- console.log(` 3. Commit with message: "${message}"`);
222
- console.log(` 4. Create git tag with annotation`);
270
+ log(` 2. Bump ${type} version`);
271
+ log(` 3. Commit with message: "${message}"`);
272
+ log(' 4. Create git tag with annotation');
223
273
 
224
274
  if (generateChangelog) {
225
- console.log(' 5. Update CHANGELOG.md');
275
+ log(' 5. Update CHANGELOG.md');
276
+ } else {
277
+ log(' 5. (Skipping changelog - use --changelog to enable)');
226
278
  }
227
279
 
228
280
  if (generateReleaseNotes) {
229
- console.log(' 6. Generate release notes file');
281
+ log(' 6. Generate release notes file');
282
+ } else {
283
+ log(' 6. (Skipping release notes - use --release to enable)');
230
284
  }
231
285
 
232
286
  if (push) {
233
- console.log(' 7. Push to remote with tags');
287
+ log(' 7. Push to remote with tags');
234
288
  } else {
235
- console.log(' 7. (Skipping push - use --push to enable)');
289
+ log(' 7. (Skipping push - use --push to enable)');
236
290
  }
237
291
 
238
- console.log('\nāœ“ Dry run complete. Use without -d to apply changes.');
292
+ log('\nāœ“ Dry run complete. Use without -d to apply changes.', 'green');
239
293
  process.exit(0);
240
294
  }
241
295
 
242
296
  // STAGE FILES if requested
243
297
  if (addMode) {
244
- console.log('šŸ“¦ Staging files...');
298
+ log('šŸ“¦ Staging files...', 'cyan');
245
299
 
246
300
  if (addMode === 'tracked') {
247
- // Only stage tracked files that have been modified/deleted
248
301
  execSync('git add -u', {stdio: 'inherit'});
249
302
  } else if (addMode === 'all') {
250
- // Stage all changes (respects .gitignore for new files)
251
303
  execSync('git add -A', {stdio: 'inherit'});
252
304
  } else if (addMode === 'interactive') {
253
- // Interactive staging
254
305
  execSync('git add -i', {stdio: 'inherit'});
255
306
  } else if (addMode === 'patch') {
256
- // Patch mode staging
257
307
  execSync('git add -p', {stdio: 'inherit'});
258
308
  }
259
309
  }
260
310
  // BUMP VERSION
261
- console.log(`\nšŸ”¼ Bumping version...`);
311
+ log(`\nšŸ”¼ Bumping version...`, 'cyan');
262
312
 
263
313
  // Get current version before bump
264
314
  const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
@@ -266,9 +316,9 @@ async function main() {
266
316
 
267
317
  // Always disable npm's git integration and handle it ourselves
268
318
  if (customVersion) {
269
- execSync(`npm version ${customVersion} --git-tag-version=false`, {stdio: 'inherit'});
319
+ execSync(`npm version ${customVersion} --git-tag-version=false`, {stdio: quietMode ? 'pipe' : 'inherit'});
270
320
  } else {
271
- execSync(`npm version ${type} --git-tag-version=false`, {stdio: 'inherit'});
321
+ execSync(`npm version ${type} --git-tag-version=false`, {stdio: quietMode ? 'pipe' : 'inherit'});
272
322
  }
273
323
 
274
324
  // Get new version
@@ -281,19 +331,16 @@ async function main() {
281
331
  }
282
332
 
283
333
  // Commit with user's message
284
- execSync(`git commit -m "${message}"`, {stdio: 'inherit'});
334
+ execSync(`git commit -m "${message}"`, {stdio: quietMode ? 'pipe' : 'inherit'});
285
335
 
286
336
  // Create annotated tag
287
- execSync(`git tag -a v${newVersion} -m "Version ${newVersion}\n\n${message}"`, {stdio: 'pipe'});
288
-
289
- // ADD GIT TAG ANNOTATION (keeping console.log for UX)
290
- console.log('šŸ·ļø Adding tag annotation...');
337
+ log('šŸ·ļø Adding tag annotation...', 'cyan');
291
338
  const tagMessage = `Version ${newVersion}\n\n${message}`;
292
- execSync(`git tag -a v${newVersion} -f -m "${tagMessage}"`, {stdio: 'pipe'});
339
+ execSync(`git tag -a ${config.tagPrefix}${newVersion} -m "${tagMessage}"`, {stdio: 'pipe'});
293
340
 
294
341
  // GENERATE CHANGELOG
295
342
  if (generateChangelog) {
296
- console.log('šŸ“„ Updating CHANGELOG.md...');
343
+ log('šŸ“„ Updating CHANGELOG.md...', 'cyan');
297
344
  const date = new Date().toISOString().split('T')[0];
298
345
  const changelogEntry = `\n## [${newVersion}] - ${date}\n- ${message}\n`;
299
346
 
@@ -316,8 +363,8 @@ async function main() {
316
363
 
317
364
  // GENERATE RELEASE NOTES
318
365
  if (generateReleaseNotes) {
319
- console.log('šŸ“‹ Generating release notes...');
320
- const releaseNotes = `# Release v${newVersion}
366
+ log('šŸ“‹ Generating release notes...', 'cyan');
367
+ const releaseNotes = `# Release ${config.tagPrefix}${newVersion}
321
368
 
322
369
  Released: ${new Date().toISOString().split('T')[0]}
323
370
 
@@ -333,50 +380,52 @@ npm install ${packageJson.name}@${newVersion}
333
380
  See [CHANGELOG.md](./CHANGELOG.md) for complete version history.
334
381
  `;
335
382
 
336
- const filename = `release-notes-v${newVersion}.md`;
383
+ const filename = `release-notes-${config.tagPrefix}${newVersion}.md`;
337
384
  fs.writeFileSync(filename, releaseNotes);
338
- console.log(` Created: ${filename}`);
385
+ log(` Created: ${filename}`);
339
386
  }
340
387
 
341
388
  // PUSH TO REMOTE
342
389
  if (push) {
343
- console.log('šŸš€ Pushing to remote...');
344
- execSync('git push --follow-tags', {stdio: 'inherit'});
390
+ log('šŸš€ Pushing to remote...', 'cyan');
391
+ execSync('git push --follow-tags', {stdio: quietMode ? 'pipe' : 'inherit'});
345
392
  }
346
393
 
347
394
  // STATS/SUMMARY
348
- console.log('\nšŸ“Š Summary:');
349
- console.log('━'.repeat(50));
395
+ log('\nšŸ“Š Summary:', 'cyan');
396
+ log('━'.repeat(50), 'gray');
350
397
 
351
- console.log(`\nšŸ“¦ Version: ${oldVersion} → ${newVersion}`);
352
- console.log(`šŸ’¬ Message: ${message}`);
353
- console.log(`šŸ·ļø Tag: v${newVersion}`);
354
- console.log(`🌿 Branch: ${branch}`);
398
+ log(`\nšŸ“¦ Version: ${oldVersion} → ${newVersion}`, 'green');
399
+ log(`šŸ’¬ Message: ${message}`);
400
+ log(`šŸ·ļø Tag: ${config.tagPrefix}${newVersion}`);
401
+ log(`🌿 Branch: ${branch}`);
355
402
 
356
403
  if (generateChangelog) {
357
- console.log(`šŸ“„ Changelog: Updated`);
404
+ log(`šŸ“„ Changelog: Updated`);
358
405
  }
359
406
 
360
407
  if (generateReleaseNotes) {
361
- console.log(`šŸ“‹ Release notes: Generated`);
408
+ log(`šŸ“‹ Release notes: Generated`);
362
409
  }
363
410
 
364
411
  if (push) {
365
- console.log(`šŸš€ Remote: Pushed with tags`);
412
+ log(`šŸš€ Remote: Pushed with tags`, 'green');
366
413
  } else {
367
- console.log(`šŸ“ Remote: Not pushed (use --push to enable)`);
414
+ log(`šŸ“ Remote: Not pushed (use --push to enable)`, 'gray');
368
415
  }
369
416
 
370
417
  // Show files changed
371
- console.log('\nšŸ“ Files changed:');
372
- const diff = execSync('git diff HEAD~1 --stat').toString();
373
- console.log(diff);
418
+ if (!quietMode) {
419
+ log('\nšŸ“ Files changed:');
420
+ const diff = execSync('git diff HEAD~1 --stat').toString();
421
+ console.log(diff);
422
+ }
374
423
 
375
- console.log('━'.repeat(50));
376
- console.log('\nāœ… Version bump complete!\n');
424
+ log('━'.repeat(50), 'gray');
425
+ log('\nāœ… Version bump complete!\n', 'green');
377
426
 
378
427
  } catch (error) {
379
- console.error('\nāŒ Error:', error.message);
428
+ logError('\nāŒ Error: ' + error.message);
380
429
  process.exit(1);
381
430
  }
382
431
  }
@@ -394,6 +443,7 @@ Options:
394
443
  -m, --message <msg> Commit message (required, or use interactive mode)
395
444
  -t, --type <type> Version type: patch, minor, major (auto-detected from message)
396
445
  -v, --version <ver> Set specific version (e.g., 2.0.0-beta.1)
446
+ -V, --version Show vnxt version
397
447
  -p, --push Push to remote with tags
398
448
  -dnp, --no-push Prevent auto-push (overrides config)
399
449
  -c, --changelog Update CHANGELOG.md
@@ -402,6 +452,7 @@ Options:
402
452
  Modes: tracked (default), all, interactive (i), patch (p)
403
453
  If no mode specified, prompts interactively
404
454
  -r, --release Generate release notes file
455
+ -q, --quiet Minimal output (errors only)
405
456
  -h, --help Show this help message
406
457
 
407
458
  Auto-detection:
@@ -420,10 +471,12 @@ Configuration:
420
471
  "requireCleanWorkingDir": false,
421
472
  "autoPush": true,
422
473
  "defaultStageMode": "tracked",
423
- "tagPrefix": "v"
474
+ "tagPrefix": "v",
475
+ "colors": true
424
476
  }
425
477
 
426
478
  Examples:
479
+ vx -V # Show version
427
480
  vx -m "fix: resolve bug" # Auto-pushes with autoPush: true
428
481
  vx -m "feat: add new feature" # Auto-pushes with autoPush: true
429
482
  vx -m "fix: bug" -dnp # Don't push (override)
@@ -434,6 +487,7 @@ Examples:
434
487
  vx -m "fix: bug" -a all # Stage all changes
435
488
  vx -m "fix: bug" -a i # Interactive git add
436
489
  vx -m "fix: bug" -a p # Patch mode
490
+ vx -m "fix: bug" -q # Quiet mode (minimal output)
437
491
  vx # Interactive mode
438
492
  `);
439
493
  process.exit(0);