claude-git-hooks 2.14.1 → 2.15.5

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +118 -3
  2. package/LICENSE +20 -20
  3. package/README.md +4 -1
  4. package/bin/claude-hooks +84 -84
  5. package/lib/commands/analyze-diff.js +0 -1
  6. package/lib/commands/bump-version.js +23 -22
  7. package/lib/commands/create-pr.js +157 -15
  8. package/lib/commands/debug.js +1 -1
  9. package/lib/commands/helpers.js +11 -6
  10. package/lib/commands/install.js +7 -8
  11. package/lib/commands/migrate-config.js +24 -2
  12. package/lib/commands/setup-github.js +1 -1
  13. package/lib/commands/update.js +1 -1
  14. package/lib/config.js +0 -4
  15. package/lib/hooks/prepare-commit-msg.js +2 -2
  16. package/lib/utils/changelog-generator.js +6 -8
  17. package/lib/utils/claude-client.js +7 -6
  18. package/lib/utils/claude-diagnostics.js +14 -21
  19. package/lib/utils/file-operations.js +1 -1
  20. package/lib/utils/file-utils.js +0 -1
  21. package/lib/utils/git-operations.js +0 -1
  22. package/lib/utils/github-api.js +3 -3
  23. package/lib/utils/github-client.js +2 -2
  24. package/lib/utils/installation-diagnostics.js +1 -1
  25. package/lib/utils/prompt-builder.js +4 -6
  26. package/lib/utils/sanitize.js +13 -14
  27. package/lib/utils/task-id.js +18 -20
  28. package/lib/utils/telemetry.js +5 -7
  29. package/package.json +13 -5
  30. package/templates/config.advanced.example.json +113 -113
  31. package/templates/pre-commit +7 -0
  32. package/templates/presets/ai/config.json +5 -5
  33. package/templates/presets/backend/config.json +5 -5
  34. package/templates/presets/backend/preset.json +49 -49
  35. package/templates/presets/database/config.json +5 -5
  36. package/templates/presets/database/preset.json +38 -38
  37. package/templates/presets/default/config.json +5 -5
  38. package/templates/presets/default/preset.json +53 -53
  39. package/templates/presets/frontend/config.json +5 -5
  40. package/templates/presets/frontend/preset.json +50 -50
  41. package/templates/presets/fullstack/config.json +5 -5
  42. package/templates/presets/fullstack/preset.json +55 -55
