@ksw8954/git-ai-commit 1.0.12 → 1.1.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.1 - 2026-01-07
4
+
5
+ ### Bug Fixes
6
+ - Fix zsh completion not working due to fpath added after compinit
7
+ - Fix install-completion to insert fpath before compinit in zshrc
8
+ - Fix uninstall-completion to properly remove fpath line
9
+
10
+ ## 1.1.0 - 2026-01-06
11
+
12
+ ### New Features
13
+ - Add `completion` command for bash/zsh shell auto-completion
14
+ - Add `make install-completion` and `make uninstall-completion` targets
15
+
16
+ ### Improvements
17
+ - Change tag message format to GitHub Release style (title + categorized notes)
18
+
3
19
  ## 1.0.11 - 2025-12-29
4
20
  - Default to `max_completion_tokens` and retry with `max_tokens` if unsupported.
5
21
  - Remove `temperature` from API requests to rely on model defaults.
package/Makefile CHANGED
@@ -1,4 +1,4 @@
1
- .PHONY: install build dev lint test typecheck clean uninstall link unlink version publish install-package
1
+ .PHONY: install build dev lint test typecheck clean uninstall link unlink version publish install-package install-completion uninstall-completion
2
2
 
3
3
  install: ## Install dependencies and build the project
4
4
  npm install
@@ -42,3 +42,81 @@ publish: build ## Publish the package to npm (ensure you're logged in)
42
42
 
43
43
  install-package: ## Install this package globally via npm
44
44
  npm i -g @ksw8954/git-ai-commit
