@synmux/claude-commit 1.0.3 → 1.1.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/CHANGELOG.md +238 -0
- package/README.md +92 -38
- package/bin/cco.js +16 -0
- package/bin/cco.ts +3 -6
- package/dist/bin/cco.js +2347 -0
- package/dist/index.js +1642 -0
- package/dist/types/index.d.ts +22 -0
- package/dist/types/src/agent.d.ts +93 -0
- package/dist/types/src/config.d.ts +36 -0
- package/dist/types/src/diff.d.ts +115 -0
- package/{src/errors.ts → dist/types/src/errors.d.ts} +3 -6
- package/dist/types/src/generate.d.ts +113 -0
- package/dist/types/src/git.d.ts +31 -0
- package/dist/types/src/models.d.ts +42 -0
- package/dist/types/src/ollama.d.ts +89 -0
- package/dist/types/src/paths.d.ts +9 -0
- package/dist/types/src/prompts.d.ts +59 -0
- package/dist/types/src/tokens.d.ts +58 -0
- package/dist/types/src/types.d.ts +234 -0
- package/{src/ui/colors.ts → dist/types/src/ui/colors.d.ts} +2 -5
- package/dist/types/src/ui/spinner.d.ts +23 -0
- package/package.json +45 -32
- package/index.ts +0 -69
- package/src/agent.ts +0 -280
- package/src/cli.ts +0 -442
- package/src/config.ts +0 -337
- package/src/diff.ts +0 -571
- package/src/generate.ts +0 -478
- package/src/git.ts +0 -145
- package/src/models.ts +0 -95
- package/src/ollama.ts +0 -502
- package/src/paths.ts +0 -139
- package/src/prompts.ts +0 -364
- package/src/tokens.ts +0 -147
- package/src/types.ts +0 -238
- package/src/ui/editor.ts +0 -89
- package/src/ui/interactive.ts +0 -313
- package/src/ui/spinner.ts +0 -79
- package/src/utils.ts +0 -5
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `claude-commit` are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project
|
|
5
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
Each version also has a [GitHub release](https://github.com/synmux/claude-commit/releases)
|
|
8
|
+
carrying the same notes at greater length.
|
|
9
|
+
|
|
10
|
+
## [1.1.0] - 2026-09-13
|
|
11
|
+
|
|
12
|
+
### [1.1.0] - Changed
|
|
13
|
+
|
|
14
|
+
- **Runs on Node, not Bun.** `cco` now requires Node.js 22.18 or later
|
|
15
|
+
(24 LTS recommended) and no longer needs Bun at all. The package ships a
|
|
16
|
+
bundled `dist/` built with esbuild plus type declarations for the library
|
|
17
|
+
entry; the executable is `bin/cco.js`, which runs the TypeScript sources
|
|
18
|
+
directly from a checkout via Node's native type stripping.
|
|
19
|
+
- **The interactive picker is built on Clack** (`@clack/core` +
|
|
20
|
+
`@clack/prompts`) instead of OpenTUI. It looks a little different - a
|
|
21
|
+
title, a hint line, and every candidate shown as its subject plus a
|
|
22
|
+
one-line body preview - and gains `j`/`k` navigation with wrapping and
|
|
23
|
+
`Ctrl-C` to cancel alongside the existing arrow keys, `Enter`, `e` and
|
|
24
|
+
`q`/`Esc`. The list windows itself to the terminal height. It still draws
|
|
25
|
+
on stderr only.
|
|
26
|
+
- Path patterns (`lowPriorityPaths`, `ignore`) are matched by `picomatch`
|
|
27
|
+
instead of `Bun.Glob`. Every well-formed pattern behaves exactly as
|
|
28
|
+
before. Two ill-formed cases differ: an unbalanced `{` now matches
|
|
29
|
+
nothing (it used to match its first alternative), and an unterminated `[`
|
|
30
|
+
now matches its literal text (it used to match nothing).
|
|
31
|
+
- Development moved to pnpm (`pnpm-lock.yaml`, `pnpm-workspace.yaml`),
|
|
32
|
+
vitest (`pnpm test`) and esbuild (`pnpm run build`). The repository's own
|
|
33
|
+
`lowPriorityPaths` deprioritise `pnpm-lock.yaml` instead of `bun.lock`.
|
|
34
|
+
- The npm publish workflow now runs `ci.yml` (lint, typecheck, build, test)
|
|
35
|
+
as a reusable workflow against the tagged commit and only publishes once
|
|
36
|
+
it succeeds. It no longer carries its own test step, which had been
|
|
37
|
+
calling a `typecheck` script that no longer exists.
|
|
38
|
+
|
|
39
|
+
### [1.1.0] - Removed
|
|
40
|
+
|
|
41
|
+
- The `@opentui/core` and `@types/bun` dependencies, `bun.lock`, and the Bun
|
|
42
|
+
pin in `mise.toml` (now Node 24.20.0).
|
|
43
|
+
|
|
44
|
+
## [1.0.4] - 2026-09-11
|
|
45
|
+
|
|
46
|
+
### [1.0.4] - Added
|
|
47
|
+
|
|
48
|
+
- **Filenames-only mode.** Set `"filenamesOnly": true` in your config, or
|
|
49
|
+
pass `-f` / `--filenames-only`, to skip the summariser and send only
|
|
50
|
+
filenames to the final model. This reduces model work at the cost of
|
|
51
|
+
broader, less useful messages; the default remains `false`.
|
|
52
|
+
- Filename lists retain `ignore` filtering and `lowPriorityPaths` weighting,
|
|
53
|
+
including both paths of renames and copies. Formatting, templates, custom
|
|
54
|
+
instructions and interactive options still apply; the model is instructed
|
|
55
|
+
to avoid inventing specific edits or motivations from filenames alone.
|
|
56
|
+
- Verbose output identifies when the summariser was skipped. In this mode,
|
|
57
|
+
library results contain an empty `summaries` array and `chunkCount: 0`,
|
|
58
|
+
and the summary model is never called or preloaded.
|
|
59
|
+
|
|
60
|
+
## [1.0.3] - 2026-09-11
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- **Ollama models.** Any model can run on a local or self-hosted
|
|
65
|
+
[Ollama](https://ollama.com) server by prefixing its name with `ollama:`;
|
|
66
|
+
everything after the prefix is the Ollama model name verbatim, tag
|
|
67
|
+
included. The two pipeline stages resolve independently, so the diff can be
|
|
68
|
+
summarised locally and free while the final message still goes to Claude.
|
|
69
|
+
`cco` uses the native `/api/chat` endpoint rather than either compatibility
|
|
70
|
+
layer, because only the native API can set a context length.
|
|
71
|
+
- **`ollama.context`**, defaulting to `"auto"`. Ollama truncates an oversized
|
|
72
|
+
prompt silently - HTTP 200, oldest content dropped, nothing in the response
|
|
73
|
+
to say so - so `cco` never lets the window stay implicit: it preloads the
|
|
74
|
+
model with no window set, reads the server's own VRAM-based choice back from
|
|
75
|
+
`/api/ps`, pins that number on every request, sizes chunks against it, and
|
|
76
|
+
checks the returned token counts to catch a truncation that happened anyway.
|
|
77
|
+
A number pins the window instead.
|
|
78
|
+
- **`ollama.host`** (defaults to `$OLLAMA_HOST`, then `http://localhost:11434`)
|
|
79
|
+
and **`ollama.keepAlive`**, plus the `--ollama-host` and `--ollama-context`
|
|
80
|
+
flags.
|
|
81
|
+
- **`lowPriorityPaths`.** Gitignore-style patterns for churn-heavy paths whose
|
|
82
|
+
changes are summarised separately, so they cannot crowd out the code in the
|
|
83
|
+
final message. The content is still read and still costs the same; only its
|
|
84
|
+
weight changes. `--no-low-priority-paths` disables it for one run.
|
|
85
|
+
- **`ignore`.** The same pattern syntax, but matching file sections are removed
|
|
86
|
+
from the diff before anything else looks at it - before the low-priority
|
|
87
|
+
partition, before chunking, before any model call. The files are still
|
|
88
|
+
committed; `ignore` governs what the model reads, never what git stages. When
|
|
89
|
+
a pattern matches everything, `cco` stops with an error naming the directive
|
|
90
|
+
rather than inventing a message about changes you told it not to read.
|
|
91
|
+
`--no-ignore` disables it for one run.
|
|
92
|
+
|
|
93
|
+
### Changed
|
|
94
|
+
|
|
95
|
+
- The default spinner is now `material`.
|
|
96
|
+
- `@opentui/core` bumped to 0.5.7, alongside SDK and skill dependency bumps.
|
|
97
|
+
- CI workflows bump `checkout`, `setup-node` and `claude-code-action`.
|
|
98
|
+
|
|
99
|
+
## [1.0.2] - 2026-07-27
|
|
100
|
+
|
|
101
|
+
### [1.0.2] - Changed
|
|
102
|
+
|
|
103
|
+
- The default spinner is now `dwarfFortress` instead of `bouncingBall`.
|
|
104
|
+
|
|
105
|
+
## [1.0.1] - 2026-07-27
|
|
106
|
+
|
|
107
|
+
### [1.0.1] - Added
|
|
108
|
+
|
|
109
|
+
- **A configurable spinner.** The `spinner` config key accepts any name from
|
|
110
|
+
the [cli-spinners](https://github.com/sindresorhus/cli-spinners) set bundled
|
|
111
|
+
with [ora](https://github.com/sindresorhus/ora). Unknown names fall back to
|
|
112
|
+
the default rather than throwing, because a cosmetic option must never be
|
|
113
|
+
able to break a commit.
|
|
114
|
+
|
|
115
|
+
### [1.0.1] - Changed
|
|
116
|
+
|
|
117
|
+
- The progress spinner is an ora instance rather than a hand-rolled frame
|
|
118
|
+
timer. Enablement is still decided solely by the existing TTY and
|
|
119
|
+
`--no-spinner` checks - ora's own CI auto-detection is bypassed - and a final
|
|
120
|
+
success or failure line still prints when the animation is disabled.
|
|
121
|
+
|
|
122
|
+
## [1.0.0] - 2026-07-24
|
|
123
|
+
|
|
124
|
+
### [1.0.0] - Added
|
|
125
|
+
|
|
126
|
+
- **`--skip-armored`** and the matching `skipArmored` config key, replacing
|
|
127
|
+
each run of armoured or encoded lines with a short marker. Runs of one or two
|
|
128
|
+
lines survive, because a lone URL or hash is content. Ciphertext is
|
|
129
|
+
unreadable to the model and re-encrypts nondeterministically on every
|
|
130
|
+
`chezmoi re-add`, so this is the recommended mode for repos holding encrypted
|
|
131
|
+
files.
|
|
132
|
+
|
|
133
|
+
### [1.0.0] - Fixed
|
|
134
|
+
|
|
135
|
+
- **Chunks are sized by real token density.** `Prompt is too long` returned,
|
|
136
|
+
and the isolation fix in 0.1.3 turned out to have treated a symptom. Armoured
|
|
137
|
+
and base64 content tokenises at roughly 1.14 chars per token on current
|
|
138
|
+
Claude models, while chunk budgets assumed the configured `charsPerToken` of
|
|
139
|
+
3.5: a 1,247,318-character diff was estimated at ~356k tokens and really
|
|
140
|
+
counted ~1.19M. Long unbroken runs are now priced at their own, much denser
|
|
141
|
+
ratio. A third-party "real tokeniser" would not fix this class of bug -
|
|
142
|
+
tiktoken-style vocabularies compress base64 about three times better than
|
|
143
|
+
Claude's actual tokeniser, so they underestimate the same way.
|
|
144
|
+
- **The summary stage is a work queue.** If the backend rejects a chunk anyway
|
|
145
|
+
(its rejection is free, unbilled, and the only authoritative count), the
|
|
146
|
+
budget is halved, that chunk is re-split, and processing continues in place.
|
|
147
|
+
|
|
148
|
+
### [1.0.0] - Changed
|
|
149
|
+
|
|
150
|
+
- The 0.1.3 documentation blaming these failures on MCP/skill leakage is
|
|
151
|
+
corrected. That isolation stays as hygiene and cost control, but density was
|
|
152
|
+
the bug.
|
|
153
|
+
|
|
154
|
+
## [0.1.4] - 2026-07-23
|
|
155
|
+
|
|
156
|
+
### [0.1.4] - Fixed
|
|
157
|
+
|
|
158
|
+
- `cco --version` reported a hardcoded string rather than the installed package
|
|
159
|
+
version.
|
|
160
|
+
|
|
161
|
+
## [0.1.3] - 2026-07-23
|
|
162
|
+
|
|
163
|
+
### [0.1.3] - Fixed
|
|
164
|
+
|
|
165
|
+
- **Requests no longer inherit your global Claude Code context.** Runs failed
|
|
166
|
+
reporting ~1,149k tokens against a conversation of only ~301k; the missing
|
|
167
|
+
~848k were MCP tool definitions and skills pulled from the user's global
|
|
168
|
+
configuration into what should be an isolated prompt-in, text-out request.
|
|
169
|
+
The Agent SDK gates each context source separately, and `settingSources: []`
|
|
170
|
+
disables only settings files and `CLAUDE.md` - MCP servers and plugins load
|
|
171
|
+
regardless, and the CLI performs skill discovery even when the `skills`
|
|
172
|
+
option is omitted. Every switch is now set explicitly in one tested
|
|
173
|
+
`buildQueryOptions()`.
|
|
174
|
+
- **The chunk budget is clamped to the summary model's context window.**
|
|
175
|
+
`maxChunkTokens` was converted straight into a character budget regardless of
|
|
176
|
+
the configured model, so on any 200k-context model a single chunk could
|
|
177
|
+
exceed the whole window. It is now a cap rather than a promise, clamped to
|
|
178
|
+
the model's window minus a 32k reserve.
|
|
179
|
+
|
|
180
|
+
### [0.1.3] - Added
|
|
181
|
+
|
|
182
|
+
- npm publishing on version tags via CI.
|
|
183
|
+
|
|
184
|
+
## [0.1.2] - 2026-07-09
|
|
185
|
+
|
|
186
|
+
### [0.1.2] - Changed
|
|
187
|
+
|
|
188
|
+
- **Both pipeline stages default to `sonnet`.** The final stage's input is a
|
|
189
|
+
handful of summaries and its output is the entire point of the tool, so a
|
|
190
|
+
strong model there costs almost nothing and writes a visibly better message.
|
|
191
|
+
|
|
192
|
+
### [0.1.2] - Added
|
|
193
|
+
|
|
194
|
+
- MIT licence.
|
|
195
|
+
|
|
196
|
+
## [0.1.1] - 2026-07-02
|
|
197
|
+
|
|
198
|
+
### [0.1.1] - Changed
|
|
199
|
+
|
|
200
|
+
- Minor tweaks.
|
|
201
|
+
|
|
202
|
+
## [0.1.0] - 2026-07-02
|
|
203
|
+
|
|
204
|
+
The first release, published as `@synmux/claude-commit` and providing the `cco`
|
|
205
|
+
and `claude-commit` binaries.
|
|
206
|
+
|
|
207
|
+
### [0.1.0] - Added
|
|
208
|
+
|
|
209
|
+
- **The two-stage pipeline.** The diff is split into chunks that fit the
|
|
210
|
+
context window, each chunk is summarised, and the summaries are handed back
|
|
211
|
+
to a model to write the final message. Diffs too large for a single context
|
|
212
|
+
window simply produce more chunks.
|
|
213
|
+
- **Message formatting.** Conventional Commits (`-c`), gitmoji (`-g`),
|
|
214
|
+
multi-line subject and body (`-m`), a first-line template (`-t`), and
|
|
215
|
+
free-form extra instructions (`-p`).
|
|
216
|
+
- **Interactive mode.** `cco -i` lists candidate messages in a TUI, generated
|
|
217
|
+
at a higher temperature for variety, with the scrollable diff alongside.
|
|
218
|
+
- **Layered configuration.** Built-in defaults, a global user config, a
|
|
219
|
+
`claude-commit` key in the repo's `package.json`, the nearest dotted config
|
|
220
|
+
file, then CLI flags.
|
|
221
|
+
- **Structured output.** The final message is requested as JSON against a
|
|
222
|
+
`{ messages: string[] }` schema rather than parsed out of free-form text,
|
|
223
|
+
degrading to a temperature-free request and then to delimiter parsing.
|
|
224
|
+
- **`allowApiKey`, defaulting to false.** An exported `ANTHROPIC_API_KEY` would
|
|
225
|
+
otherwise silently switch every generation from subscription auth to
|
|
226
|
+
pay-as-you-go billing, because the SDK subprocess inherits `process.env`.
|
|
227
|
+
Those credentials are stripped unless you opt in.
|
|
228
|
+
|
|
229
|
+
[1.0.4]: https://github.com/synmux/claude-commit/compare/1.0.3...1.0.4
|
|
230
|
+
[1.0.3]: https://github.com/synmux/claude-commit/compare/1.0.2...1.0.3
|
|
231
|
+
[1.0.2]: https://github.com/synmux/claude-commit/compare/1.0.1...1.0.2
|
|
232
|
+
[1.0.1]: https://github.com/synmux/claude-commit/compare/1.0.0...1.0.1
|
|
233
|
+
[1.0.0]: https://github.com/synmux/claude-commit/compare/0.1.4...1.0.0
|
|
234
|
+
[0.1.4]: https://github.com/synmux/claude-commit/compare/0.1.3...0.1.4
|
|
235
|
+
[0.1.3]: https://github.com/synmux/claude-commit/compare/0.1.2...0.1.3
|
|
236
|
+
[0.1.2]: https://github.com/synmux/claude-commit/compare/0.1.1...0.1.2
|
|
237
|
+
[0.1.1]: https://github.com/synmux/claude-commit/compare/0.1.0...0.1.1
|
|
238
|
+
[0.1.0]: https://github.com/synmux/claude-commit/releases/tag/0.1.0
|
package/README.md
CHANGED
|
@@ -39,19 +39,29 @@ Either stage can run on a local [Ollama](#ollama-models) model instead; by
|
|
|
39
39
|
default both go through the
|
|
40
40
|
[Claude Agent SDK](https://code.claude.com/docs/en/agent-sdk/overview).
|
|
41
41
|
|
|
42
|
+
For less model work at the cost of less useful messages, enable
|
|
43
|
+
[`filenamesOnly`](#filenames-only-mode) to skip summarisation entirely.
|
|
44
|
+
|
|
42
45
|
## Install
|
|
43
46
|
|
|
44
|
-
Requires [
|
|
47
|
+
Requires [Node.js](https://nodejs.org) 22.18 or later (24 LTS recommended).
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
npm install -g @synmux/claude-commit # `cco` and `claude-commit` on your PATH
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
From a checkout, [pnpm](https://pnpm.io) is the package manager (the
|
|
54
|
+
`packageManager` field pins the version, so `corepack enable` is enough):
|
|
45
55
|
|
|
46
56
|
```sh
|
|
47
|
-
|
|
48
|
-
|
|
57
|
+
pnpm install
|
|
58
|
+
pnpm link --global # makes `cco` and `claude-commit` available on your PATH
|
|
49
59
|
```
|
|
50
60
|
|
|
51
61
|
Or run it directly without linking:
|
|
52
62
|
|
|
53
63
|
```sh
|
|
54
|
-
|
|
64
|
+
node bin/cco.js --help
|
|
55
65
|
```
|
|
56
66
|
|
|
57
67
|
## Authentication
|
|
@@ -85,28 +95,29 @@ and asks for confirmation before committing. Pass `-y` to skip the prompt, or
|
|
|
85
95
|
|
|
86
96
|
### Options
|
|
87
97
|
|
|
88
|
-
| Flag | Description
|
|
89
|
-
| ---------------------------------------- |
|
|
90
|
-
| `-i, --interactive` / `--no-interactive` | Choose between several options in an interactive
|
|
91
|
-
| `-n, --count <n>` | Number of options to generate in interactive mode (default 3)
|
|
92
|
-
| `-a, --all` | Stage all changes (`git add -A`) before committing
|
|
93
|
-
| `-c, --conventional` | Format as a [Conventional Commit](https://www.conventionalcommits.org)
|
|
94
|
-
| `-g, --gitmoji` | Prefix the subject with a [gitmoji](https://gitmoji.dev)
|
|
95
|
-
| `-m, --multiline` / `--no-multiline` | Write a multi-line commit (subject + body), or force a single line
|
|
96
|
-
| `-t, --template <tpl>` | Template for the first line, e.g. `"[PROJ-1] {message}"`
|
|
97
|
-
| `-p, --prompt <text>` | Extra instructions appended to the prompt
|
|
98
|
-
|
|
|
99
|
-
| `--model-
|
|
100
|
-
| `--
|
|
101
|
-
| `--
|
|
102
|
-
| `--no-
|
|
103
|
-
| `--
|
|
104
|
-
| `--ollama-
|
|
105
|
-
|
|
|
106
|
-
| `-
|
|
107
|
-
|
|
|
108
|
-
| `--
|
|
109
|
-
|
|
|
98
|
+
| Flag | Description |
|
|
99
|
+
| ---------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
100
|
+
| `-i, --interactive` / `--no-interactive` | Choose between several options in an interactive picker, or skip it when enabled in config |
|
|
101
|
+
| `-n, --count <n>` | Number of options to generate in interactive mode (default 3) |
|
|
102
|
+
| `-a, --all` | Stage all changes (`git add -A`) before committing |
|
|
103
|
+
| `-c, --conventional` | Format as a [Conventional Commit](https://www.conventionalcommits.org) |
|
|
104
|
+
| `-g, --gitmoji` | Prefix the subject with a [gitmoji](https://gitmoji.dev) |
|
|
105
|
+
| `-m, --multiline` / `--no-multiline` | Write a multi-line commit (subject + body), or force a single line |
|
|
106
|
+
| `-t, --template <tpl>` | Template for the first line, e.g. `"[PROJ-1] {message}"` |
|
|
107
|
+
| `-p, --prompt <text>` | Extra instructions appended to the prompt |
|
|
108
|
+
| `-f, --filenames-only` | Skip summarisation and send only filenames to the final model |
|
|
109
|
+
| `--model-summary <model>` | Model used to summarize the diff (default `sonnet`) |
|
|
110
|
+
| `--model-final <model>` | Model used to write the message (default `sonnet`) |
|
|
111
|
+
| `--skip-armored` | Omit armored/encoded lines (age/gpg armor, base64 blobs) from the summarized diff |
|
|
112
|
+
| `--no-low-priority-paths` | Ignore `lowPriorityPaths` for this run, so every change weighs the same |
|
|
113
|
+
| `--no-ignore` | Disregard `ignore` for this run, so every staged change is read |
|
|
114
|
+
| `--ollama-host <url>` | Base URL of the Ollama server for `ollama:` models |
|
|
115
|
+
| `--ollama-context <tokens>` | Context window requested from Ollama models |
|
|
116
|
+
| `-d, --dry-run` | Print the message to stdout without committing |
|
|
117
|
+
| `-y, --yes` | Commit without asking for confirmation |
|
|
118
|
+
| `--no-spinner` | Disable the progress spinner |
|
|
119
|
+
| `--config <path>` | Path to a config file |
|
|
120
|
+
| `-v, --verbose` | Print summaries, cost and debug output |
|
|
110
121
|
|
|
111
122
|
### Examples
|
|
112
123
|
|
|
@@ -115,20 +126,48 @@ cco # generate, confirm, and commit staged changes
|
|
|
115
126
|
cco -a -c # stage everything and write a Conventional Commit
|
|
116
127
|
cco -c -g -m # conventional + gitmoji + a body
|
|
117
128
|
cco -i -n 5 # pick from 5 options interactively
|
|
118
|
-
cco --dry-run
|
|
129
|
+
cco -f --dry-run # generate from filenames only, without committing
|
|
130
|
+
cco --dry-run | cat # print a message without committing (no picker, pipe-safe)
|
|
119
131
|
git commit -F <(cco -d) # use the message with your own git invocation
|
|
120
132
|
```
|
|
121
133
|
|
|
122
134
|
In a pipe (no TTY) there is no spinner and no confirmation prompt - `cco` just
|
|
123
135
|
generates and commits (or prints, with `--dry-run`).
|
|
124
136
|
|
|
137
|
+
## Filenames-only mode
|
|
138
|
+
|
|
139
|
+
Set `"filenamesOnly": true` in any config layer, or pass `-f` /
|
|
140
|
+
`--filenames-only`, to send only the list of filenames touched by staged
|
|
141
|
+
changes to `models.final`. The default is `false`.
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{ "filenamesOnly": true }
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The summariser is skipped entirely: no diff chunks, summary calls, or
|
|
148
|
+
summary-model preload. The final model receives no file contents or diff
|
|
149
|
+
hunks, so expect broader, less useful messages. It is instructed to describe
|
|
150
|
+
the affected areas without inventing specific edits or reasons for them.
|
|
151
|
+
Normal formatting, custom instructions and interactive options still apply.
|
|
152
|
+
|
|
153
|
+
`ignore` still removes matching file sections, and `lowPriorityPaths` still
|
|
154
|
+
groups and weights the remaining filenames. Renames and copies include both
|
|
155
|
+
paths; additions, deletions, binary files and mode changes are included.
|
|
156
|
+
If every staged file is ignored, generation still stops with an error.
|
|
157
|
+
|
|
158
|
+
`models.summary`, `maxChunkTokens`, `charsPerToken` and `skipArmored` have no
|
|
159
|
+
effect in this mode. `--verbose` reports that the summariser was skipped;
|
|
160
|
+
library results have an empty `summaries` array and `chunkCount: 0`.
|
|
161
|
+
|
|
125
162
|
## Interactive mode
|
|
126
163
|
|
|
127
|
-
`cco -i` opens a
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
164
|
+
`cco -i` opens a picker (built on [Clack](https://github.com/bombshell-dev/clack))
|
|
165
|
+
listing several candidate messages, each with its subject and a one-line body
|
|
166
|
+
preview. The options are generated with a higher temperature
|
|
167
|
+
(`interactiveTemperature`) for more variety. Use the arrow keys (or `j`/`k`) to
|
|
168
|
+
move between options, `Enter` to commit the highlighted option, `e` to edit it
|
|
169
|
+
in your `$EDITOR` first, and `q`/`Esc`/`Ctrl-C` to cancel. The picker draws on
|
|
170
|
+
stderr, so stdout stays clean.
|
|
132
171
|
|
|
133
172
|
To make interactive mode the default without typing `-i` every time, set
|
|
134
173
|
`"interactive": true` in your config (see below); opt out of a single run with
|
|
@@ -172,6 +211,7 @@ keys are valid at every level:
|
|
|
172
211
|
},
|
|
173
212
|
"maxChunkTokens": 600000,
|
|
174
213
|
"charsPerToken": 3.5,
|
|
214
|
+
"filenamesOnly": false,
|
|
175
215
|
"skipArmored": false,
|
|
176
216
|
"lowPriorityPaths": [],
|
|
177
217
|
"ignore": [],
|
|
@@ -226,7 +266,12 @@ those paths:
|
|
|
226
266
|
|
|
227
267
|
```json
|
|
228
268
|
{
|
|
229
|
-
"lowPriorityPaths": [
|
|
269
|
+
"lowPriorityPaths": [
|
|
270
|
+
".agents/skills/*-skilld",
|
|
271
|
+
"pnpm-lock.yaml",
|
|
272
|
+
"generated/**",
|
|
273
|
+
"!generated/schema.ts"
|
|
274
|
+
]
|
|
230
275
|
}
|
|
231
276
|
```
|
|
232
277
|
|
|
@@ -244,9 +289,9 @@ usually be copied in:
|
|
|
244
289
|
- A pattern with a `/` in it is anchored at the repository root and matches a
|
|
245
290
|
path or any directory above it - `.agents/skills/*-skilld` covers every file
|
|
246
291
|
inside each matching directory.
|
|
247
|
-
- A pattern without a `/` matches any path segment at any depth -
|
|
248
|
-
matches `packages/app/
|
|
249
|
-
`*-skilld` directory.
|
|
292
|
+
- A pattern without a `/` matches any path segment at any depth -
|
|
293
|
+
`pnpm-lock.yaml` matches `packages/app/pnpm-lock.yaml`; `*-skilld` matches
|
|
294
|
+
everything inside any `*-skilld` directory.
|
|
250
295
|
- `*` matches dotfiles and does not cross `/`; `**` does; `{a,b}` expands. A
|
|
251
296
|
leading `/` or `./` anchors, a trailing `/` is ignored. The anchoring
|
|
252
297
|
decision looks at the whole pattern, so a `/` inside a brace group anchors
|
|
@@ -399,10 +444,19 @@ Where the number comes from is `ollama.context`:
|
|
|
399
444
|
## Development
|
|
400
445
|
|
|
401
446
|
```sh
|
|
402
|
-
|
|
403
|
-
|
|
447
|
+
pnpm test # run the test suite (vitest)
|
|
448
|
+
pnpm run typecheck # tsc --noEmit
|
|
449
|
+
pnpm run build # bundle bin/ and index.ts into dist/ (only needed to publish)
|
|
404
450
|
```
|
|
405
451
|
|
|
452
|
+
The sources run directly on Node's native type stripping, so there is no build
|
|
453
|
+
step during development: `node bin/cco.js` picks up `dist/` when it exists and
|
|
454
|
+
falls back to the TypeScript entry otherwise.
|
|
455
|
+
|
|
456
|
+
What changed between versions is in [CHANGELOG.md](CHANGELOG.md), and at
|
|
457
|
+
greater length on the
|
|
458
|
+
[releases page](https://github.com/synmux/claude-commit/releases).
|
|
459
|
+
|
|
406
460
|
## Did you vibe this?
|
|
407
461
|
|
|
408
462
|
I distinguish vibe coding and AI-assisted development by
|
package/bin/cco.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Launcher for `cco` / `claude-commit`.
|
|
4
|
+
*
|
|
5
|
+
* The published package ships a bundled `dist/bin/cco.js` (Node refuses to
|
|
6
|
+
* strip types from files under `node_modules`); a development checkout runs
|
|
7
|
+
* the TypeScript entry directly through Node's native type stripping. Build
|
|
8
|
+
* output wins when present, so `pnpm run build` is only ever needed for
|
|
9
|
+
* publishing.
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync } from "node:fs";
|
|
12
|
+
|
|
13
|
+
const bundled = new URL("../dist/bin/cco.js", import.meta.url);
|
|
14
|
+
const source = new URL("./cco.ts", import.meta.url);
|
|
15
|
+
|
|
16
|
+
await import(existsSync(bundled) ? bundled.href : source.href);
|
package/bin/cco.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
1
|
/**
|
|
3
2
|
* Executable entry point for `cco` / `claude-commit`.
|
|
4
3
|
*/
|
|
5
|
-
import { run } from "../src/cli";
|
|
6
|
-
import { color } from "../src/ui/colors";
|
|
4
|
+
import { run } from "../src/cli.ts";
|
|
5
|
+
import { color } from "../src/ui/colors.ts";
|
|
7
6
|
|
|
8
7
|
run(process.argv.slice(2))
|
|
9
8
|
.then((code) => {
|
|
@@ -11,8 +10,6 @@ run(process.argv.slice(2))
|
|
|
11
10
|
})
|
|
12
11
|
.catch((err) => {
|
|
13
12
|
// Unexpected (non-ClaudeCommitError) failures: print a stack for debugging.
|
|
14
|
-
process.stderr.write(
|
|
15
|
-
`${color("31", "unexpected error:")} ${err?.stack ?? err}\n`,
|
|
16
|
-
);
|
|
13
|
+
process.stderr.write(`${color("31", "unexpected error:")} ${err?.stack ?? err}\n`);
|
|
17
14
|
process.exitCode = 1;
|
|
18
15
|
});
|