amont 1.44.0 → 1.45.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/README.md +53 -284
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -6,327 +6,96 @@
|
|
|
6
6
|
[](https://github.com/fredericrous/amont/releases/latest)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
|
|
9
|
-
A single Rust binary that checks `git commit` and `git push
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
— a gate pre-commit, lefthook and husky do not have.
|
|
19
|
-
- **Nothing on the commit path but `std`.** The hook binary links no external
|
|
20
|
-
crates, and CI fails any build that changes that.
|
|
21
|
-
- **Leaving is one command.** `amont uninstall` removes exactly the five
|
|
22
|
-
shims install wrote; a hook you or another tool put there is named and left
|
|
23
|
-
alone.
|
|
9
|
+
A single Rust binary that checks `git commit` and `git push`. It ships
|
|
10
|
+
thirty-eight built-in checks — commit-message conventions, conflict markers,
|
|
11
|
+
secrets, the linters and test suites of the languages your repository actually
|
|
12
|
+
uses — and each one fires only where the repository has opted into its tool, so
|
|
13
|
+
there is no YAML to write before it is useful. The commit path links no
|
|
14
|
+
external crates, a cloned repository's own checks stay inert until you
|
|
15
|
+
`amont trust` them, and `amont uninstall` removes exactly the six shims install
|
|
16
|
+
wrote. [How it compares](docs/similar-projects.md) to pre-commit, lefthook and
|
|
17
|
+
husky.
|
|
24
18
|
|
|
25
19
|

|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
## Install
|
|
31
|
-
|
|
32
|
-
```sh
|
|
33
|
-
# Linux and macOS
|
|
34
|
-
curl -fsSL https://raw.githubusercontent.com/fredericrous/amont/main/install/install.sh | sh
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
```powershell
|
|
38
|
-
# Windows (the line above is POSIX sh and only reaches Windows through Git Bash)
|
|
39
|
-
irm https://raw.githubusercontent.com/fredericrous/amont/main/install/install.ps1 | iex
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Either one downloads a release binary, verifies it against the published
|
|
43
|
-
`SHA256SUMS`, and puts it where the hooks already look. Both **enable
|
|
44
|
-
nothing** — hooks are turned on per repository, by you, afterwards:
|
|
45
|
-
|
|
46
|
-
```sh
|
|
47
|
-
cd <your-repo> && amont install # this repository only
|
|
48
|
-
amont list # what would run here, and why not
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Homebrew, crates.io, npm, prebuilt binaries for six targets, building from
|
|
52
|
-
source, and what `--force` will and will not do:
|
|
53
|
-
[installing and activating](docs/install.md).
|
|
54
|
-
|
|
55
|
-
## What actually runs
|
|
56
|
-
|
|
57
|
-
`amont list` answers that for the repository you are standing in, and it is
|
|
58
|
-
the honest answer rather than the catalogue: most checks are **inert** in most
|
|
59
|
-
repositories, because a repo with no `ruff.toml` never needs ruff.
|
|
21
|
+
`amont list` says what runs in the repository you are standing in — here, a
|
|
22
|
+
Python one:
|
|
60
23
|
|
|
61
24
|
```
|
|
62
25
|
pre-commit
|
|
63
26
|
● ban-terms
|
|
64
|
-
|
|
65
|
-
●
|
|
66
|
-
|
|
67
|
-
○ prettier inert here — needs .prettierrc | .prettierrc.json | …
|
|
68
|
-
● usual-name
|
|
27
|
+
● ruff
|
|
28
|
+
● secrets
|
|
29
|
+
…
|
|
69
30
|
pre-push
|
|
70
|
-
●
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
○ cargo-test inert here — needs .rs + Cargo.toml
|
|
74
|
-
|
|
75
|
-
● runs here ○ inert ⊘ skipped via hook.skip ✗ declaration unusable
|
|
31
|
+
● audit-python
|
|
32
|
+
…
|
|
33
|
+
15 active here. 23 inert (Go, JavaScript, Kubernetes, Python, Rust) — amont list --all
|
|
76
34
|
```
|
|
77
35
|
|
|
78
|
-
|
|
79
|
-
declares itself. What each one needs before it fires:
|
|
80
|
-
[the checks reference](docs/checks.md).
|
|
81
|
-
|
|
82
|
-
## Turning hooks on
|
|
83
|
-
|
|
84
|
-
**Per repository** is the default, and nothing runs anywhere you did not ask:
|
|
85
|
-
|
|
86
|
-
```sh
|
|
87
|
-
cd <your-repo> && amont install
|
|
88
|
-
amont-fleet install --root ~/Developer # or in bulk, across many repos
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
**Everywhere, forever** is an opt-in, and a real one:
|
|
92
|
-
|
|
93
|
-
```sh
|
|
94
|
-
amont enroll --conventions declared
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
One command per machine: every future `git clone` and `git init` arrives with
|
|
98
|
-
the hooks. `--conventions declared` keeps the house rules — commit shapes,
|
|
99
|
-
branch names, gates — scoped to repositories that commit an `amont.conf`,
|
|
100
|
-
while the safety net of conflict markers, secrets, oversized files and debug
|
|
101
|
-
leftovers runs everywhere.
|
|
102
|
-
|
|
103
|
-
That split is what makes the grant safe on a machine that also clones other
|
|
104
|
-
people's projects. It is still a standing grant, so it is worth stating what
|
|
105
|
-
you granted: a cloned repository's own checks are then one `amont trust` away
|
|
106
|
-
from running on your first commit in a repository you may have cloned only to
|
|
107
|
-
read. **Trust deliberately** rather than letting installation be the moment
|
|
108
|
-
you decided. The full reasoning, and rolling this out to a team:
|
|
109
|
-
[team rollout](docs/team-rollout.md).
|
|
110
|
-
|
|
111
|
-
## Trust: a repository you clone cannot run its own checks
|
|
112
|
-
|
|
113
|
-
`amont.conf` is committed — that is the point, a team shares a check by
|
|
114
|
-
committing a line rather than by everybody installing something. So a
|
|
115
|
-
repository you cloned can _declare_ checks, and running them is a decision you
|
|
116
|
-
make, not one `git clone` makes for you.
|
|
36
|
+
## Install
|
|
117
37
|
|
|
118
38
|
```sh
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
amont trust --revoke
|
|
39
|
+
# Linux and macOS
|
|
40
|
+
curl -fsSL https://raw.githubusercontent.com/fredericrous/amont/main/install/install.sh | sh
|
|
122
41
|
```
|
|
123
42
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
before it. [The trust model](docs/trust.md).
|
|
128
|
-
|
|
129
|
-
## Custom checks, and packs
|
|
130
|
-
|
|
131
|
-
A repository declares checks of its own in a committed `amont.conf` — five
|
|
132
|
-
whitespace-separated fields, no shell:
|
|
133
|
-
|
|
134
|
-
```
|
|
135
|
-
# stage name scope severity command
|
|
136
|
-
pre-commit lint-shell *.sh block scripts/lint-shell.sh
|
|
137
|
-
pre-commit rubocop *.rb+.rubocop.yml block rubocop
|
|
138
|
-
pre-push smoke * warn make smoke
|
|
43
|
+
```powershell
|
|
44
|
+
# Windows
|
|
45
|
+
irm https://raw.githubusercontent.com/fredericrous/amont/main/install/install.ps1 | iex
|
|
139
46
|
```
|
|
140
47
|
|
|
141
|
-
|
|
142
|
-
`
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
repository carries_: `*.rb+.rubocop.yml` reads "a staged `.rb`, **and** this
|
|
146
|
-
repository has a `.rubocop.yml`". That is what lets a check be safe to hand to
|
|
147
|
-
somebody else.
|
|
148
|
-
|
|
149
|
-
### Shipping one — packs
|
|
48
|
+
Either one downloads a release binary, checks it against the published
|
|
49
|
+
`SHA256SUMS`, and **enables nothing**. Homebrew, crates.io, npm, prebuilt
|
|
50
|
+
archives and building from source: [installing](docs/install.md). Needs git
|
|
51
|
+
2.31 or later.
|
|
150
52
|
|
|
151
|
-
|
|
152
|
-
that same syntax. `amont add` vendors its rows into your `amont.conf`:
|
|
53
|
+
## Turning hooks on
|
|
153
54
|
|
|
154
55
|
```sh
|
|
155
|
-
amont
|
|
56
|
+
cd <your-repo> && amont install # this repository only — the default
|
|
57
|
+
amont-fleet install --root ~/Developer # many repositories at once
|
|
58
|
+
amont enroll --conventions declared # every future clone on this machine
|
|
156
59
|
```
|
|
157
60
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
moment anything becomes runnable.
|
|
162
|
-
|
|
163
|
-
Want to write one? [`fredericrous/amont-pack-java`](https://github.com/fredericrous/amont-pack-java)
|
|
164
|
-
is a complete worked example — two rows, one for Maven and one for Gradle, so
|
|
165
|
-
half of it is visibly inert wherever you install it. Its README is the
|
|
166
|
-
long-form authoring guide: gating your rows, what a pack may not carry, and
|
|
167
|
-
how to publish and tag one.
|
|
168
|
-
|
|
169
|
-
Full reference for both: [custom checks](docs/custom-checks.md).
|
|
61
|
+
`enroll` is a standing grant; read [rolling out to a team](docs/team-rollout.md)
|
|
62
|
+
before you use it. `amont uninstall` removes the shims again —
|
|
63
|
+
[opting out](docs/opting-out.md) covers that and everything short of it.
|
|
170
64
|
|
|
171
65
|
## Day to day
|
|
172
66
|
|
|
173
67
|
```sh
|
|
174
|
-
amont run
|
|
175
|
-
amont run --all-files
|
|
176
|
-
amont check src/main.rs
|
|
177
|
-
|
|
178
|
-
amont
|
|
179
|
-
amont rehearse --wait # the push gate on a snapshot of HEAD, before
|
|
180
|
-
# git opens a connection — the push then skips it
|
|
181
|
-
amont restore # bring back unstaged work a killed hook parked
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
`amont run --all-files` on a dirty tree reports on content that is not
|
|
185
|
-
committed and may never be — which is what you want when adopting a check into
|
|
186
|
-
an existing repository, where `git add .` is not an acceptable way to measure
|
|
187
|
-
the mess.
|
|
188
|
-
|
|
189
|
-
Turning one off, or down:
|
|
190
|
-
|
|
191
|
-
```sh
|
|
68
|
+
amont run # would my commit pass? (the staged set)
|
|
69
|
+
amont run --all-files # does my working tree pass?
|
|
70
|
+
amont check src/main.rs # these files, in the format editors already parse
|
|
71
|
+
amont rehearse --wait # the push gate on a snapshot of HEAD, before you push
|
|
72
|
+
amont trust # review what this repository's amont.conf declares
|
|
192
73
|
git config amont.severity.clippy warn # runs, reports, does not block
|
|
193
74
|
git config hook.skip clippy # does not run at all
|
|
194
75
|
```
|
|
195
76
|
|
|
196
|
-
Prefer the downgrade: it keeps the check working and keeps you looking at what
|
|
197
|
-
it finds. [Opting out](docs/opting-out.md) · [configuration](docs/configuration.md)
|
|
198
|
-
· [commit conventions](docs/commit-convention.md).
|
|
199
|
-
|
|
200
|
-
**What a push actually tests.** By default `pre-push` runs your suite against
|
|
201
|
-
the _working tree_, and says so — fast, and usually what you want, but not what
|
|
202
|
-
you are pushing. `git config amont.testPushedTree true` runs it in a throwaway
|
|
203
|
-
checkout of the commits being pushed instead.
|
|
204
|
-
|
|
205
|
-
**For coding agents.** `amont list --json` is the same answer as `amont list`,
|
|
206
|
-
machine-readable: declared and effective severity, whether each check fires
|
|
207
|
-
here and why not, and the command if it is a declared external. `--stage`
|
|
208
|
-
filters to one trigger, `--pushed` scopes to what your next push would carry.
|
|
209
|
-
`amont agents-md` writes the guidance block into `AGENTS.md`.
|
|
210
|
-
[Where the hooks fit in your flow](docs/coding-flow.md).
|
|
211
|
-
|
|
212
|
-
## One view across every repo
|
|
213
|
-
|
|
214
|
-
`amont-fleet` — installed separately, on purpose — answers the questions a
|
|
215
|
-
directory full of repositories accumulates: which repos are covered, which
|
|
216
|
-
shims went stale after an upgrade, and which repository is quietly carrying a
|
|
217
|
-
`hook.skip` somebody forgot.
|
|
218
|
-
|
|
219
|
-

|
|
220
|
-
|
|
221
|
-
```sh
|
|
222
|
-
amont-fleet install --root ~/Developer # shims into every repo at once
|
|
223
|
-
amont-fleet # report the fleet
|
|
224
|
-
amont-fleet tui # the dashboard above
|
|
225
|
-
amont-fleet fix --root ~/Developer # what drifted (dry run)
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
Design record: [the fleet dashboard](docs/fleet-dashboard.md).
|
|
229
|
-
|
|
230
|
-
## Why you can let this near your commits
|
|
231
|
-
|
|
232
|
-
A prompt theme is cosmetic. This blocks commits and pushes, reads every staged
|
|
233
|
-
file, and runs with your credentials while nobody is watching — so the claim it
|
|
234
|
-
has to earn is not "delightful", it is "harmless".
|
|
235
|
-
|
|
236
|
-
- **The commit path links no external crates.** `amont` and `amont-runtime`
|
|
237
|
-
are std-only, and `scripts/check-no-deps.sh` fails a build that changes
|
|
238
|
-
that — fails _closed_, so a cargo error or an unreachable registry is a
|
|
239
|
-
failure rather than a reassuring green tick.
|
|
240
|
-
- **No network, ever.** No telemetry, no update checks, no fetches. With the
|
|
241
|
-
commit path std-only there is not even an HTTP client linked to do it with.
|
|
242
|
-
- **Over a thousand tests**, run on Linux, macOS and Windows, alongside
|
|
243
|
-
`cargo fmt --check`, `clippy -D warnings`, an MSRV floor of 1.74 compiled
|
|
244
|
-
for the commit path, and `cargo-audit`.
|
|
245
|
-
- **v1.0.0 followed a full security review**, and each finding landed with a
|
|
246
|
-
committed reproduction — a drive-by RCE via a relative path in the shim, a
|
|
247
|
-
held-store format that let a repository plant a symlink outside the
|
|
248
|
-
worktree, a trust prompt a repository could conceal declarations from.
|
|
249
|
-
- **Your uncommitted work is the thing that must never be lost.** The release
|
|
250
|
-
profile deliberately omits `panic = "abort"` so the `Drop` that restores
|
|
251
|
-
unstaged work still runs when a check panics — with a test asserting on the
|
|
252
|
-
manifest, because no behavioural test could catch that regression.
|
|
253
|
-
|
|
254
|
-
Threat model and private reporting: [SECURITY.md](SECURITY.md).
|
|
255
|
-
|
|
256
|
-
## Requirements
|
|
257
|
-
|
|
258
|
-
**Git 2.31+** — `git rev-parse --path-format=absolute` landed there, and three
|
|
259
|
-
places depend on it. On an older git those return nothing rather than failing
|
|
260
|
-
loudly, which is the worst shape for a version floor.
|
|
261
|
-
|
|
262
|
-
The hooks are a single binary with no runtime dependencies. Each check brings
|
|
263
|
-
its own tool requirement only where you have opted into that check.
|
|
264
|
-
|
|
265
|
-
Everything works on Windows; the one difference is that there is no symlink,
|
|
266
|
-
so `init.templateDir` points straight at the checkout. [Details](docs/install.md).
|
|
267
|
-
|
|
268
|
-
## The repositories around it
|
|
269
|
-
|
|
270
|
-
Three companions, each its own repository because it runs somewhere amont
|
|
271
|
-
deliberately does not:
|
|
272
|
-
|
|
273
|
-
- [**amont-agent**](https://github.com/fredericrous/amont-agent) — a Claude
|
|
274
|
-
Code `PreToolUse` hook for the mistake no git hook can reach, because it
|
|
275
|
-
lives in the command string itself: `git push … | tail -5` reports tail's
|
|
276
|
-
exit status, so a rejected push reads as success. The guard judges the
|
|
277
|
-
pipeline before it runs. Independent by design — no shared code, and
|
|
278
|
-
neither needs the other; they meet in one optional place, where its
|
|
279
|
-
session notice asks `amont agents-md --check` whether the guidance block
|
|
280
|
-
an agent is about to believe has gone stale.
|
|
281
|
-
- [**attest**](https://github.com/fredericrous/attest) — the CI half of
|
|
282
|
-
`amont.attest`: when every pre-push block gate passed locally, amont
|
|
283
|
-
leaves a **signed** note on the tree it tested, and this single-purpose
|
|
284
|
-
verifier lets CI skip work provably already done. Fail-open by
|
|
285
|
-
construction, and separate precisely so that amont itself never runs in
|
|
286
|
-
CI — [the reasoning](docs/ci.md).
|
|
287
|
-
- [**amont-pack-java**](https://github.com/fredericrous/amont-pack-java) —
|
|
288
|
-
the worked example of [a pack](#shipping-one--packs): how checks amont
|
|
289
|
-
deliberately does not build in get shipped anyway.
|
|
290
|
-
|
|
291
77
|
## Documentation
|
|
292
78
|
|
|
293
|
-
|
|
294
|
-
|
|
79
|
+
Versioned with the code in [`docs/`](docs/) and published as a
|
|
80
|
+
[book](https://fredericrous.github.io/amont/):
|
|
295
81
|
|
|
296
|
-
- [Installing and activating](docs/install.md)
|
|
82
|
+
- [Installing and activating](docs/install.md) ·
|
|
83
|
+
[Rolling out to a team](docs/team-rollout.md) · [The CI backstop](docs/ci.md)
|
|
297
84
|
- [The checks](docs/checks.md) · [Configuration](docs/configuration.md) ·
|
|
298
|
-
[Opting out](docs/opting-out.md)
|
|
299
|
-
- [The trust model](docs/trust.md) · [Custom checks and packs](docs/custom-checks.md)
|
|
85
|
+
[Opting out](docs/opting-out.md) · [Commit conventions](docs/commit-convention.md)
|
|
300
86
|
- [Where the hooks fit in your flow](docs/coding-flow.md) ·
|
|
301
|
-
[
|
|
302
|
-
|
|
303
|
-
[
|
|
304
|
-
[
|
|
305
|
-
- Decision records for maintainers: [hook architecture](docs/hook-architecture.md),
|
|
306
|
-
[index fidelity and run modes](docs/index-fidelity-and-run-modes.md),
|
|
307
|
-
[skip management](docs/hook-skip-management.md),
|
|
308
|
-
[the fleet dashboard](docs/fleet-dashboard.md),
|
|
309
|
-
[the Rust migration](docs/rust-migration.md)
|
|
87
|
+
[The trust model](docs/trust.md) · [Custom checks and packs](docs/custom-checks.md)
|
|
88
|
+
- [Why you can let this near your commits](docs/index.md#why-you-can-let-this-near-your-commits) ·
|
|
89
|
+
[The repositories around it](docs/index.md#the-repositories-around-it) ·
|
|
90
|
+
[SECURITY.md](SECURITY.md) · [design records](docs/SUMMARY.md#design-records)
|
|
310
91
|
|
|
311
92
|
## Contributing
|
|
312
93
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
crates/amont-fleet/ the dashboard and the fleet fixer. Opt-in.
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
`make check` is the CI-parity target — run it before you push. Setup, the
|
|
322
|
-
zero-dependency rule and when reopening it is legitimate, the house test style
|
|
323
|
-
and the commit convention are all in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
324
|
-
|
|
325
|
-
Questions, "does this work with X", ideas for checks:
|
|
326
|
-
[Discussions](https://github.com/fredericrous/amont/discussions). Bugs:
|
|
327
|
-
[issues](https://github.com/fredericrous/amont/issues).
|
|
328
|
-
|
|
329
|
-
By participating you agree to the [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
94
|
+
`make check` is the CI-parity target; setup, the zero-dependency rule and the
|
|
95
|
+
house style are in [CONTRIBUTING.md](CONTRIBUTING.md). Questions in
|
|
96
|
+
[Discussions](https://github.com/fredericrous/amont/discussions), bugs in
|
|
97
|
+
[issues](https://github.com/fredericrous/amont/issues). By participating you
|
|
98
|
+
agree to the [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
330
99
|
|
|
331
100
|
## License
|
|
332
101
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amont",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.45.0",
|
|
4
4
|
"description": "Opinionated git hooks that judge what you are committing, not what is on disk",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"git",
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
"node": ">=18"
|
|
33
33
|
},
|
|
34
34
|
"optionalDependencies": {
|
|
35
|
-
"@amont-hooks/darwin-arm64": "1.
|
|
36
|
-
"@amont-hooks/darwin-x64": "1.
|
|
37
|
-
"@amont-hooks/linux-arm64-gnu": "1.
|
|
38
|
-
"@amont-hooks/linux-x64-gnu": "1.
|
|
39
|
-
"@amont-hooks/linux-x64-musl": "1.
|
|
40
|
-
"@amont-hooks/win32-x64": "1.
|
|
35
|
+
"@amont-hooks/darwin-arm64": "1.45.0",
|
|
36
|
+
"@amont-hooks/darwin-x64": "1.45.0",
|
|
37
|
+
"@amont-hooks/linux-arm64-gnu": "1.45.0",
|
|
38
|
+
"@amont-hooks/linux-x64-gnu": "1.45.0",
|
|
39
|
+
"@amont-hooks/linux-x64-musl": "1.45.0",
|
|
40
|
+
"@amont-hooks/win32-x64": "1.45.0"
|
|
41
41
|
}
|
|
42
42
|
}
|