Skip to content

perf: use mimalloc as the global allocator - #1635

Merged
jdx merged 1 commit into
mainfrom
claude/mimalloc
Oct 3, 2026
Merged

jdx merged 1 commit into
mainfrom
claude/mimalloc

Conversation

@jdx

@jdx jdx commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

https://entire.io/gh/jdx/hk/trails/211

Summary

Sets mimalloc as hk's global allocator. pklr's config evaluation is allocation-heavy: profiling showed about half its time in malloc/free with the system allocator.

config.rs now spells std::env!("OUT_DIR") explicitly. With the mimalloc crate added, the bare env! became ambiguous with hk's own env module (cannot determine resolution for the macro env), on both stable and beta.

Measurements

hk validate on this repo's hk.pkl, release build, hyperfine with 8 runs:

Allocator Time
System 1.180 s ± 0.034 s
mimalloc 0.674 s ± 0.021 s

That's 1.75x faster. Separate pklr performance work is in progress (jdx/pklr#223), and the two gains stack.

Testing

  • cargo build --release and cargo clippy --all-targets -- -D warnings are clean
  • cargo fmt --check is clean
  • cargo test: 16 cli::init::detector tests fail on this machine both with and without this change, so they're unrelated

AI-assisted — Tool: Claude Code; model: anthropic/claude-opus-5-5; version: 2.1.286.

🤖 Generated with Claude Code


Note

Low Risk
Infrastructure-only change (allocator swap plus a macro path fix); no auth, config semantics, or hook behavior changes.

Overview
Sets mimalloc as hk’s process-wide allocator to speed up allocation-heavy pklr config evaluation (roughly ~1.75× on hk validate in release, per PR benchmarks).

Adds the mimalloc dependency and registers MiMalloc via #[global_allocator] in main.rs.

Fixes a compile-time macro clash: embedded package bytes in config.rs now use std::env!("OUT_DIR") instead of bare env!, because the new dependency made env! ambiguous with hk’s env module.

Reviewed by Cursor Bugbot for commit e9d3d83. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Performance
    • Configuration evaluation is now approximately one-third faster, helping the application start more quickly when loading configuration. Actual startup improvement may vary depending on your environment and configuration size.

Evaluating hk.pkl through pklr is allocation-heavy, and with the system
allocator about half of pklr's time went to malloc and free. With
mimalloc, `hk validate` on this repo's config drops from 1.18 s to
0.67 s.

config.rs now spells `std::env!` explicitly: adding the mimalloc crate
made the bare `env!` ambiguous with the crate's own `env` module
("cannot determine resolution for the macro `env`") on stable and beta.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M41ZTCA6R1ZSPT15YMNVZMKE
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​mimalloc@​0.1.5210010093100100

View full report

@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f1cb0172-b342-4362-9028-c6b9a55d4c0c
📥 Commits

Reviewing files that changed from the base of the PR and between 8e63f1e and e9d3d83.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • Cargo.toml
  • src/config.rs
  • src/main.rs

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The change adds mimalloc as a dependency and sets it as the global allocator. It also updates the embedded package path to read OUT_DIR with std::env!.

Changes

Runtime and configuration updates

Layer / File(s) Summary
Add and set the global allocator
Cargo.toml, src/main.rs
Cargo.toml adds mimalloc version 0.1. src/main.rs sets mimalloc as the process-wide global allocator.
Read the embedded package path
src/config.rs
The embedded package path reads OUT_DIR with std::env! instead of env!.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to e9d3d

The PR changes hk’s allocator and preserves the generated Pkl package path. No supported-build failure or other actionable merge blocker is established.

Security Architecture Review

Security architecture risk: 🔵 Low · up to e9d3d

The allocator change affects memory management throughout hk, but the inspected changes do not add privileges or new input paths. No concrete security regression was identified. Native dependency behavior and compatibility across release platforms remain incompletely verified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The directly affected scope is Rust global allocation within the hk process, including configuration evaluation and concurrent runtime work. An allocator defect could therefore affect process-wide memory integrity or availability, although no such defect was identified.

Trust Boundaries and Controls

  • inferred — Qualifying std::env! does not turn OUT_DIR into a runtime input. The embedded bytes remain selected during compilation, and the inspected evaluator retains its offline setting, cache configuration, and conditional preload behavior. This change does not expand configuration-input reachability.

