amont 1.43.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.
Files changed (2) hide show
  1. package/README.md +53 -284
  2. package/package.json +7 -7
package/README.md CHANGED
@@ -6,327 +6,96 @@
6
6
  [![Release](https://img.shields.io/github/v/release/fredericrous/amont?label=release)](https://github.com/fredericrous/amont/releases/latest)
7
7
  [![License](https://img.shields.io/github/license/fredericrous/amont)](LICENSE)
8
8
 
9
- A single Rust binary that checks `git commit` and `git push` — no YAML to
10
- write, no runtime to install, nothing to configure before it is useful.
11
-
12
- - **Useful in the first minute.** Thirty-eight built-in checks — commit-message
13
- conventions, merge-conflict markers, the linters and formatters for the
14
- languages your repository actually uses, branch rules, your test suite —
15
- and each one fires only where the repository has opted into its tool.
16
- - **A cloned repository cannot run code on your machine.** Checks a repository
17
- declares for itself are inert until you review them and say `amont trust`
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
  ![amont catching a commit and letting the fixed one through](docs/assets/amont-demo.gif)
26
20
 
27
- How that stacks up against pre-commit, lefthook and husky, feature by feature:
28
- [the full comparison](docs/similar-projects.md).
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
- ○ cargo-fmt inert here — needs .rs + Cargo.toml
65
- ● lint-json-yaml
66
- ● merge-conflict
67
- ○ prettier inert here — needs .prettierrc | .prettierrc.json | …
68
- ● usual-name
27
+ ● ruff
28
+ ● secrets
29
+ …
69
30
  pre-push
70
- ● branch-protect
71
- ● branch-pattern
72
- ● pull-rebase
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
- Thirty-eight built-in checks across six git hooks, plus any your repository
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
- amont trust # show what it declares, then record it
120
- amont trust --show # what it declares, and whether it is trusted
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
- Until then the declarations are **reported, not dropped** — you can see there
125
- is a decision waiting. Acceptance is recorded against the file's _content_, so
126
- a `git pull` that adds a command does not inherit the trust you gave the file
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
- They run alongside the built-ins, obey the same `hook.skip` and
142
- `amont.severity` controls, and are inert until trusted.
143
-
144
- The `+` in the scope column splits _what the change touches_ from _what the
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
- A **pack** is any git repository with an `amont.pack` at its root, written in
152
- that same syntax. `amont add` vendors its rows into your `amont.conf`:
53
+ ## Turning hooks on
153
54
 
154
55
  ```sh
155
- amont add github:fredericrous/amont-pack-java@v1
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
- What ships is **text, not execution**. The rows land between markers with the
159
- pack's commit id beside them, the manifest's fingerprint changes, and every
160
- declared check is inert until you `amont trust` it. Adding a pack is never the
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 # would my commit pass? (the staged set)
175
- amont run --all-files # does my working tree pass? (git ls-files)
176
- amont check src/main.rs # what is wrong with these FILES — no index, no
177
- # staging; `file:line: message` an editor can parse
178
- amont list # what would run here, and why not
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
- ![the amont-fleet dashboard scanning a fleet of repositories](docs/assets/fleet-demo.gif)
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
- The full documentation is in [`docs/`](docs/), versioned with the code and
294
- published as a book:
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
- [Commit conventions](docs/commit-convention.md) ·
302
- [CI, and why amont does not run in it](docs/ci.md) ·
303
- [How it compares](docs/similar-projects.md) ·
304
- [Ideas, not a roadmap](docs/ideas.md)
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
- Everything is Rust, in `crates/`:
314
-
315
- ```
316
- crates/amont-runtime/ the checks, registry and dispatchers. std only.
317
- crates/amont/ the hook binary. Runs on every commit. std only.
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.43.0",
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.43.0",
36
- "@amont-hooks/darwin-x64": "1.43.0",
37
- "@amont-hooks/linux-arm64-gnu": "1.43.0",
38
- "@amont-hooks/linux-x64-gnu": "1.43.0",
39
- "@amont-hooks/linux-x64-musl": "1.43.0",
40
- "@amont-hooks/win32-x64": "1.43.0"
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
  }