45
+
46
+ install-completion: ## Install shell completion for current shell (bash/zsh)
47
+ @CURRENT_SHELL=$$(basename "$$SHELL"); \
48
+ if [ "$$CURRENT_SHELL" = "zsh" ]; then \
49
+ COMP_DIR="$$HOME/.zsh/completions"; \
50
+ COMP_FILE="$$COMP_DIR/_git-ai-commit"; \
51
+ RCFILE="$$HOME/.zshrc"; \
52
+ mkdir -p "$$COMP_DIR"; \
53
+ git-ai-commit completion zsh > "$$COMP_FILE"; \
54
+ echo "Completion file created: $$COMP_FILE"; \
55
+ if ! grep -q 'fpath=.*\.zsh/completions' "$$RCFILE" 2>/dev/null; then \
56
+ if grep -q 'autoload.*compinit' "$$RCFILE" 2>/dev/null; then \
57
+ sed -i.bak '/autoload.*compinit/i\
58
+ fpath=(~/.zsh/completions $$fpath) # git-ai-commit completion\
59
+ ' "$$RCFILE" && rm -f "$$RCFILE.bak"; \
60
+ echo "Added fpath before compinit in $$RCFILE"; \
61
+ else \
62
+ echo "" >> "$$RCFILE"; \
63
+ echo "# git-ai-commit shell completion" >> "$$RCFILE"; \
64
+ echo 'fpath=(~/.zsh/completions $$fpath)' >> "$$RCFILE"; \
65
+ echo 'autoload -Uz compinit && compinit' >> "$$RCFILE"; \
66
+ echo "Added fpath and compinit to $$RCFILE"; \
67
+ fi; \
68
+ fi; \
69
+ echo "Restart your shell or run: exec zsh"; \
70
+ elif [ "$$CURRENT_SHELL" = "bash" ]; then \
71
+ if [ -f "$$HOME/.bash_profile" ]; then \
72
+ RCFILE="$$HOME/.bash_profile"; \
73
+ else \
74
+ RCFILE="$$HOME/.bashrc"; \
75
+ fi; \
76
+ COMPLETION_LINE='eval "$$(git-ai-commit completion bash)"'; \
77
+ if grep -q "git-ai-commit completion" "$$RCFILE" 2>/dev/null; then \
78
+ echo "Completion already installed in $$RCFILE"; \
79
+ else \
80
+ echo "" >> "$$RCFILE"; \
81
+ echo "# git-ai-commit shell completion" >> "$$RCFILE"; \
82
+ echo "$$COMPLETION_LINE" >> "$$RCFILE"; \
83
+ echo "Completion installed in $$RCFILE"; \
84
+ echo "Run 'source $$RCFILE' or restart your shell to enable"; \
85
+ fi; \
86
+ else \
87
+ echo "Unsupported shell: $$CURRENT_SHELL (only bash and zsh are supported)"; \
88
+ exit 1; \
89
+ fi
90
+
91
+ uninstall-completion: ## Remove shell completion from current shell config
92
+ @CURRENT_SHELL=$$(basename "$$SHELL"); \
93
+ if [ "$$CURRENT_SHELL" = "zsh" ]; then \
94
+ COMP_FILE="$$HOME/.zsh/completions/_git-ai-commit"; \
95
+ RCFILE="$$HOME/.zshrc"; \
96
+ if [ -f "$$COMP_FILE" ]; then \
97
+ rm -f "$$COMP_FILE"; \
98
+ echo "Removed $$COMP_FILE"; \
99
+ fi; \
100
+ if grep -q "git-ai-commit completion" "$$RCFILE" 2>/dev/null; then \
101
+ sed -i.bak '/git-ai-commit completion/d' "$$RCFILE"; \
102
+ rm -f "$$RCFILE.bak"; \
103
+ echo "Removed fpath from $$RCFILE"; \
104
+ fi; \
105
+ elif [ "$$CURRENT_SHELL" = "bash" ]; then \
106
+ if [ -f "$$HOME/.bash_profile" ]; then \
107
+ RCFILE="$$HOME/.bash_profile"; \
108
+ else \
109
+ RCFILE="$$HOME/.bashrc"; \
110
+ fi; \
111
+ if grep -q "git-ai-commit completion" "$$RCFILE" 2>/dev/null; then \
112
+ sed -i.bak '/# git-ai-commit shell completion/d' "$$RCFILE"; \
113
+ sed -i.bak '/git-ai-commit completion/d' "$$RCFILE"; \
114
+ rm -f "$$RCFILE.bak"; \
115
+ echo "Completion removed from $$RCFILE"; \
116
+ else \
117
+ echo "No completion found in $$RCFILE"; \
118
+ fi; \
119
+ else \
120
+ echo "Unsupported shell: $$CURRENT_SHELL"; \
121
+ exit 1; \
122
+ fi
@@ -0,0 +1,10 @@
1
+ import { Command } from 'commander';
2
+ export declare class CompletionCommand {
3
+ private program;
4
+ constructor();
5
+ private handleCompletion;
6
+ private generateBashCompletion;
7
+ private generateZshCompletion;
8
+ getCommand(): Command;
9
+ }
10
+ //# sourceMappingURL=completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/commands/completion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAU;;IASzB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,sBAAsB;IAsG9B,OAAO,CAAC,qBAAqB;IAqH7B,UAAU,IAAI,OAAO;CAGtB"}
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CompletionCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ class CompletionCommand {
6
+ constructor() {
7
+ this.program = new commander_1.Command('completion')
8
+ .description('Generate shell completion scripts')
9
+ .argument('<shell>', 'Shell type (bash or zsh)')
10
+ .action(this.handleCompletion.bind(this));
11
+ }
12
+ handleCompletion(shell) {
13
+ const normalized = shell.toLowerCase().trim();
14
+ if (normalized === 'bash') {
15
+ console.log(this.generateBashCompletion());
16
+ }
17
+ else if (normalized === 'zsh') {
18
+ console.log(this.generateZshCompletion());
19
+ }
20
+ else {
21
+ console.error(`Unsupported shell: ${shell}`);
22
+ console.error('Supported shells: bash, zsh');
23
+ process.exit(1);
24
+ }
25
+ }
26
+ generateBashCompletion() {
27
+ return `# git-ai-commit bash completion
28
+ # Add to ~/.bashrc or ~/.bash_profile:
29
+ # eval "$(git-ai-commit completion bash)"
30
+
31
+ _git_ai_commit() {
32
+ local cur prev words cword
33
+ _init_completion || return
34
+
35
+ local commands="commit config pr tag history completion"
36
+
37
+ # Global options
38
+ local global_opts="-v --version -h --help"
39
+
40
+ # Command-specific options
41
+ local commit_opts="-k --api-key -b --base-url --model -m --message-only -p --push --prompt --no-verify"
42
+ local config_opts="-s --show -l --language --auto-push --no-auto-push -k --api-key -b --base-url -m --model --mode"
43
+ local pr_opts="--base --compare -k --api-key -b --base-url --model"
44
+ local tag_opts="-k --api-key --base-url -m --model --message -t --base-tag --prompt"
45
+ local history_opts="-l --limit --json --clear"
46
+ local completion_opts=""
47
+
48
+ case "\${cword}" in
49
+ 1)
50
+ COMPREPLY=( \$(compgen -W "\${commands} \${global_opts}" -- "\${cur}") )
51
+ return
52
+ ;;
53
+ esac
54
+
55
+ local cmd="\${words[1]}"
56
+
57
+ case "\${cmd}" in
58
+ commit)
59
+ case "\${prev}" in
60
+ -k|--api-key|-b|--base-url|--model|--prompt)
61
+ return
62
+ ;;
63
+ esac
64
+ COMPREPLY=( \$(compgen -W "\${commit_opts}" -- "\${cur}") )
65
+ ;;
66
+ config)
67
+ case "\${prev}" in
68
+ -l|--language)
69
+ COMPREPLY=( \$(compgen -W "ko en" -- "\${cur}") )
70
+ return
71
+ ;;
72
+ --mode)
73
+ COMPREPLY=( \$(compgen -W "custom openai" -- "\${cur}") )
74
+ return
75
+ ;;
76
+ -k|--api-key|-b|--base-url|-m|--model)
77
+ return
78
+ ;;
79
+ esac
80
+ COMPREPLY=( \$(compgen -W "\${config_opts}" -- "\${cur}") )
81
+ ;;
82
+ pr)
83
+ case "\${prev}" in
84
+ --base|--compare)
85
+ # Complete with git branches
86
+ local branches=\$(git branch --format='%(refname:short)' 2>/dev/null)
87
+ COMPREPLY=( \$(compgen -W "\${branches}" -- "\${cur}") )
88
+ return
89
+ ;;
90
+ -k|--api-key|-b|--base-url|--model)
91
+ return
92
+ ;;
93
+ esac
94
+ COMPREPLY=( \$(compgen -W "\${pr_opts}" -- "\${cur}") )
95
+ ;;
96
+ tag)
97
+ case "\${prev}" in
98
+ -t|--base-tag)
99
+ # Complete with git tags
100
+ local tags=\$(git tag 2>/dev/null)
101
+ COMPREPLY=( \$(compgen -W "\${tags}" -- "\${cur}") )
102
+ return
103
+ ;;
104
+ -k|--api-key|--base-url|-m|--model|--message|--prompt)
105
+ return
106
+ ;;
107
+ esac
108
+ COMPREPLY=( \$(compgen -W "\${tag_opts}" -- "\${cur}") )
109
+ ;;
110
+ history)
111
+ case "\${prev}" in
112
+ -l|--limit)
113
+ return
114
+ ;;
115
+ esac
116
+ COMPREPLY=( \$(compgen -W "\${history_opts}" -- "\${cur}") )
117
+ ;;
118
+ completion)
119
+ COMPREPLY=( \$(compgen -W "bash zsh" -- "\${cur}") )
120
+ ;;
121
+ esac
122
+ }
123
+
124
+ complete -F _git_ai_commit git-ai-commit
125
+ `;
126
+ }
127
+ generateZshCompletion() {
128
+ return `#compdef git-ai-commit
129
+ # git-ai-commit zsh completion
130
+ # Installation:
131
+ # mkdir -p ~/.zsh/completions
132
+ # git-ai-commit completion zsh > ~/.zsh/completions/_git-ai-commit
133
+ # # Add to ~/.zshrc (before compinit): fpath=(~/.zsh/completions \$fpath)
134
+ # # Then restart shell or run: autoload -Uz compinit && compinit
135
+
136
+ _git-ai-commit() {
137
+ local curcontext="\$curcontext" state line
138
+ typeset -A opt_args
139
+
140
+ _arguments -C \\
141
+ '-v[output the version number]' \\
142
+ '--version[output the version number]' \\
143
+ '-h[display help]' \\
144
+ '--help[display help]' \\
145
+ '1: :->command' \\
146
+ '*:: :->args' && return
147
+
148
+ case \$state in
149
+ command)
150
+ local -a commands
151
+ commands=(
152
+ 'commit:Generate AI-powered commit message'
153
+ 'config:Manage git-ai-commit configuration'
154
+ 'pr:Generate a pull request title and summary'
155
+ 'tag:Create an annotated git tag with AI-generated notes'
156
+ 'history:Manage git-ai-commit command history'
157
+ 'completion:Generate shell completion scripts'
158
+ )
159
+ _describe -t commands 'git-ai-commit commands' commands
160
+ ;;
161
+ args)
162
+ case \$line[1] in
163
+ commit)
164
+ _arguments \\
165
+ '-k[OpenAI API key]:key:' \\
166
+ '--api-key[OpenAI API key]:key:' \\
167
+ '-b[Custom API base URL]:url:' \\
168
+ '--base-url[Custom API base URL]:url:' \\
169
+ '--model[Model to use]:model:' \\
170
+ '-m[Output only the generated commit message]' \\
171
+ '--message-only[Output only the generated commit message]' \\
172
+ '-p[Push after creating the commit]' \\
173
+ '--push[Push after creating the commit]' \\
174
+ '--prompt[Additional AI prompt instructions]:text:' \\
175
+ '--no-verify[Skip pre-commit hooks]'
176
+ ;;
177
+ config)
178
+ _arguments \\
179
+ '-s[Show current configuration]' \\
180
+ '--show[Show current configuration]' \\
181
+ '-l[Set default language]:language:(ko en)' \\
182
+ '--language[Set default language]:language:(ko en)' \\
183
+ '--auto-push[Enable automatic git push]' \\
184
+ '--no-auto-push[Disable automatic git push]' \\
185
+ '-k[Persist API key]:key:' \\
186
+ '--api-key[Persist API key]:key:' \\
187
+ '-b[Persist API base URL]:url:' \\
188
+ '--base-url[Persist API base URL]:url:' \\
189
+ '-m[Persist default AI model]:model:' \\
190
+ '--model[Persist default AI model]:model:' \\
191
+ '--mode[Persist AI mode]:mode:(custom openai)'
192
+ ;;
193
+ pr)
194
+ _arguments \\
195
+ '--base[Base branch to diff against]:branch:->branches' \\
196
+ '--compare[Compare branch to describe]:branch:->branches' \\
197
+ '-k[Override API key]:key:' \\
198
+ '--api-key[Override API key]:key:' \\
199
+ '-b[Override API base URL]:url:' \\
200
+ '--base-url[Override API base URL]:url:' \\
201
+ '--model[Override AI model]:model:'
202
+ [[ \$state == branches ]] && {
203
+ local -a branches
204
+ branches=(\${(f)"\$(git branch --format='%(refname:short)' 2>/dev/null)"})
205
+ _describe -t branches 'branches' branches
206
+ }
207
+ ;;
208
+ tag)
209
+ _arguments \\
210
+ '1:tag name:' \\
211
+ '-k[OpenAI API key]:key:' \\
212
+ '--api-key[OpenAI API key]:key:' \\
213
+ '--base-url[Custom API base URL]:url:' \\
214
+ '-m[Model to use]:model:' \\
215
+ '--model[Model to use]:model:' \\
216
+ '--message[Tag message to use directly]:message:' \\
217
+ '-t[Existing tag to diff against]:tag:->tags' \\
218
+ '--base-tag[Existing tag to diff against]:tag:->tags' \\
219
+ '--prompt[Additional AI prompt instructions]:text:'
220
+ [[ \$state == tags ]] && {
221
+ local -a tags
222
+ tags=(\${(f)"\$(git tag 2>/dev/null)"})
223
+ _describe -t tags 'tags' tags
224
+ }
225
+ ;;
226
+ history)
227
+ _arguments \\
228
+ '-l[Limit number of entries]:number:' \\
229
+ '--limit[Limit number of entries]:number:' \\
230
+ '--json[Output in JSON format]' \\
231
+ '--clear[Clear all stored history]'
232
+ ;;
233
+ completion)
234
+ _arguments \\
235
+ '1:shell:(bash zsh)'
236
+ ;;
237
+ esac
238
+ ;;
239
+ esac
240
+ }
241
+ `;
242
+ }
243
+ getCommand() {
244
+ return this.program;
245
+ }
246
+ }
247
+ exports.CompletionCommand = CompletionCommand;
248
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../src/commands/completion.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AAEpC,MAAa,iBAAiB;IAG5B;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,mBAAO,CAAC,YAAY,CAAC;aACrC,WAAW,CAAC,mCAAmC,CAAC;aAChD,QAAQ,CAAC,SAAS,EAAE,0BAA0B,CAAC;aAC/C,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IAEO,gBAAgB,CAAC,KAAa;QACpC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QAE9C,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC;QAC7C,CAAC;aAAM,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAEO,sBAAsB;QAC5B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkGV,CAAC;IACA,CAAC;IAEO,qBAAqB;QAC3B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiHV,CAAC;IACA,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AAtPD,8CAsPC"}
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ const configCommand_1 = require("./commands/configCommand");
12
12
  const prCommand_1 = require("./commands/prCommand");
