@mihairo/cmt 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mihai Ro
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
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,262 @@
1
+ # cmt
2
+
3
+ > Conventional Commits CLI โ€” zero dependencies, one bash script.
4
+
5
+ [![npm](https://img.shields.io/npm/v/cmt-cli?label=npm)](https://npmjs.com/package/cmt-cli)
6
+ [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-fe5196?logo=conventionalcommits)](https://conventionalcommits.org)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
+
9
+ ---
10
+
11
+ ## Install
12
+
13
+ **npm (any project โ€” no Node required at runtime)**
14
+
15
+ ```bash
16
+ npm install -g cmt-cli
17
+ ```
18
+
19
+ **Homebrew**
20
+
21
+ ```bash
22
+ brew tap mihairo/tap
23
+ brew install cmt
24
+ ```
25
+
26
+ **curl (no package manager)**
27
+
28
+ ```bash
29
+ curl -fsSL https://raw.githubusercontent.com/mihai-ro/cmt/main/cmt \
30
+ -o ~/.local/bin/cmt && chmod +x ~/.local/bin/cmt
31
+ ```
32
+
33
+ ---
34
+
35
+ ## Usage
36
+
37
+ ```
38
+ cmt <command> [flags]
39
+
40
+ init [--husky] [--lint] create .cmt.json + install git hook(s)
41
+ commit interactive commit builder
42
+ lint [file] lint a message file or stdin โ†’ exit 1 on error
43
+ log [n] pretty log of last n commits (default: 20)
44
+ types list available commit types
45
+ uninstall remove cmt-managed hooks and .cmt.json
46
+ version
47
+ ```
48
+
49
+ **Set up a repo:**
50
+
51
+ ```bash
52
+ cd my-project
53
+ cmt init # picker hook only
54
+ cmt init --lint # picker + lint git commit -m "..." commits
55
+ cmt init --husky # husky v9 format (.husky/prepare-commit-msg)
56
+ cmt init --husky --lint # both hooks, husky format
57
+ ```
58
+
59
+ **Guided interactive commit:**
60
+
61
+ ```bash
62
+ git add .
63
+ git commit # triggers the interactive picker automatically
64
+ # or:
65
+ cmt commit # run directly
66
+ ```
67
+
68
+ **Lint from anywhere:**
69
+
70
+ ```bash
71
+ echo "feat(api): add login" | cmt lint # exit 0
72
+ echo "bad message" | cmt lint # exit 1
73
+
74
+ # lint every commit on a branch (CI)
75
+ git log --format="%s" origin/main..HEAD | while IFS= read -r msg; do
76
+ echo "$msg" | cmt lint || exit 1
77
+ done
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Commit format
83
+
84
+ ```
85
+ <type>[optional scope]: <description>
86
+
87
+ [optional body]
88
+
89
+ [optional footer(s)]
90
+ ```
91
+
92
+ **Breaking change:**
93
+
94
+ ```
95
+ feat!: drop support for Node 14
96
+ feat(api)!: redesign endpoints
97
+ BREAKING CHANGE: /auth now returns JWT
98
+ ```
99
+
100
+ **Built-in types**
101
+
102
+ | Type | Emoji | SemVer impact |
103
+ | ---------- | ----- | ------------- |
104
+ | `feat` | โœจ | minor |
105
+ | `fix` | ๐Ÿ› | patch |
106
+ | `docs` | ๐Ÿ“š | โ€” |
107
+ | `style` | ๐Ÿ’… | โ€” |
108
+ | `refactor` | โ™ป๏ธ | โ€” |
109
+ | `perf` | โšก | patch |
110
+ | `test` | ๐Ÿงช | โ€” |
111
+ | `build` | ๐Ÿ—๏ธ | โ€” |
112
+ | `ci` | ๐Ÿ”ง | โ€” |
113
+ | `chore` | ๐Ÿ”ฉ | โ€” |
114
+ | `revert` | โช | patch |
115
+
116
+ ---
117
+
118
+ ## Configuration โ€” `.cmt.json`
119
+
120
+ `cmt init` creates `.cmt.json` at your repo root with a `$schema` pointer.
121
+ VS Code, JetBrains, and any JSON Language Server will autocomplete and
122
+ validate it automatically โ€” no extension needed.
123
+
124
+ ```json
125
+ {
126
+ "$schema": "https://raw.githubusercontent.com/mihai-ro/cmt/main/schema/cmt.schema.json",
127
+ "version": "1.0.0",
128
+ "customTypes": [
129
+ {
130
+ "type": "wip",
131
+ "emoji": "๐Ÿšง",
132
+ "semver": "none",
133
+ "description": "Work in progress"
134
+ },
135
+ {
136
+ "type": "security",
137
+ "emoji": "๐Ÿ”’",
138
+ "semver": "patch",
139
+ "description": "Security fix"
140
+ }
141
+ ],
142
+ "scopes": ["auth", "api", "ui", "db"],
143
+ "rules": {
144
+ "maxHeaderLength": 72,
145
+ "requireScope": false,
146
+ "allowBreakingChanges": ["feat", "fix"],
147
+ "disallowUpperCaseDescription": false,
148
+ "disallowTrailingPeriod": false
149
+ }
150
+ }
151
+ ```
152
+
153
+ **Scopes** โ€” when the `scopes` array is non-empty, `cmt commit` shows an
154
+ arrow-key picker with your configured scopes, a "custom" option for free-text
155
+ entry, and a "skip" option. Leave `scopes` empty to always use free-text input.
156
+
157
+ Commit `.cmt.json` โ€” your whole team shares the same types, scopes, and rules.
158
+
159
+ ---
160
+
161
+ ## Hooks
162
+
163
+ ### `prepare-commit-msg` (always installed)
164
+
165
+ Intercepts plain `git commit`, runs the interactive picker, and writes the
166
+ message โ€” so git never opens its editor. Skips amends, merges, squashes, and
167
+ any commit that already has a source message.
168
+
169
+ ### `commit-msg` (opt-in via `--lint`)
170
+
171
+ Lints the final commit message. Catches `git commit -m "..."`, `--amend`,
172
+ and commits from GUI tools:
173
+
174
+ ```bash
175
+ cmt init --lint
176
+ ```
177
+
178
+ Both hooks follow the same append/create pattern โ€” if a hook file already
179
+ exists they append a clearly-marked block rather than overwriting it.
180
+ `cmt uninstall` removes only the cmt blocks, leaving any other content intact.
181
+
182
+ ---
183
+
184
+ ## Integrations
185
+
186
+ ### Husky v9
187
+
188
+ ```bash
189
+ cmt init --husky --lint # writes .husky/prepare-commit-msg + .husky/commit-msg
190
+ git add .husky/ # commit them โ€” every teammate gets them on clone
191
+ ```
192
+
193
+ ### lint-staged
194
+
195
+ Add to `.husky/pre-commit`:
196
+
197
+ ```sh
198
+ npx lint-staged
199
+ ```
200
+
201
+ `cmt` handles commit message linting separately โ€” the two hooks are completely independent.
202
+
203
+ ### GitHub Actions
204
+
205
+ ```yaml
206
+ - name: Lint commit messages
207
+ run: |
208
+ git log --format="%s" origin/main..HEAD | while IFS= read -r msg; do
209
+ echo "$msg" | cmt lint || exit 1
210
+ done
211
+ ```
212
+
213
+ ### Git operations and hook behaviour
214
+
215
+ | Operation | Hook fires? | Result |
216
+ | --------------------- | ---------------- | ------------------------------------ |
217
+ | `git commit` | โœ… | picker runs |
218
+ | `git commit -m "..."` | โœ… with `--lint` | linted |
219
+ | `git commit --amend` | โœ… with `--lint` | linted |
220
+ | `git merge --no-ff` | โœ… | โญ skipped (auto-generated message) |
221
+ | `git revert` | โœ… | โญ skipped (auto-generated message) |
222
+ | `fixup!` / `squash!` | โœ… | โญ skipped |
223
+ | `git pull --rebase` | โœ… | โœ… passes (replays existing commits) |
224
+ | Empty/aborted commit | โœ… | โญ skipped |
225
+
226
+ ---
227
+
228
+ ## Lint rules
229
+
230
+ | Rule | Config key | Default | On fail |
231
+ | ----------------------------------------- | ------------------------------ | -------- | ---------- |
232
+ | Header format `type(scope)?: description` | โ€” | required | โŒ error |
233
+ | Valid type | โ€” | required | โŒ error |
234
+ | Non-empty description | โ€” | required | โŒ error |
235
+ | Blank line before body | โ€” | required | โŒ error |
236
+ | Scope required | `requireScope` | `false` | โŒ error |
237
+ | Uppercase description | `disallowUpperCaseDescription` | `false` | โš ๏ธ / โŒ |
238
+ | Trailing period | `disallowTrailingPeriod` | `false` | โš ๏ธ / โŒ |
239
+ | Header length | `maxHeaderLength` | `72` | โš ๏ธ warning |
240
+
241
+ Warnings exit `0`. Errors exit `1`.
242
+
243
+ ---
244
+
245
+ ## Why not commitlint + husky + commitizen?
246
+
247
+ | | **cmt** | commitlint + husky | commitizen |
248
+ | -------------------------- | ------------------ | ------------------ | --------------- |
249
+ | Runtime dependencies | **0** | ~15 npm packages | Python + pip |
250
+ | Works in any language repo | โœ… | โŒ needs Node | โŒ needs Python |
251
+ | Install | copy one file | `npm install` | `pip install` |
252
+ | Interactive commit prompt | โœ… | via cz-commitlint | โœ… |
253
+ | Commit-msg linting | โœ… opt-in `--lint` | โœ… | โœ… |
254
+ | Husky v9 support | โœ… | native | via config |
255
+ | JSON Schema / intellisense | โœ… | partial | โŒ |
256
+ | Custom types + scopes | โœ… `.cmt.json` | โœ… | โœ… |
257
+
258
+ ---
259
+
260
+ ## License
261
+
262
+ MIT