package/CHANGELOG.md CHANGED
@@ -5,58 +5,173 @@ Todos los cambios notables en este proyecto se documentarán en este archivo.
5
5
  El formato está basado en [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  y este proyecto adhiere a [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.15.5] - 2026-02-12
9
+
10
+ ### ✨ Added
11
+ - Added comprehensive CI-safe integration test suite that runs without Claude CLI dependency
12
+ - Added new test scripts: `test:integration:ci` for CI environments and `test:changed` for testing only modified files
13
+
14
+ ### 🔧 Changed
15
+ - Optimized CI matrix to run full OS/Node.js combinations only on push events, reducing PR build times
16
+ - Refactored integration tests to verify installation workflow, hook lifecycle, config persistence, and CLI routing
17
+ - Improved timeout handling in Claude CLI client by clearing timeouts consistently on all exit paths
18
+ - Simplified template variable replacement in prompt-builder with cleaner regex handling
19
+ - Reduced Jest verbosity and coverage reporters for cleaner CI output
20
+
21
+ ### 🐛 Fixed
22
+ - Fixed potential timeout leak in claude-client.js where timeouts were not cleared on error or stdin failures
23
+
24
+ ### 🗑️ Removed
25
+ - Removed unused variables and parameters across multiple modules (analyze-diff, create-pr, install, config, changelog-generator, claude-client, claude-diagnostics, file-utils, git-operations, prompt-builder)
26
+
27
+
28
+ ## [2.15.4] - 2026-02-11
29
+
30
+ ### ✨ Added
31
+ - Added comprehensive unit tests for claude-diagnostics.js covering error detection, formatting, and recovery classification
32
+ - Added unit tests for file-utils.js covering directory creation and file writing operations
33
+
34
+
35
+ ## [2.15.3] - 2026-02-10
36
+
37
+ ### ✨ Added
38
+ - Unit tests for `generate-changelog.js` command covering CHANGELOG generation, version detection, and error handling
39
+ - Unit tests for `github-client.js` covering CODEOWNERS parsing, reviewer detection, and GitHub repo parsing
40
+ - Unit tests for `hooks.js` command covering enable, disable, status, and uninstall operations
41
+
42
+
43
+ ## [2.15.2] - 2026-02-10
44
+
45
+ ### 🔧 Changed
46
+ - The bump-version command now uses the configured default branch (from github.pr.defaultBase) in the 'Next steps' output instead of hardcoded 'main'
47
+
48
+ ### 🐛 Fixed
49
+ - Fixed cross-platform path assertions in unit tests to use partial matching instead of exact paths, improving Windows compatibility
50
+
51
+
52
+ ## [2.15.1] - 2026-02-10
53
+
54
+ ### 🐛 Fixed
55
+
56
+ - Fixed cross-platform test compatibility for Windows environments by updating path assertions to use partial matching instead of exact Unix paths
57
+ - Fixed CI workflow to properly skip integration tests that require Claude CLI, with clear documentation about manual testing requirements
58
+ - Fixed Unix-specific tests to be skipped on Windows platform
59
+ - Fixed executable file permissions for bin/claude-hooks and hook templates (pre-commit, prepare-commit-msg)
60
+
61
+ ## [2.15.0] - 2026-02-10
62
+
63
+ ### ✨ Added
64
+
65
+ - Comprehensive testing suite with GitHub Actions CI workflow including lint, smoke tests, unit tests, integration tests, and dogfooding checks
66
+ - Cross-platform unit tests running on Ubuntu, Windows, and macOS with Node.js 18, 20, and 22
67
+ - Codecov integration for coverage reporting on unit and integration tests
68
+ - Per-module coverage thresholds for critical modules (config.js, helpers.js, git-operations.js, preset-loader.js, analysis-engine.js)
69
+
70
+ ### 🔧 Changed
71
+
72
+ - Updated ESLint configuration from ECMAScript 2021 to 2022
73
+ - Improved Jest configuration with separate coverage reporters (text, text-summary, lcov, html) and adjusted global coverage thresholds
74
+ - Updated .gitignore to track test files (\*.test.js) while ignoring coverage directory
75
+
76
+ ### 🐛 Fixed
77
+
78
+ - Fixed ESLint linting issues across utility and command modules including string concatenation, switch case indentation, and arrow function formatting (#68)
79
+
80
+ ## [2.14.4] - 2026-02-09
81
+
82
+ ### 🔧 Changed
83
+
84
+ - The migrate-config command now detects and fixes incorrectly placed preset fields in config overrides
85
+
86
+ ### 🐛 Fixed
87
+
88
+ - Fixed preset field being incorrectly placed inside overrides when using --set-preset command (#66)
89
+
90
+ ## [2.14.3] - 2026-02-06
91
+
92
+ ### 🔧 Changed
93
+
94
+ - The bump-version command now uses the configured default branch (from github.pr.defaultBase) in the 'Next steps' output instead of hardcoded 'main'
95
+
96
+ ## [2.14.2] - 2026-02-06
97
+
98
+ ### ✨ Added
99
+
100
+ - New `--push` flag for `bump-version` command to explicitly push tags to remote when desired
101
+
102
+ ### 🔧 Changed
103
+
104
+ - Changed `bump-version` default behavior to keep tags local instead of automatically pushing to remote (#65)
105
+ - Tags are now pushed by `create-pr` command or manually with `--push` flag, providing better control over the release workflow
106
+ - Updated documentation in README.md, README-NPM.md, and CLAUDE.md to reflect new tag push behavior
107
+
108
+ ### ⚠️ Deprecated
109
+
110
+ - The `--no-push` flag for `bump-version` is no longer needed as tags now stay local by default
111
+
112
+ ### 🗑️ Removed
113
+
114
+ - Removed RFC-001 documentation file (pr-metadata-engine-refactor.md) as the refactor has been completed
115
+
8
116
  ## [2.14.1] - 2026-02-06
9
117
 
10
118
  ### 🔧 Changed
119
+
11
120
  - Improved `bump-version` command workflow - now automatically stages and commits version changes with conventional commit format before tag creation
12
121
  - Enhanced `bump-version` command flexibility - added `--no-commit` flag for manual workflows where users prefer to commit changes themselves
13
122
  - Improved error handling in `bump-version` - provides clearer guidance when staging or committing fails, with manual fallback instructions
14
123
  - Enhanced next-steps guidance in `bump-version` output - adapts instructions based on flags used (--no-commit, --no-push, --no-tag)
15
124
 
16
125
  ### 🐛 Fixed
126
+
17
127
  - Fixed `bump-version` workflow inconsistency - prevented tag creation when using `--no-commit` flag, as tags should only be created after changes are committed
18
128
  - Fixed potential git history issues - version bump commits now use `--no-verify` flag to bypass pre-commit hooks and prevent circular execution
19
129
 
20
130
  ### 🗑️ Removed
21
- - Removed redundant fallback warnings from `analyze-diff` and `create-pr` commands - warnings were unnecessary as base branch resolution now throws clear errors with suggestions instead
22
131
 
132
+ - Removed redundant fallback warnings from `analyze-diff` and `create-pr` commands - warnings were unnecessary as base branch resolution now throws clear errors with suggestions instead
23
133
 
24
134
  ## [2.14.0] - 2026-02-06
25
135
 
26
136
  ### ✨ Added
137
+
27
138
  - PR metadata engine (`pr-metadata-engine.js`) - centralized module for generating PR titles, descriptions, and test plans from branch diffs with timeout resilience (#63)
28
139
  - Tiered diff reduction system - automatically truncates large diffs using context reduction, proportional budgets, and stat-only summaries to prevent timeouts
29
140
  - Extended git operations - added `fetchRemote()`, `branchExists()`, `resolveBaseBranch()`, `getChangedFilesBetweenRefs()`, `getDiffBetweenRefs()`, and `getCommitsBetweenRefs()` to `git-operations.js`
30
141
  - RFC-001 documentation - comprehensive design specification for PR metadata engine refactor with timeout resilience strategy
31
142
 
32
143
  ### 🔧 Changed
144
+
33
145
  - Refactored `analyze-diff` command to use shared PR metadata engine - reduced from 262 to ~80 lines by eliminating duplicate git logic
34
146
  - Refactored `create-pr` command to use shared PR metadata engine - eliminated duplicate diff extraction logic (lines 340-420)
35
147
  - Improved timeout error handling - timeout errors now include `errorInfo` and are classified as recoverable for automatic retry with exponential backoff
36
148
  - Updated CLAUDE.md with PR metadata engine architecture, new git operations exports, and tiered diff reduction strategy
37
149
 
38
150
  ### 🐛 Fixed
151
+
39
152
  - Fixed timeout failures in `analyze-diff` for large diffs - now uses tiered reduction instead of monolithic diff processing
40
153
  - Fixed inconsistent behavior between `analyze-diff` and `create-pr` commands - both now share identical analysis logic via unified engine
41
154
 
42
155
  ### 🗑️ Removed
43
- - Removed unreliable `SUBAGENT_INSTRUCTION` text hint - replaced with deterministic tiered diff reduction for parallel processing
44
156
 
157
+ - Removed unreliable `SUBAGENT_INSTRUCTION` text hint - replaced with deterministic tiered diff reduction for parallel processing
45
158
 
46
159
  ## [2.13.0] - 2026-02-05
47
160
 
48
161
  ### ✨ Added
162
+
49
163
  - Interactive analysis command `claude-hooks analyze` - review all issues (INFO to BLOCKER) interactively before committing with auto-commit option
50
164
  - Shared analysis engine module (`analysis-engine.js`) - centralized file data building, analysis orchestration, and results display for both pre-commit hooks and interactive analysis
51
165
  - Support for version files in subdirectories - automatically searches parent directories when version files not found in repo root
52
166
  - Auto-commit functionality after interactive analysis - creates commit with auto-generated message when user confirms
53
167
 
54
168
  ### 🔧 Changed
169
+
55
170
  - Improved version detection logic for pom.xml files - enhanced reliability of version extraction in Maven projects
56
171
 
57
172
  ### 🐛 Fixed
58
- - Fixed version search logic for pom.xml files - corrected parsing issues in Maven version detection
59
173
 
174
+ - Fixed version search logic for pom.xml files - corrected parsing issues in Maven version detection
60
175
 
61
176
  ## [2.12.0] - 2026-02-03
62
177
 
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Pablo Rovito
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Pablo Rovito
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
package/README.md CHANGED
@@ -111,6 +111,9 @@ claude-hooks bump-version major --update-changelog
111
111
  # Preview without applying
112
112
  claude-hooks bump-version patch --dry-run
113
113
 
114
+ # Push tag immediately (otherwise pushed by create-pr)
115
+ claude-hooks bump-version patch --push
116
+
114
117
  # Manual workflow (skip automatic commit)
115
118
  claude-hooks bump-version patch --no-commit
116
119
  ```
@@ -121,7 +124,7 @@ claude-hooks bump-version patch --no-commit
121
124
  - Generates CHANGELOG entry with Claude (analyzes commits)
122
125
  - Commits changes automatically with conventional commit format
123
126
  - Creates annotated Git tag with `v` prefix (e.g., `v2.7.0`)
124
- - Pushes tag to remote automatically
127
+ - Tags stay local by default (use `--push` to push immediately, or let `create-pr` handle it)
125
128
 
126
129
  **Version workflow:**
127
130
  ```
package/bin/claude-hooks CHANGED
@@ -34,90 +34,90 @@ async function main() {
34
34
  const command = args[0];
35
35
 
36
36
  switch (command) {
37
- case 'install':
38
- await runInstall(args.slice(1));
39
- break;
40
- case 'update':
41
- await runUpdate();
42
- break;
43
- case 'uninstall':
44
- runUninstall();
45
- break;
46
- case 'enable':
47
- runEnable(args[1]);
48
- break;
49
- case 'disable':
50
- runDisable(args[1]);
51
- break;
52
- case 'status':
53
- runStatus();
54
- break;
55
- case 'analyze':
56
- await runAnalyze({
57
- staged: !args.includes('--unstaged') && !args.includes('--all'),
58
- unstaged: args.includes('--unstaged'),
59
- all: args.includes('--all')
60
- });
61
- break;
62
- case 'analyze-diff':
63
- await runAnalyzeDiff(args.slice(1));
64
- break;
65
- case 'create-pr':
66
- await runCreatePr(args.slice(1));
67
- break;
68
- case 'setup-github':
69
- await runSetupGitHub();
70
- break;
71
- case 'presets':
72
- await runShowPresets();
73
- break;
74
- case '--set-preset':
75
- await runSetPreset(args[1]);
76
- break;
77
- case 'preset':
78
- // Handle subcommands: preset current
79
- if (args[1] === 'current') {
80
- await runCurrentPreset();
81
- } else {
82
- error(`Unknown preset subcommand: ${args[1]}`);
83
- }
84
- break;
85
- case 'migrate-config':
86
- await runMigrateConfig();
87
- break;
88
- case 'bump-version':
89
- await runBumpVersion(args.slice(1));
90
- break;
91
- case 'generate-changelog':
92
- await runGenerateChangelog(args.slice(1));
93
- break;
94
- case 'telemetry':
95
- // Handle subcommands: telemetry show, telemetry clear
96
- if (args[1] === 'show' || args[1] === undefined) {
97
- await runShowTelemetry();
98
- } else if (args[1] === 'clear') {
99
- await runClearTelemetry();
100
- } else {
101
- error(`Unknown telemetry subcommand: ${args[1]}`);
102
- }
103
- break;
104
- case '--debug':
105
- await runSetDebug(args[1]);
106
- break;
107
- case '--version':
108
- case '-v':
109
- case 'version':
110
- runShowVersion();
111
- break;
112
- case 'help':
113
- case '--help':
114
- case '-h':
115
- case undefined:
116
- runShowHelp();
117
- break;
118
- default:
119
- error(`Unknown command: ${command}`);
120
- runShowHelp();
37
+ case 'install':
38
+ await runInstall(args.slice(1));
39
+ break;
40
+ case 'update':
41
+ await runUpdate();
42
+ break;
43
+ case 'uninstall':
44
+ runUninstall();
45
+ break;
46
+ case 'enable':
47
+ runEnable(args[1]);
48
+ break;
49
+ case 'disable':
50
+ runDisable(args[1]);
51
+ break;
52
+ case 'status':
53
+ runStatus();
54
+ break;
55
+ case 'analyze':
56
+ await runAnalyze({
57
+ staged: !args.includes('--unstaged') && !args.includes('--all'),
58
+ unstaged: args.includes('--unstaged'),
59
+ all: args.includes('--all')
60
+ });
61
+ break;
62
+ case 'analyze-diff':
63
+ await runAnalyzeDiff(args.slice(1));
64
+ break;
65
+ case 'create-pr':
66
+ await runCreatePr(args.slice(1));
67
+ break;
68
+ case 'setup-github':
69
+ await runSetupGitHub();
70
+ break;
71
+ case 'presets':
72
+ await runShowPresets();
73
+ break;
74
+ case '--set-preset':
75
+ await runSetPreset(args[1]);
76
+ break;
77
+ case 'preset':
78
+ // Handle subcommands: preset current
79
+ if (args[1] === 'current') {
80
+ await runCurrentPreset();
81
+ } else {
82
+ error(`Unknown preset subcommand: ${args[1]}`);
83
+ }
84
+ break;
85
+ case 'migrate-config':
86
+ await runMigrateConfig();
87
+ break;
88
+ case 'bump-version':
89
+ await runBumpVersion(args.slice(1));
90
+ break;
91
+ case 'generate-changelog':
92
+ await runGenerateChangelog(args.slice(1));
93
+ break;
94
+ case 'telemetry':
95
+ // Handle subcommands: telemetry show, telemetry clear
96
+ if (args[1] === 'show' || args[1] === undefined) {
97
+ await runShowTelemetry();
98
+ } else if (args[1] === 'clear') {
99
+ await runClearTelemetry();
100
+ } else {
101
+ error(`Unknown telemetry subcommand: ${args[1]}`);
102
+ }
103
+ break;
104
+ case '--debug':
105
+ await runSetDebug(args[1]);
106
+ break;
107
+ case '--version':
108
+ case '-v':
109
+ case 'version':
110
+ runShowVersion();
111
+ break;
112
+ case 'help':
113
+ case '--help':
114
+ case '-h':
115
+ case undefined:
116
+ runShowHelp();
117
+ break;
118
+ default:
119
+ error(`Unknown command: ${command}`);
120
+ runShowHelp();
121
121
  }
122
122
  }
123
123
 
@@ -11,7 +11,6 @@ import {
11
11
  colors,
12
12
  error,
13
13
  info,
14
- warning,
15
14
  checkGitRepo
16
15
  } from './helpers.js';
17
16
 
@@ -10,7 +10,7 @@
10
10
  * 5. [Optional] Generate and update CHANGELOG
11
11
  * 6. Stage and commit changes (skipped with --no-commit)
12
12
  * 7. Create annotated Git tag (skipped with --no-tag or --no-commit)
13
- * 8. Push tag to remote (skipped with --no-push)
13
+ * 8. Push tag to remote (only if --push flag provided, otherwise pushed by create-pr)
14
14
  */
15
15
 
16
16
  import { execSync } from 'child_process';
@@ -21,7 +21,6 @@ import {
21
21
  getCurrentVersion,
22
22
  incrementVersion,
23
23
  updateVersion,
24
- parseVersion,
25
24
  getDiscoveredPaths
26
25
  } from '../utils/version-manager.js';
27
26
  import {
@@ -48,9 +47,7 @@ import logger from '../utils/logger.js';
48
47
  import {
49
48
  colors,
50
49
  error,
51
- success,
52
50
  info,
53
- warning,
54
51
  checkGitRepo
55
52
  } from './helpers.js';
56
53
 
@@ -116,7 +113,7 @@ function validatePrerequisites() {
116
113
  * Why: Extracts bump type and options from CLI args
117
114
  *
118
115
  * @param {Array<string>} args - CLI arguments
119
- * @returns {Object} Parsed args: { bumpType, suffix, updateChangelog, baseBranch, dryRun, noTag, noPush }
116
+ * @returns {Object} Parsed args: { bumpType, suffix, updateChangelog, baseBranch, dryRun, noTag, push, noCommit }
120
117
  */
121
118
  function parseArguments(args) {
122
119
  logger.debug('bump-version - parseArguments', 'Parsing arguments', { args });
@@ -128,7 +125,7 @@ function parseArguments(args) {
128
125
  baseBranch: 'main',
129
126
  dryRun: false,
130
127
  noTag: false,
131
- noPush: false,
128
+ push: false, // Changed: default to NOT push (use --push to enable)
132
129
  noCommit: false
133
130
  };
134
131
 
@@ -160,8 +157,8 @@ function parseArguments(args) {
160
157
  parsed.dryRun = true;
161
158
  } else if (arg === '--no-tag') {
162
159
  parsed.noTag = true;
163
- } else if (arg === '--no-push') {
164
- parsed.noPush = true;
160
+ } else if (arg === '--push') {
161
+ parsed.push = true;
165
162
  } else if (arg === '--no-commit') {
166
163
  parsed.noCommit = true;
167
164
  }
@@ -223,7 +220,7 @@ export async function runBumpVersion(args) {
223
220
  console.log(' --update-changelog [branch] Generate CHANGELOG entry (default branch: main)');
224
221
  console.log(' --dry-run Preview changes without applying');
225
222
  console.log(' --no-tag Skip Git tag creation');
226
- console.log(' --no-push Create tag but don\'t push to remote');
223
+ console.log(' --push Push tag to remote (default: tags stay local)');
227
224
  console.log(' --no-commit Skip automatic commit (manual workflow)');
228
225
  console.log('');
229
226
  console.log('Examples:');
@@ -348,6 +345,11 @@ export async function runBumpVersion(args) {
348
345
  console.log('');
349
346
 
350
347
  try {
348
+ // Load config for default branch
349
+ const config = await getConfig();
350
+ const defaultBranch = config.github?.pr?.defaultBase || '{target-branch}';
351
+ logger.debug('bump-version', 'Default branch for PR', { defaultBranch });
352
+
351
353
  // Step 4: Update version files
352
354
  logger.debug('bump-version', 'Step 4: Updating version files');
353
355
  showInfo('Updating version files...');
@@ -364,7 +366,6 @@ export async function runBumpVersion(args) {
364
366
  logger.debug('bump-version', 'Step 5: Generating CHANGELOG');
365
367
  showInfo('Generating CHANGELOG entry...');
366
368
 
367
- const config = await getConfig();
368
369
  const isReleaseVersion = !options.suffix; // Final version if no suffix
369
370
 
370
371
  const changelogResult = await generateChangelogEntry({
@@ -494,9 +495,9 @@ export async function runBumpVersion(args) {
494
495
  showSuccess(`✓ Tag created: ${tagName}`);
495
496
  console.log('');
496
497
 
497
- // Step 7: Push tag (if not disabled)
498
- if (!options.noPush) {
499
- logger.debug('bump-version', 'Step 7: Pushing tag to remote');
498
+ // Step 8: Push tag (if --push flag provided)
499
+ if (options.push) {
500
+ logger.debug('bump-version', 'Step 8: Pushing tag to remote');
500
501
  showInfo('Pushing tag to remote...');
501
502
 
502
503
  const pushResult = pushTags(null, tagName);
@@ -510,10 +511,10 @@ export async function runBumpVersion(args) {
510
511
  console.log(` git push origin ${tagName}`);
511
512
  }
512
513
  } else {
513
- showInfo('Tag push skipped (--no-push)');
514
+ showInfo('Tag created locally (use --push to push immediately)');
514
515
  console.log('');
515
- console.log('To push the tag later:');
516
- console.log(` git push origin ${tagName}`);
516
+ console.log('Tag will be pushed automatically when you run:');
517
+ console.log(' claude-hooks create-pr [branch]');
517
518
  }
518
519
  } else {
519
520
  showError(`Failed to create tag: ${tagResult.error}`);
@@ -546,18 +547,18 @@ export async function runBumpVersion(args) {
546
547
  console.log(` 4. Create tag: git tag -a ${tagName} -m "Release version ${newVersion}"`);
547
548
  console.log(` 5. Push: git push origin $(git branch --show-current) ${tagName}`);
548
549
  console.log('');
549
- } else if (commitCreated && !options.noTag && !options.noPush) {
550
- console.log('All done! Changes committed and tag pushed to remote.');
550
+ } else if (commitCreated && !options.noTag && options.push) {
551
+ console.log('All done! Changes committed, tagged, and pushed to remote.');
551
552
  console.log('');
552
553
  console.log('Next steps:');
553
- console.log(' 1. Create PR: claude-hooks create-pr main');
554
+ console.log(` 1. Create PR: claude-hooks create-pr ${defaultBranch}`);
554
555
  console.log('');
555
556
  } else {
556
557
  console.log('Next steps:');
557
- if (commitCreated && options.noPush) {
558
- console.log(` 1. Push changes: git push origin $(git branch --show-current) ${tagName}`);
558
+ if (commitCreated && !options.push) {
559
+ console.log(` 1. Create PR: claude-hooks create-pr ${defaultBranch}`);
560
+ console.log(' (will automatically push tag during PR creation)');
559
561
  }
560
- console.log(' 2. Create PR: claude-hooks create-pr main');
561
562
  console.log('');
562
563
  }
563
564