13
13
  const tag_1 = require("./commands/tag");
14
14
  const history_1 = require("./commands/history");
15
+ const completion_1 = require("./commands/completion");
15
16
  function getPackageVersion() {
16
17
  try {
17
18
  // When compiled, __dirname will be dist/; package.json is one level up
@@ -35,10 +36,12 @@ const configCommand = new configCommand_1.ConfigCommand();
35
36
  const pullRequestCommand = new prCommand_1.PullRequestCommand();
36
37
  const tagCommand = new tag_1.TagCommand();
37
38
  const historyCommand = new history_1.HistoryCommand();
39
+ const completionCommand = new completion_1.CompletionCommand();
38
40
  program.addCommand(commitCommand.getCommand());
39
41
  program.addCommand(configCommand.getCommand());
40
42
  program.addCommand(pullRequestCommand.getCommand());
41
43
  program.addCommand(tagCommand.getCommand());
42
44
  program.addCommand(historyCommand.getCommand());
45
+ program.addCommand(completionCommand.getCommand());
43
46
  program.parse();
44
47
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,4CAAoB;AACpB,gDAAwB;AACxB,8CAAkD;AAClD,4DAAyD;AACzD,oDAA0D;AAC1D,wCAA4C;AAC5C,gDAAoD;AAEpD,SAAS,iBAAiB;IACxB,IAAI,CAAC;QACH,uEAAuE;QACvE,MAAM,OAAO,GAAG,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,YAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,eAAe,CAAC;KACrB,WAAW,CAAC,yCAAyC,CAAC;IACvD,6CAA6C;KAC5C,OAAO,CAAC,iBAAiB,EAAE,EAAE,eAAe,EAAE,2BAA2B,CAAC,CAAC;AAE9E,MAAM,aAAa,GAAG,IAAI,sBAAa,EAAE,CAAC;AAC1C,MAAM,aAAa,GAAG,IAAI,6BAAa,EAAE,CAAC;AAC1C,MAAM,kBAAkB,GAAG,IAAI,8BAAkB,EAAE,CAAC;AACpD,MAAM,UAAU,GAAG,IAAI,gBAAU,EAAE,CAAC;AACpC,MAAM,cAAc,GAAG,IAAI,wBAAc,EAAE,CAAC;AAE5C,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC,CAAC;AAC/C,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC,CAAC;AAC/C,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,CAAC;AACpD,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC,CAAC;AAEhD,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,4CAAoB;AACpB,gDAAwB;AACxB,8CAAkD;AAClD,4DAAyD;AACzD,oDAA0D;AAC1D,wCAA4C;AAC5C,gDAAoD;AACpD,sDAA0D;AAE1D,SAAS,iBAAiB;IACxB,IAAI,CAAC;QACH,uEAAuE;QACvE,MAAM,OAAO,GAAG,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,YAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,eAAe,CAAC;KACrB,WAAW,CAAC,yCAAyC,CAAC;IACvD,6CAA6C;KAC5C,OAAO,CAAC,iBAAiB,EAAE,EAAE,eAAe,EAAE,2BAA2B,CAAC,CAAC;AAE9E,MAAM,aAAa,GAAG,IAAI,sBAAa,EAAE,CAAC;AAC1C,MAAM,aAAa,GAAG,IAAI,6BAAa,EAAE,CAAC;AAC1C,MAAM,kBAAkB,GAAG,IAAI,8BAAkB,EAAE,CAAC;AACpD,MAAM,UAAU,GAAG,IAAI,gBAAU,EAAE,CAAC;AACpC,MAAM,cAAc,GAAG,IAAI,wBAAc,EAAE,CAAC;AAC5C,MAAM,iBAAiB,GAAG,IAAI,8BAAiB,EAAE,CAAC;AAElD,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC,CAAC;AAC/C,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC,CAAC;AAC/C,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,CAAC;AACpD,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC,CAAC;AAChD,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,UAAU,EAAE,CAAC,CAAC;AAEnD,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/prompts/tag.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE5C,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,EACf,2BAAuB,EACvB,WAAU,iBAAwB,KACjC,MA2CF,CAAC"}
1
+ {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/prompts/tag.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE5C,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,EACf,2BAAuB,EACvB,WAAU,iBAAwB,KACjC,MAwEF,CAAC"}
@@ -2,42 +2,69 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateTagPrompt = void 0;
4
4
  const generateTagPrompt = (tagName, customInstructions = '', language = 'ko') => {
5
+ const titleInstruction = language === 'ko'
6
+ ? `첫 줄에 버전 "${tagName}"을 제목으로 작성하세요.`
7
+ : `Write the version "${tagName}" as the title on the first line.`;
5
8
  const summaryInstruction = language === 'ko'
6
- ? 'Begin with a short summary sentence (in Korean) that captures the overall impact of the release using plain text only.'
7
- : 'Begin with a short summary sentence (in English) that captures the overall impact of the release using plain text only.';
9
+ ? '제목 다음 줄에 이번 릴리즈의 전체적인 영향을 요약하는 문장을 작성하세요.'
10
+ : 'On the line after the title, write a one-sentence summary capturing the overall impact of this release.';
8
11
  const listInstruction = language === 'ko'
9
- ? 'After the summary, write one line per category 사용자 기능, 버그 수정, 유지 보수 using the format "사용자 기능: 변경1; 변경2" with plain text only (no bullets, numbers, or markdown symbols).'
10
- : 'After the summary, write one line per category User Features, Bug Fixes, Maintenance using the format "User Features: Change 1; Change 2" with plain text only (no bullets, numbers, or markdown symbols).';
12
+ ? '요약 줄을 두고, 카테고리별로 변경사항을 나열하세요: 새로운 기능, 버그 수정, 개선사항. 항목은 "- " 시작합니다.'
13
+ : 'After the summary, leave a blank line, then list changes by category: New Features, Bug Fixes, Improvements. Each item starts with "- ".';
14
+ const categoryFormat = language === 'ko'
15
+ ? `카테고리 형식:
16
+ ### 새로운 기능
17
+ - 변경사항 1
18
+ - 변경사항 2
19
+
20
+ ### 버그 수정
21
+ - 수정사항 1
22
+
23
+ ### 개선사항
24
+ - 개선사항 1`
25
+ : `Category format:
26
+ ### New Features
27
+ - Change 1
28
+ - Change 2
29
+
30
+ ### Bug Fixes
31
+ - Fix 1
32
+
33
+ ### Improvements
34
+ - Improvement 1`;
11
35
  const emptyCategoryInstruction = language === 'ko'
12
- ? 'If a category has no changes, write "사용자 기능: 해당 사항 없음." (or the matching category label) using the same plain text format.'
13
- : 'If a category has no changes, write "User Features: None." (or the matching category label) using the same plain text format.';
36
+ ? '변경사항이 없는 카테고리는 생략하세요.'
37
+ : 'Omit categories with no changes.';
14
38
  const noChangesInstruction = language === 'ko'
15
- ? 'If no changes exist at all, state "변경 사항 없음" plainly.'
16
- : 'If no changes exist at all, state "No changes to report." plainly.';
39
+ ? '변경사항이 전혀 없으면 "변경 사항 없음"이라고 작성하세요.'
40
+ : 'If no changes exist at all, state "No changes to report."';
17
41
  const outputLanguageLine = language === 'ko'
18
- ? 'Write the release notes in Korean using concise plain text without markdown syntax.'
19
- : 'Write the release notes in English using concise plain text without markdown syntax.';
20
- return `You are an experienced release manager. Produce clear, user-facing release notes that describe the differences between the previous tag and ${tagName}.
42
+ ? '릴리즈 노트를 한국어로 작성하세요.'
43
+ : 'Write the release notes in English.';
44
+ return `You are an experienced release manager. Produce clear, user-facing release notes in GitHub Release style.
21
45
 
22
46
  ## Objective
23
- Summarize the meaningful changes that occurred between the prior release tag and ${tagName}. Treat the commit log provided by the user message as the complete history of changes since the previous tag.
47
+ Create release notes for ${tagName} that describe the meaningful changes since the previous release.
24
48
 
25
49
  ## Input Context
26
50
  - Target tag to publish: ${tagName}
27
- - Commit history between the previous tag and ${tagName} will be supplied in the user message (most recent first).
51
+ - Commit history between the previous tag and ${tagName} will be supplied in the user message.
52
+
53
+ ${customInstructions ? `## Additional Instructions\n${customInstructions}\n` : ''}
54
+ ## Output Format (GitHub Release Style)
55
+ ${titleInstruction}
56
+ ${summaryInstruction}
57
+ ${listInstruction}
28
58
 
29
- ${customInstructions}
59
+ ${categoryFormat}
30
60
 
31
- ## Output Requirements
61
+ ## Rules
32
62
  - ${outputLanguageLine}
33
- - ${summaryInstruction}
34
- - ${listInstruction}
35
- - Use short phrases for each change and include scope/component names when helpful, without copying commit messages verbatim.
36
63
  - ${emptyCategoryInstruction}
37
64
  - ${noChangesInstruction}
38
- - Do not invent work beyond what appears in the commit log.
39
- - Do not use markdown syntax such as headings (#), bullets (-), emphasis (**), underscores (_), or backticks (\`).
40
- - Separate lines using newline characters only; do not use numbering, bullet prefixes, tables, or code blocks.
65
+ - Use concise descriptions; do not copy commit messages verbatim.
66
+ - Do not invent changes beyond what appears in the commit log.
67
+ - Use markdown formatting (###, -, etc.) as shown in the category format.
41
68
  - Return only the release notes content with no surrounding commentary.`;
42
69
  };
43
70
  exports.generateTagPrompt = generateTagPrompt;
@@ -1 +1 @@
1
- {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/prompts/tag.ts"],"names":[],"mappings":";;;AAEO,MAAM,iBAAiB,GAAG,CAC/B,OAAe,EACf,kBAAkB,GAAG,EAAE,EACvB,WAA8B,IAAI,EAC1B,EAAE;IACV,MAAM,kBAAkB,GAAG,QAAQ,KAAK,IAAI;QAC1C,CAAC,CAAC,wHAAwH;QAC1H,CAAC,CAAC,yHAAyH,CAAC;IAE9H,MAAM,eAAe,GAAG,QAAQ,KAAK,IAAI;QACvC,CAAC,CAAC,8KAA8K;QAChL,CAAC,CAAC,gNAAgN,CAAC;IAErN,MAAM,wBAAwB,GAAG,QAAQ,KAAK,IAAI;QAChD,CAAC,CAAC,4HAA4H;QAC9H,CAAC,CAAC,+HAA+H,CAAC;IAEpI,MAAM,oBAAoB,GAAG,QAAQ,KAAK,IAAI;QAC5C,CAAC,CAAC,uDAAuD;QACzD,CAAC,CAAC,oEAAoE,CAAC;IAEzE,MAAM,kBAAkB,GAAG,QAAQ,KAAK,IAAI;QAC1C,CAAC,CAAC,qFAAqF;QACvF,CAAC,CAAC,sFAAsF,CAAC;IAE3F,OAAO,+IAA+I,OAAO;;;mFAG5E,OAAO;;;2BAG/D,OAAO;gDACc,OAAO;;EAErD,kBAAkB;;;IAGhB,kBAAkB;IAClB,kBAAkB;IAClB,eAAe;;IAEf,wBAAwB;IACxB,oBAAoB;;;;wEAIgD,CAAC;AACzE,CAAC,CAAC;AA/CW,QAAA,iBAAiB,qBA+C5B"}
1
+ {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/prompts/tag.ts"],"names":[],"mappings":";;;AAEO,MAAM,iBAAiB,GAAG,CAC/B,OAAe,EACf,kBAAkB,GAAG,EAAE,EACvB,WAA8B,IAAI,EAC1B,EAAE;IACV,MAAM,gBAAgB,GAAG,QAAQ,KAAK,IAAI;QACxC,CAAC,CAAC,YAAY,OAAO,gBAAgB;QACrC,CAAC,CAAC,sBAAsB,OAAO,mCAAmC,CAAC;IAErE,MAAM,kBAAkB,GAAG,QAAQ,KAAK,IAAI;QAC1C,CAAC,CAAC,6CAA6C;QAC/C,CAAC,CAAC,yGAAyG,CAAC;IAE9G,MAAM,eAAe,GAAG,QAAQ,KAAK,IAAI;QACvC,CAAC,CAAC,8EAA8E;QAChF,CAAC,CAAC,0IAA0I,CAAC;IAE/I,MAAM,cAAc,GAAG,QAAQ,KAAK,IAAI;QACtC,CAAC,CAAC;;;;;;;;;SASG;QACL,CAAC,CAAC;;;;;;;;;gBASU,CAAC;IAEf,MAAM,wBAAwB,GAAG,QAAQ,KAAK,IAAI;QAChD,CAAC,CAAC,uBAAuB;QACzB,CAAC,CAAC,kCAAkC,CAAC;IAEvC,MAAM,oBAAoB,GAAG,QAAQ,KAAK,IAAI;QAC5C,CAAC,CAAC,mCAAmC;QACrC,CAAC,CAAC,2DAA2D,CAAC;IAEhE,MAAM,kBAAkB,GAAG,QAAQ,KAAK,IAAI;QAC1C,CAAC,CAAC,qBAAqB;QACvB,CAAC,CAAC,qCAAqC,CAAC;IAE1C,OAAO;;;2BAGkB,OAAO;;;2BAGP,OAAO;gDACc,OAAO;;EAErD,kBAAkB,CAAC,CAAC,CAAC,+BAA+B,kBAAkB,IAAI,CAAC,CAAC,CAAC,EAAE;;EAE/E,gBAAgB;EAChB,kBAAkB;EAClB,eAAe;;EAEf,cAAc;;;IAGZ,kBAAkB;IAClB,wBAAwB;IACxB,oBAAoB;;;;wEAIgD,CAAC;AACzE,CAAC,CAAC;AA5EW,QAAA,iBAAiB,qBA4E5B"}
package/package.json CHANGED
@@ -1,21 +1,11 @@
1
1
  {
2
2
  "name": "@ksw8954/git-ai-commit",
3
- "version": "1.0.12",
3
+ "version": "1.1.1",
4
4
  "description": "AI-powered git commit message generator",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "git-ai-commit": "./dist/index.js"
8
8
  },
9
- "scripts": {
10
- "build": "tsc",
11
- "dev": "ts-node src/index.ts",
12
- "test": "jest",
13
- "test:file": "jest",
14
- "test:watch": "jest --watch",
15
- "test:coverage": "jest --coverage",
16
- "lint": "eslint src/**/*.ts",
17
- "typecheck": "tsc --noEmit"
18
- },
19
9
  "repository": {
20
10
  "type": "git",
21
11
  "url": "git+https://github.com/onaries/git-ai-commit.git"
@@ -47,5 +37,15 @@
47
37
  "dependencies": {
48
38
  "commander": "^14.0.1",
49
39
  "openai": "^5.20.2"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "dev": "ts-node src/index.ts",
44
+ "test": "jest",
45
+ "test:file": "jest",
46
+ "test:watch": "jest --watch",
47
+ "test:coverage": "jest --coverage",
48
+ "lint": "eslint src/**/*.ts",
49
+ "typecheck": "tsc --noEmit"
50
50
  }
51
- }
51
+ }
@@ -0,0 +1,249 @@
1
+ import { Command } from 'commander';
2
+
3
+ export class CompletionCommand {
4
+ private program: Command;
5
+
6
+ constructor() {
7
+ this.program = new Command('completion')
8
+ .description('Generate shell completion scripts')
9
+ .argument('<shell>', 'Shell type (bash or zsh)')
10
+ .action(this.handleCompletion.bind(this));
11
+ }
12
+
13
+ private handleCompletion(shell: string): void {
14
+ const normalized = shell.toLowerCase().trim();
15
+
16
+ if (normalized === 'bash') {
17
+ console.log(this.generateBashCompletion());
18
+ } else if (normalized === 'zsh') {
19
+ console.log(this.generateZshCompletion());
20
+ } else {
21
+ console.error(`Unsupported shell: ${shell}`);
22
+ console.error('Supported shells: bash, zsh');
23
+ process.exit(1);
24
+ }
25
+ }
26
+
27
+ private generateBashCompletion(): string {
28
+ return `# git-ai-commit bash completion
29
+ # Add to ~/.bashrc or ~/.bash_profile:
30
+ # eval "$(git-ai-commit completion bash)"
31
+
32
+ _git_ai_commit() {
33
+ local cur prev words cword
34
+ _init_completion || return
35
+
36
+ local commands="commit config pr tag history completion"
37
+
38
+ # Global options
39
+ local global_opts="-v --version -h --help"
40
+
41
+ # Command-specific options
42
+ local commit_opts="-k --api-key -b --base-url --model -m --message-only -p --push --prompt --no-verify"
43
+ local config_opts="-s --show -l --language --auto-push --no-auto-push -k --api-key -b --base-url -m --model --mode"
44
+ local pr_opts="--base --compare -k --api-key -b --base-url --model"
45
+ local tag_opts="-k --api-key --base-url -m --model --message -t --base-tag --prompt"
46
+ local history_opts="-l --limit --json --clear"
47
+ local completion_opts=""
48
+
49
+ case "\${cword}" in
50
+ 1)
51
+ COMPREPLY=( \$(compgen -W "\${commands} \${global_opts}" -- "\${cur}") )
52
+ return
53
+ ;;
54
+ esac
55
+
56
+ local cmd="\${words[1]}"
57
+
58
+ case "\${cmd}" in
59
+ commit)
60
+ case "\${prev}" in
61
+ -k|--api-key|-b|--base-url|--model|--prompt)
62
+ return
63
+ ;;
64
+ esac
65
+ COMPREPLY=( \$(compgen -W "\${commit_opts}" -- "\${cur}") )
66
+ ;;
67
+ config)
68
+ case "\${prev}" in
69
+ -l|--language)
70
+ COMPREPLY=( \$(compgen -W "ko en" -- "\${cur}") )
71
+ return
72
+ ;;
73
+ --mode)
74
+ COMPREPLY=( \$(compgen -W "custom openai" -- "\${cur}") )
75
+ return
76
+ ;;
77
+ -k|--api-key|-b|--base-url|-m|--model)
78
+ return
79
+ ;;
80
+ esac
81
+ COMPREPLY=( \$(compgen -W "\${config_opts}" -- "\${cur}") )
82
+ ;;
83
+ pr)
84
+ case "\${prev}" in
85
+ --base|--compare)
86
+ # Complete with git branches
87
+ local branches=\$(git branch --format='%(refname:short)' 2>/dev/null)
88
+ COMPREPLY=( \$(compgen -W "\${branches}" -- "\${cur}") )
89
+ return
90
+ ;;
91
+ -k|--api-key|-b|--base-url|--model)
92
+ return
93
+ ;;
94
+ esac
95
+ COMPREPLY=( \$(compgen -W "\${pr_opts}" -- "\${cur}") )
96
+ ;;
97
+ tag)
98
+ case "\${prev}" in
99
+ -t|--base-tag)
100
+ # Complete with git tags
101
+ local tags=\$(git tag 2>/dev/null)
102
+ COMPREPLY=( \$(compgen -W "\${tags}" -- "\${cur}") )
103
+ return
104
+ ;;
105
+ -k|--api-key|--base-url|-m|--model|--message|--prompt)
106
+ return
107
+ ;;
108
+ esac
109
+ COMPREPLY=( \$(compgen -W "\${tag_opts}" -- "\${cur}") )
110
+ ;;
111
+ history)
112
+ case "\${prev}" in
113
+ -l|--limit)
114
+ return
115
+ ;;
116
+ esac
117
+ COMPREPLY=( \$(compgen -W "\${history_opts}" -- "\${cur}") )
118
+ ;;
119
+ completion)
120
+ COMPREPLY=( \$(compgen -W "bash zsh" -- "\${cur}") )
121
+ ;;
122
+ esac
123
+ }
124
+
125
+ complete -F _git_ai_commit git-ai-commit
126
+ `;
127
+ }
128
+
129
+ private generateZshCompletion(): string {
130
+ return `#compdef git-ai-commit
131
+ # git-ai-commit zsh completion
132
+ # Installation:
133
+ # mkdir -p ~/.zsh/completions
134
+ # git-ai-commit completion zsh > ~/.zsh/completions/_git-ai-commit
135
+ # # Add to ~/.zshrc (before compinit): fpath=(~/.zsh/completions \$fpath)
136
+ # # Then restart shell or run: autoload -Uz compinit && compinit
137
+
138
+ _git-ai-commit() {
139
+ local curcontext="\$curcontext" state line
140
+ typeset -A opt_args
141
+
142
+ _arguments -C \\
143
+ '-v[output the version number]' \\
144
+ '--version[output the version number]' \\
145
+ '-h[display help]' \\
146
+ '--help[display help]' \\
147
+ '1: :->command' \\
148
+ '*:: :->args' && return
149
+
150
+ case \$state in
151
+ command)
152
+ local -a commands
153
+ commands=(
154
+ 'commit:Generate AI-powered commit message'
155
+ 'config:Manage git-ai-commit configuration'
156
+ 'pr:Generate a pull request title and summary'
157
+ 'tag:Create an annotated git tag with AI-generated notes'
158
+ 'history:Manage git-ai-commit command history'
159
+ 'completion:Generate shell completion scripts'
160
+ )
161
+ _describe -t commands 'git-ai-commit commands' commands
162
+ ;;
163
+ args)
164
+ case \$line[1] in
165
+ commit)
166
+ _arguments \\
167
+ '-k[OpenAI API key]:key:' \\
168
+ '--api-key[OpenAI API key]:key:' \\
169
+ '-b[Custom API base URL]:url:' \\
170
+ '--base-url[Custom API base URL]:url:' \\
171
+ '--model[Model to use]:model:' \\
172
+ '-m[Output only the generated commit message]' \\
173
+ '--message-only[Output only the generated commit message]' \\
174
+ '-p[Push after creating the commit]' \\
175
+ '--push[Push after creating the commit]' \\
176
+ '--prompt[Additional AI prompt instructions]:text:' \\
177
+ '--no-verify[Skip pre-commit hooks]'
178
+ ;;
179
+ config)
180
+ _arguments \\
181
+ '-s[Show current configuration]' \\
182
+ '--show[Show current configuration]' \\
183
+ '-l[Set default language]:language:(ko en)' \\
184
+ '--language[Set default language]:language:(ko en)' \\
185
+ '--auto-push[Enable automatic git push]' \\
186
+ '--no-auto-push[Disable automatic git push]' \\
187
+ '-k[Persist API key]:key:' \\
188
+ '--api-key[Persist API key]:key:' \\
189
+ '-b[Persist API base URL]:url:' \\
190
+ '--base-url[Persist API base URL]:url:' \\
191
+ '-m[Persist default AI model]:model:' \\
192
+ '--model[Persist default AI model]:model:' \\
193
+ '--mode[Persist AI mode]:mode:(custom openai)'
194
+ ;;
195
+ pr)
196
+ _arguments \\
197
+ '--base[Base branch to diff against]:branch:->branches' \\
198
+ '--compare[Compare branch to describe]:branch:->branches' \\
199
+ '-k[Override API key]:key:' \\
200
+ '--api-key[Override API key]:key:' \\
201
+ '-b[Override API base URL]:url:' \\
202
+ '--base-url[Override API base URL]:url:' \\
203
+ '--model[Override AI model]:model:'
204
+ [[ \$state == branches ]] && {
205
+ local -a branches
206
+ branches=(\${(f)"\$(git branch --format='%(refname:short)' 2>/dev/null)"})
207
+ _describe -t branches 'branches' branches
208
+ }
209
+ ;;
210
+ tag)
211
+ _arguments \\
212
+ '1:tag name:' \\
213
+ '-k[OpenAI API key]:key:' \\
214
+ '--api-key[OpenAI API key]:key:' \\
215
+ '--base-url[Custom API base URL]:url:' \\
216
+ '-m[Model to use]:model:' \\
217
+ '--model[Model to use]:model:' \\
218
+ '--message[Tag message to use directly]:message:' \\
219
+ '-t[Existing tag to diff against]:tag:->tags' \\
220
+ '--base-tag[Existing tag to diff against]:tag:->tags' \\
221
+ '--prompt[Additional AI prompt instructions]:text:'
222
+ [[ \$state == tags ]] && {
223
+ local -a tags
224
+ tags=(\${(f)"\$(git tag 2>/dev/null)"})
225
+ _describe -t tags 'tags' tags
226
+ }
227
+ ;;
228
+ history)
229
+ _arguments \\
230
+ '-l[Limit number of entries]:number:' \\
231
+ '--limit[Limit number of entries]:number:' \\
232
+ '--json[Output in JSON format]' \\
233
+ '--clear[Clear all stored history]'
234
+ ;;
235
+ completion)
236
+ _arguments \\
237
+ '1:shell:(bash zsh)'
238
+ ;;
239
+ esac
240
+ ;;
241
+ esac
242
+ }
243
+ `;
244
+ }
245
+
246
+ getCommand(): Command {
247
+ return this.program;
248
+ }
249
+ }
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ import { ConfigCommand } from './commands/configCommand';
8
8
  import { PullRequestCommand } from './commands/prCommand';
9
9
  import { TagCommand } from './commands/tag';
10
10
  import { HistoryCommand } from './commands/history';
11
+ import { CompletionCommand } from './commands/completion';
11
12
 
12
13
  function getPackageVersion(): string {
13
14
  try {
@@ -34,11 +35,13 @@ const configCommand = new ConfigCommand();
34
35
  const pullRequestCommand = new PullRequestCommand();
35
36
  const tagCommand = new TagCommand();
36
37
  const historyCommand = new HistoryCommand();
38
+ const completionCommand = new CompletionCommand();
37
39
 
38
40
  program.addCommand(commitCommand.getCommand());
39
41
  program.addCommand(configCommand.getCommand());
40
42
  program.addCommand(pullRequestCommand.getCommand());
41
43
  program.addCommand(tagCommand.getCommand());
42
44
  program.addCommand(historyCommand.getCommand());
45
+ program.addCommand(completionCommand.getCommand());
43
46
 
44
47
  program.parse();
@@ -5,46 +5,75 @@ export const generateTagPrompt = (
5
5
  customInstructions = '',
6
6
  language: TagPromptLanguage = 'ko'
7
7
  ): string => {
8
+ const titleInstruction = language === 'ko'
9
+ ? `첫 줄에 버전 "${tagName}"을 제목으로 작성하세요.`
10
+ : `Write the version "${tagName}" as the title on the first line.`;
11
+
8
12
  const summaryInstruction = language === 'ko'
9
- ? 'Begin with a short summary sentence (in Korean) that captures the overall impact of the release using plain text only.'
10
- : 'Begin with a short summary sentence (in English) that captures the overall impact of the release using plain text only.';
13
+ ? '제목 다음 줄에 이번 릴리즈의 전체적인 영향을 요약하는 문장을 작성하세요.'
14
+ : 'On the line after the title, write a one-sentence summary capturing the overall impact of this release.';
11
15
 
12
16
  const listInstruction = language === 'ko'
13
- ? 'After the summary, write one line per category 사용자 기능, 버그 수정, 유지 보수 using the format "사용자 기능: 변경1; 변경2" with plain text only (no bullets, numbers, or markdown symbols).'
14
- : 'After the summary, write one line per category User Features, Bug Fixes, Maintenance using the format "User Features: Change 1; Change 2" with plain text only (no bullets, numbers, or markdown symbols).';
17
+ ? '요약 줄을 두고, 카테고리별로 변경사항을 나열하세요: 새로운 기능, 버그 수정, 개선사항. 항목은 "- " 시작합니다.'
18
+ : 'After the summary, leave a blank line, then list changes by category: New Features, Bug Fixes, Improvements. Each item starts with "- ".';
19
+
20
+ const categoryFormat = language === 'ko'
21
+ ? `카테고리 형식:
22
+ ### 새로운 기능
23
+ - 변경사항 1
24
+ - 변경사항 2
25
+
26
+ ### 버그 수정
27
+ - 수정사항 1
28
+
29
+ ### 개선사항
30
+ - 개선사항 1`
31
+ : `Category format:
32
+ ### New Features
33
+ - Change 1
34
+ - Change 2
35
+
36
+ ### Bug Fixes
37
+ - Fix 1
38
+
39
+ ### Improvements
40
+ - Improvement 1`;
15
41
 
16
42
  const emptyCategoryInstruction = language === 'ko'
17
- ? 'If a category has no changes, write "사용자 기능: 해당 사항 없음." (or the matching category label) using the same plain text format.'
18
- : 'If a category has no changes, write "User Features: None." (or the matching category label) using the same plain text format.';
43
+ ? '변경사항이 없는 카테고리는 생략하세요.'
44
+ : 'Omit categories with no changes.';
19
45
 
20
46
  const noChangesInstruction = language === 'ko'
21
- ? 'If no changes exist at all, state "변경 사항 없음" plainly.'
22
- : 'If no changes exist at all, state "No changes to report." plainly.';
47
+ ? '변경사항이 전혀 없으면 "변경 사항 없음"이라고 작성하세요.'
48
+ : 'If no changes exist at all, state "No changes to report."';
23
49
 
24
50
  const outputLanguageLine = language === 'ko'
25
- ? 'Write the release notes in Korean using concise plain text without markdown syntax.'
26
- : 'Write the release notes in English using concise plain text without markdown syntax.';
51
+ ? '릴리즈 노트를 한국어로 작성하세요.'
52
+ : 'Write the release notes in English.';
27
53
 
28
- return `You are an experienced release manager. Produce clear, user-facing release notes that describe the differences between the previous tag and ${tagName}.
54
+ return `You are an experienced release manager. Produce clear, user-facing release notes in GitHub Release style.
29
55
 
30
56
  ## Objective
31
- Summarize the meaningful changes that occurred between the prior release tag and ${tagName}. Treat the commit log provided by the user message as the complete history of changes since the previous tag.
57
+ Create release notes for ${tagName} that describe the meaningful changes since the previous release.
32
58
 
33
59
  ## Input Context
34
60
  - Target tag to publish: ${tagName}
35
- - Commit history between the previous tag and ${tagName} will be supplied in the user message (most recent first).
61
+ - Commit history between the previous tag and ${tagName} will be supplied in the user message.
62
+
63
+ ${customInstructions ? `## Additional Instructions\n${customInstructions}\n` : ''}
64
+ ## Output Format (GitHub Release Style)
65
+ ${titleInstruction}
66
+ ${summaryInstruction}
67
+ ${listInstruction}
36
68
 
37
- ${customInstructions}
69
+ ${categoryFormat}
38
70
 
39
- ## Output Requirements
71
+ ## Rules
40
72
  - ${outputLanguageLine}
41
- - ${summaryInstruction}
42
- - ${listInstruction}
43
- - Use short phrases for each change and include scope/component names when helpful, without copying commit messages verbatim.
44
73
  - ${emptyCategoryInstruction}
45
74
  - ${noChangesInstruction}
46
- - Do not invent work beyond what appears in the commit log.
47
- - Do not use markdown syntax such as headings (#), bullets (-), emphasis (**), underscores (_), or backticks (\`).
48
- - Separate lines using newline characters only; do not use numbering, bullet prefixes, tables, or code blocks.
75
+ - Use concise descriptions; do not copy commit messages verbatim.
76
+ - Do not invent changes beyond what appears in the commit log.
77
+ - Use markdown formatting (###, -, etc.) as shown in the category format.
49
78
  - Return only the release notes content with no surrounding commentary.`;
50
79
  };