Resilience and Maintainability Implications

  • inferred — The inspected lifecycle has one fixed global allocator and no newly added manual allocation/free, teardown, or allocator-switch path. Inspected FFI-adjacent code retains local Rust ownership rather than introducing native cleanup of Rust allocations. This counters an ownership-mismatch concern, but does not verify allocation behavior inside transitive native dependencies.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely states the main change: using mimalloc as the global allocator.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Replaces the memory allocator with a third-party library.

The PR appears safe to merge; no actionable failure was established.

Summary

This PR makes mimalloc hk’s global allocator to improve allocation-heavy configuration evaluation and qualifies the OUT_DIR macro reference to avoid name ambiguity.

  • Adds mimalloc and its native dependency to the manifest and lockfile.
  • Applies the allocator unconditionally to the binary.

Reviews (1) · Last reviewed commit: "perf: use mimalloc as the global allocat..."

@jdx
jdx enabled auto-merge (squash) October 3, 2026 23:26
@jdx
jdx merged commit 2b200ef into main Oct 3, 2026
29 of 32 checks passed
@jdx
jdx deleted the claude/mimalloc branch October 3, 2026 23:42
jdx added a commit to jdx/pklr that referenced this pull request Oct 4, 2026
… config 180 ms -> 24 ms) (#229)

<!-- entire-trail-link-start -->
https://entire.io/gh/jdx/pklr/trails/34
<!-- entire-trail-link-end -->

Part of a stack: #225 → #227 → #228 → **#229**.

## Summary

`import* "dir/*.pkl" as Alias` evaluated every matched module up front.
When the importing code reads the mapping only as `Alias["key"]`, the
import-use analysis now records those keys the way it records
`Alias.field`, and the glob import evaluates just the matching modules.

Any other use of the mapping still evaluates every module: `Alias.keys`,
`Alias.length`, method calls, or passing the mapping around. A requested
name that isn't a matched path also counts as such a use.

hk's `Builtins.pkl` glob-imports 156 builtins, and hk's own config reads
11 of them.

This also matches Pkl, which evaluates glob-imported modules lazily.
With `pkl eval` 0.32.1, a matched module that throws doesn't break code
that never reads it. `main` evaluates it anyway and fails; this PR
returns the same result as Pkl.

## Measurements

hk's `hk.pkl`, release build:

| | ms per evaluation |
|---|---|
| `main` | 401 |
| #225 | 196 |
| #227 | 185 |
| #228 | 180 |
| **#229** | **24** |
| #229 with mimalloc as the allocator (jdx/hk#1635) | 20 |

## Testing

- `cargo test --all-features` (478 feature tests) passes, including two
new tests:
- `import_glob_evaluates_only_referenced_modules`: an unread module that
throws isn't evaluated
- `import_glob_keys_still_see_every_module`: `.length` still counts
every module
- clippy and fmt are clean
- Output is byte-identical to `main` for hk's config, all 161 builtins
and their helpers, and 106 other `.pkl` files (270 files)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes core module evaluation and import narrowing semantics;
incorrect dependency analysis could skip needed modules or change
results, though extensive tests and Pkl parity checks mitigate this.
> 
> **Overview**
> **Glob imports (`import* … as Alias`) no longer evaluate every matched
module up front.** When static analysis shows the mapping is only read
via `Alias["key"]`, `eval_glob_import` takes an optional key set and
loads just those paths; anything else still forces the full glob
(`.length`, `.keys`, field access, method calls, amend/extend bases, or
a module evaluated as an inherited base).
> 
> Import-use analysis in `analysis.rs` records literal index reads
separately from “whole mapping” uses, adds `glob_index_keys`, and
tightens **narrowed ordinary imports** so type-alias/class constraints
and transitive definition deps are included while names bound inside
type checks (`length`, `isEmpty`, `this`) are not mistaken for module
fields.
> 
> `import*("pattern")` expressions still pass `None` and evaluate all
matches. A large batch of integration tests covers lazy glob behavior,
inheritance, and constraint edge cases.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
618482d. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Glob imports now evaluate only the specifically indexed modules when
access is limited to explicit keys, so an unused failing module won’t
prevent access to a requested module.
* When code reads the glob’s keys or length, accesses a matching field,
or uses inheritance or amendments, evaluation continues to include the
full mapping.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Instruction counts

benchmark trend instructions Δ wall (min) Δ
builtins ▁▁▁▁▁▁█ 1,566,286 → 1,950,643 +24.54% ⚠️ 2.40 → 2.93ms +22.13%
check — — — 16.35 → 17.55ms +7.39%
config-cold █████▁ 320,480,742 → 257,952,658 -19.51% 59.23 → 49.00ms -17.27%
stash █████▁ 64,859,813 → 53,518,935 -17.49% 291.05 → 296.51ms +1.88%
usage ▁▂▃▃▃▃█ 4,757,774 → 4,842,879 +1.79% ⚠️ 3.55 → 4.71ms +32.79%
validate — — — 31.18 → 25.56ms -18.00%

2 benchmark(s) above the 1% gate: builtins +24.54%, usage +1.79%

Only instruction counts gate. Wall clock is shown for context — on identical hardware it moves 4-20% run to run.

Measured by tak — instruction-counted CLI benchmarks, stored in this repository's git notes.

e9d3d837e7a1 vs bf1ae647e53e · measured on the runner, not pushed to the history.

jdx added a commit that referenced this pull request Oct 4, 2026
<!-- entire-trail-link-start -->
https://entire.io/gh/jdx/hk/trails/116
<!-- entire-trail-link-end -->

### 🚀 Features

- **(builtins)** keep CRLF files CRLF in trailing_whitespace, newlines,
and mixed_line_ending by [@jdx](https://github.com/jdx) in
[#1621](#1621)
- **(builtins)** report revive findings as diagnostics by
[@jdx](https://github.com/jdx) in
[#1626](#1626)
- **(builtins)** report buf_lint and clang_format findings as
diagnostics by [@jdx](https://github.com/jdx) in
[#1627](#1627)
- **(builtins)** report actionlint findings as diagnostics by
[@jdx](https://github.com/jdx) in
[#1623](#1623)
- **(builtins)** report flake8 findings as diagnostics by
[@jdx](https://github.com/jdx) in
[#1624](#1624)
- **(builtins)** report mypy, mado and six more linters as diagnostics
by [@jdx](https://github.com/jdx) in
[#1630](#1630)
- **(config)** read column-less, prefixed and summarized output with the
gcc diagnostic format by [@jdx](https://github.com/jdx) in
[#1629](#1629)
- **(init)** detect 47 more tools from their config files by
[@jdx](https://github.com/jdx) in
[#1576](#1576)
- **(mcp)** let agents run checks on changed or unstaged files only by
[@jdx](https://github.com/jdx) in
[#1600](#1600)
- **(mcp)** let agents run checks on staged files only by
[@jdx](https://github.com/jdx) in
[#1640](#1640)
- **(test)** assert normalized diagnostics in step tests by
[@jdx](https://github.com/jdx) in
[#1622](#1622)
- **(validate)** warn about misspelled properties, no-op depends,
unmatchable globs and loose min_hk_version by
[@jdx](https://github.com/jdx) in
[#1590](#1590)

### 🐛 Bug Fixes

- **(agent)** make --safe refuse a hook report with unknown or
destructive effect by [@jdx](https://github.com/jdx) in
[#1573](#1573)
- **(agent)** make Claude Code and Codex Stop hooks block with a valid
decision and exit 0 by [@jdx](https://github.com/jdx) in
[#1604](#1604)
- **(builtins)** check large files and case conflicts in binary files by
[@jdx](https://github.com/jdx) in
[#1571](#1571)
- **(check)** fail on unknown --step names instead of passing after
running no steps by [@jdx](https://github.com/jdx) in
[#1603](#1603)
- **(ci)** fail test:bats on a mistyped path or when no tests run by
[@jdx](https://github.com/jdx) in
[#1563](#1563)
- **(cli)** keep generated output exit codes on closed pipes by
[@jdx](https://github.com/jdx) in
[#1540](#1540)
- **(cli)** print failures once, without Rust locations or a bogus fix
hint by [@jdx](https://github.com/jdx) in
[#1588](#1588)
- **(config)** union user skip_steps, skip_hooks and hide_warnings with
the project's, and warn when hk.local.pkl replaces hk.pkl by
[@jdx](https://github.com/jdx) in
[#1596](#1596)
- **(config)** honor top-level jobs, accept documented HK_STASH values,
and fix the hk config crash by [@jdx](https://github.com/jdx) in
[#1594](#1594)
- **(config)** honor subproject skip_steps and warn about ignored
subproject settings by [@jdx](https://github.com/jdx) in
[#1615](#1615)
- **(docs)** stop sidebar links showing through the logo when it bounces
by [@jdx](https://github.com/jdx) in
[#1554](#1554)
- **(git)** skip tracked files with non-UTF-8 names with a warning in
--all, --glob, --from-ref and file arguments by
[@jdx](https://github.com/jdx) in
[#1613](#1613)
- **(init)** explain why a hook is missing and print next steps after hk
init by [@jdx](https://github.com/jdx) in
[#1564](#1564)
- **(install)** correct the --force-local message when a global install
exists by [@jdx](https://github.com/jdx) in
[#1616](#1616)
- **(install)** keep hook commands working after hk upgrades and under a
minimal PATH by [@jdx](https://github.com/jdx) in
[#1597](#1597)
- **(mcp)** make cancel_run stop the real hk run instead of sticking in
cancelling by [@jdx](https://github.com/jdx) in
[#1607](#1607)
- **(mcp)** cap step output in structured results and report pre-run
failures by [@jdx](https://github.com/jdx) in
[#1605](#1605)
- **(mcp)** include untracked and binary files in get_diff and surface
capture errors by [@jdx](https://github.com/jdx) in
[#1601](#1601)
- **(pkl)** load configs that amend the v1 package schema by
[@jdx](https://github.com/jdx) in
[#1560](#1560)
- **(pkl)** hide mirror credentials in failed package download errors by
[@jdx](https://github.com/jdx) in
[#1620](#1620)
- **(pkl)** show file, line and column for Pkl syntax errors, including
in imported files by [@jdx](https://github.com/jdx) in
[#1598](#1598)
- **(stash)** preserve CRLF when restoring unstaged files by
[@jdx](https://github.com/jdx) in
[#1535](#1535)
- **(stash)** restore unstaged text over a staged binary file no step
changed by [@jdx](https://github.com/jdx) in
[#1580](#1580)
- **(stash)** stash tracked files whose names start with a colon by
[@jdx](https://github.com/jdx) in
[#1614](#1614)
- **(stash)** keep a staged edit when its worktree copy was reverted to
HEAD by [@jdx](https://github.com/jdx) in
[#1602](#1602)
- **(stash)** keep a merge or cherry-pick in progress when stashing the
worktree by [@jdx](https://github.com/jdx) in
[#1609](#1609)
- **(stash)** restore hk's own stash entry by commit id so concurrent
stashes are never touched by [@jdx](https://github.com/jdx) in
[#1637](#1637)
- **(stash)** serialize stash and restore across hk processes and linked
worktrees by [@jdx](https://github.com/jdx) in
[#1636](#1636)
- **(stash)** restore stashed changes when hk is terminated and recover
them after a crash by [@jdx](https://github.com/jdx) in
[#1641](#1641)
- **(step)** isolate formatter patches from concurrent commands and
staging by [@nettlesh](https://github.com/nettlesh) in
[#1392](#1392)
- **(step)** keep interactive steps in hk's process group by
[@jdx](https://github.com/jdx) in
[#1557](#1557)
- **(step)** say "command not found" when an argv step's tool is not
installed by [@jdx](https://github.com/jdx) in
[#1579](#1579)
- **(step)** add exec_ok for condition shell tests and stop exec
panicking by [@jdx](https://github.com/jdx) in
[#1610](#1610)
- **(step)** run steps that depend on a step with no files instead of
hanging by [@jdx](https://github.com/jdx) in
[#1584](#1584)
- **(step)** select files in directories whose names contain brackets or
braces by [@jdx](https://github.com/jdx) in
[#1592](#1592)
- **(step)** keep percent signs in file names literal under cmd.exe by
[@jdx](https://github.com/jdx) in
[#1568](#1568)
- **(step)** end tools left running by a fail-fast cancel on Windows by
[@jdx](https://github.com/jdx) in
[#1625](#1625)
- **(step)** exclude a directory's files when a step or group exclude
names it by [@jdx](https://github.com/jdx) in
[#1606](#1606)
- **(step)** report diagnostic paths relative to the repository root for
steps that run in a subdirectory by [@jdx](https://github.com/jdx) in
[#1638](#1638)
- **(step)** run a custom shell directly on Windows and accept a quoted
shell path by [@jdx](https://github.com/jdx) in
[#1628](#1628)
- **(step)** batch Windows cmd shims below the cmd.exe line limit by
[@jdx](https://github.com/jdx) in
[#1618](#1618)
- **(step)** type scripts whose env shebang has -S, options or variables
by [@jdx](https://github.com/jdx) in
[#1611](#1611)
- **(step)** keep diagnostics from every started job when another job
fails by [@jdx](https://github.com/jdx) in
[#1642](#1642)
- **(step)** report steps stopped by Ctrl-C as cancelled instead of
failed by [@jdx](https://github.com/jdx) in
[#1643](#1643)
- **(util)** check files whose 8 KiB probe splits a multibyte char and
keys in non-UTF-8 files by [@jdx](https://github.com/jdx) in
[#1572](#1572)
- **(util)** accept git-generated merge and revert titles in
check-conventional-commit by [@jdx](https://github.com/jdx) in
[#1566](#1566)
- **(util)** check protected branch, exec bits and case conflicts
against git's own state by [@jdx](https://github.com/jdx) in
[#1577](#1577)
- **(util)** keep non-UTF-8 files and symlinks intact in
fix-smart-quotes by [@jdx](https://github.com/jdx) in
[#1570](#1570)
- **(validate)** reject dependency cycles, self-dependencies and invalid
step globs at load time by [@jdx](https://github.com/jdx) in
[#1567](#1567)

### 📚 Documentation

- **(builtins)** show file selectors, script commands and options in the
catalogue by [@jdx](https://github.com/jdx) in
[#1562](#1562)
- **(config)** explain where diagnostics come from and when a step needs
diagnostic_format by [@jdx](https://github.com/jdx) in
[#1619](#1619)
- **(config)** document sharing one configuration across repositories by
[@jdx](https://github.com/jdx) in
[#1591](#1591)
- **(settings)** describe pkl rewrite and CA variables for the built-in
evaluator by [@jdx](https://github.com/jdx) in
[#1617](#1617)
- refresh competitor benchmark for v2.4.0 by
[@jdx](https://github.com/jdx) in
[#1536](#1536)
- replace the sea shanty with Bound for the Main and its music video by
[@jdx](https://github.com/jdx) in
[#1541](#1541)
- take the new shanty video down if its poster cannot be published by
[@jdx](https://github.com/jdx) in
[#1543](#1543)
- add a sea shanty mode to the landing page by
[@jdx](https://github.com/jdx) in
[#1544](#1544)
- keep a link to the sea shanty when scripting is off by
[@jdx](https://github.com/jdx) in
[#1545](#1545)
- generate the pirate CLI reference from the English one by
[@jdx](https://github.com/jdx) in
[#1550](#1550)
- restrict AI replies on Discussions and Issues and note the instant ban
by [@jdx](https://github.com/jdx) in
[#1559](#1559)
- start getting started with a first configuration that needs no linters
by [@jdx](https://github.com/jdx) in
[#1561](#1561)
- correct stash, type-checker lock, and patch-apply descriptions by
[@jdx](https://github.com/jdx) in
[#1578](#1578)
- add lefthook and husky with lint-staged migration guides by
[@jdx](https://github.com/jdx) in
[#1589](#1589)

### ⚡ Performance

- **(config)** evaluate only the builtins a config uses, cutting cold
load from ~1.4 s to ~0.07 s by [@jdx](https://github.com/jdx) in
[#1581](#1581)
- **(git)** skip the untracked scan for runs that name their files, e.g.
hk check FILE by [@jdx](https://github.com/jdx) in
[#1587](#1587)
- **(stash)** restore unstaged files no step changed with one git
process by [@jdx](https://github.com/jdx) in
[#1612](#1612)
- **(stash)** stop rescanning the worktree before stashing, saving ~80
ms on large repos by [@jdx](https://github.com/jdx) in
[#1595](#1595)
- **(step)** resolve workspace_indicator once per directory, saving ~120
ms per step in large monorepos by [@jdx](https://github.com/jdx) in
[#1599](#1599)
- **(step)** run read-only check-only steps side by side in fix hooks by
[@jdx](https://github.com/jdx) in
[#1586](#1586)
- use mimalloc as the global allocator by [@jdx](https://github.com/jdx)
in [#1635](#1635)
- bump pklr to 4.0.0 (hk validate 14x faster) by
[@jdx](https://github.com/jdx) in
[#1644](#1644)

### 🧪 Testing

- **(windows)** run every e2e-win case and cover fix, staging and
installed hooks by [@jdx](https://github.com/jdx) in
[#1574](#1574)
- fix bats teardown and event-order flakes and surface CI retries by
[@jdx](https://github.com/jdx) in
[#1583](#1583)

### 🛡️ Security

- **(deps)** update dependency esbuild to ^0.28.0 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1548](#1548)
- **(step)** refuse check_diff patches that write inside .git by
[@jdx](https://github.com/jdx) in
[#1585](#1585)
- point the landing page at the sea shanty by
[@jdx](https://github.com/jdx) in
[#1542](#1542)
- turn sea shanty mode into a pirate edition of the whole docs site by
[@jdx](https://github.com/jdx) in
[#1549](#1549)
- document what hk executes, global hook reach, and --safe limits in a
security model page by [@jdx](https://github.com/jdx) in
[#1575](#1575)
- bring the sea shanty contributing page up to date with the English
page by [@jdx](https://github.com/jdx) in
[#1631](#1631)

### 🔍 Other Changes

- **(benchmark)** gate hook stashing and cold config loads in the perf
check by [@jdx](https://github.com/jdx) in
[#1608](#1608)
- **(entire)** store checkpoints in a private repository by
[@jdx](https://github.com/jdx) in
[74bd981](74bd981)
- **(entire)** commit codex session hooks by
[@jdx](https://github.com/jdx) in
[71966d2](71966d2)
- **(entire)** commit claude session hooks by
[@jdx](https://github.com/jdx) in
[2298ebf](2298ebf)
- **(entire)** store checkpoints in a private repository by
[@jdx](https://github.com/jdx) in
[4a4e806](4a4e806)
- **(entire)** restore lower-cost trail findings by
[@jdx](https://github.com/jdx) in
[6eed674](6eed674)
- **(install)** refuse legacy hook installs that overwrite foreign hooks
or symlinks by [@jdx](https://github.com/jdx) in
[#1593](#1593)
- **(release)** smoke-run every release archive before the release is
created by [@jdx](https://github.com/jdx) in
[#1565](#1565)
- **(security)** check RustSec advisories in CI and document gh release
verify by [@jdx](https://github.com/jdx) in
[#1569](#1569)
- unblock the docs deploy and stop re-rendering unchanged videos by
[@jdx](https://github.com/jdx) in
[#1551](#1551)
- limit each contributor to one open draft PR by
[@jdx](https://github.com/jdx) in
[#1555](#1555)
- lint test code by running clippy with --all-targets by
[@jdx](https://github.com/jdx) in
[#1582](#1582)
- combine hosted Bats configurations by [@jdx](https://github.com/jdx)
in [#1633](#1633)
- skip full checks for docs-only pull requests by
[@jdx](https://github.com/jdx) in
[#1634](#1634)
- remove redundant package.homepage from Cargo.toml by
[@jdx](https://github.com/jdx) in
[#1639](#1639)

### 📦️ Dependency Updates

- lock file maintenance by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1537](#1537)
- update jdx crates by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1539](#1539)
- update github actions by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1546](#1546)
- update dependency aube to latest by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1547](#1547)
- update dependency communique to latest by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1553](#1553)
- update rust crate clx to v3.0.3 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1552](#1552)
- update dependency aube to latest by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#1556](#1556)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Mechanical version and documentation URL updates plus changelog; no
runtime code changes in the diff.
> 
> **Overview**
> **Release cut** that bumps the crate and CLI from **2.4.0** to
**2.5.0** (`Cargo.toml`, `Cargo.lock`, `hk.usage.kdl`, generated CLI
metadata) and adds the **[2.5.0] CHANGELOG** section dated 2026-10-04,
cataloguing everything shipped since v2.4.0.
> 
> Doc and sample configs are updated so `amends` / `import` examples
point at `package://…/v2.5.0/hk@2.5.0` (README, getting started,
migration guides, pirate docs, public `.pkl` examples, `hk-example.pkl`,
and a commented line in `hk.pkl`). No application logic changes appear
in this diff—only versioning and release notes alignment.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8d358e2. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: mise-en-dev <123107610+mise-en-dev@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant