https://devenv.sh/blog/2025/11/26/devenv-111-module-changelo...
Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
111–120 of 133 posts
Re: Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
#112Just to make clear it's been written -- sorry, ENGINEERED -- in Rust.
Re: Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
#113I am a big fan of prek and have converted a couple of projects over from pre-commit The main advantage for me is that prek has support for monorepo/workspaces, while staying compatible with existing pre-commit hooks. So you can have additional .pre-commit-config.yaml files in each workspace under the root, and prek will find and run them all when you commit. The results are collated nicely. Just works. Having the def…
Re: Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
#114BTW. Pre-commit hooks are the wrong way to go about this stuff. I'm advocating for JJ to build a proper daemon that runs "checks" per change in the background. So you don't run pre-commit checks when committing. They just happen in the background, and when by the time you get to sharing your changes, you get all the things verified for you for each change/commit, effortlessly without you wasting time or needing to do…
Yep, I think a watcher is better suited [0] to trigger on file changes. I personally can't stand my git commit command to be slow or to fail. [0]: such as https://github.com/watchexec/watchexec
But that's the whole point of locally checking the code, no? Would you prefer to commit broken things, fix them and then rebase and squash each time?
Re: Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
#115BTW. Pre-commit hooks are the wrong way to go about this stuff. I'm advocating for JJ to build a proper daemon that runs "checks" per change in the background. So you don't run pre-commit checks when committing. They just happen in the background, and when by the time you get to sharing your changes, you get all the things verified for you for each change/commit, effortlessly without you wasting time or needing to do…
From the docs I think Limmat is much more minimal. It doesn't have a merge queue or anything, "jobs" are just commands that run in a worktree.
I would be interested to try SelfCI coz I have actually gone back and forth on whether I want that merge queue feature in Limmat. Sometimes I think for that feature I no longer want it to be a local tool but actually I just want a "proper CI system" that isn't a huge headache to configure.
Re: Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
#116I think it was a massive mistake to build on the pre-commit plugin base. pre-commit is probably the most popular tool for pre-commit hooks but the platform is bad. My main critique is that it mixes tool installation with linting—when you will undoubtedly want to use linters _outside_ of hooks. The interface isn't built with parallelism in mind, it's sort of bolted on but not really something I think could work well i…
If you use a tool like this via Devenv instead of using its built-in mechanisms for installing tools:
- you can add a linter without putting it on your path
- you can put a linter on your path without enabling any git hooks for it
- if you are already using a linter in a git hook, adding it to your environment will get you the exact same version as you're already using for your git hook at no additional storage cost
- if you are already using a linter at the CLI, and you add a git hook for it, your hook will run with the exact same version that you are already using at the CLI at no additional storage cost
- your configuration interface is isomorphic to the upstream one, so
- any custom hooks you're already using can be added without modification beyond converting from one format to another;
- any online documentation you find about adding a custom hook not distributed with the upstream framework still applies;
- and you can configure new, custom, or modified hooks with a familiar interface.
- any hook you write as a script or with substantial logic can also be plugged into a built-in task runner for use outside git hook contexts, where
- you can express dependency relationships between tasks, so
- every task runs concurrently unless dependency relations mandate otherwise.
Which imo solves that problem pretty well. My team uses that kind of setup in all of our projects.> The interface isn't built with parallelism in mind, it's sort of bolted on but not really something I think could work well in practice.
I'm curious about what this means. Could you expand on it?
You might be interested in something like `treefmt`, which is designed around a standard interface for configuring formatters to run in parallel, but doesn't do any package management or installation at all:
https://github.com/numtide/treefmt
(That might address both of the issues I've replied to you about so far, to some extent.)
> It also uses a bunch of rando open source repos which is a supply chain nightmare even with pinning.
If the linters you're running are open source, isn't this what you're ultimately doing anyway? Nix gives a bit more control here, but I'm not sure whether it directly addresses your concern.
> I am working on a competing tool
Oh, dammit. Only after writing all of this out did I realize you're the author of mise. I'm sure you're well aware of Nix and Devenv. :)
Because I think your critiques make sense and might be shared by others, I'll post this comment anyway. I'm still interested in your replies, and your opinion of having some environment management tool plug into prek and supplant its software installation mechanisms.
And because I think mise likely gets many of these things right in the same way Devenv does, and reasonable people could prefer either, I'll include links to both Devenv and mise below:
Re: Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
#117I struggle to see value with git hooks. They're an opt-in, easily opt-out way of calling shell scripts from my understanding--you can't force folks to run them, and they don't integrate/display nicely with CI/CD. Why not just call a shell script directly? How would you use these with a CI/CD platform?
> you can't force folks to run them
I think it's useful to be able to disable things like this when debugging or reconfiguring them. I sometimes disable the ones I've set up for myself, then reenable them later.
> Why not just call a shell script directly?
Because it's manual; I have to remember to do it each time. But there's no reason not to have a script you can invoke in other ways, if that's something you want.
> How would you use these with a CI/CD platform?
The thing that sets up your environment also installs the git hooks configuration, and/or you can have it invoke specific hooks via CLI.
Re: Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
#118Earlier quoted context omitted.
I wouldn't want hooks modifying the code. They should be only approve/reject. Ideally landlock rules would give them only ro access to repo dir
It depends. I wrote a pre-commit hook (in shell, not precommit the tool) at a previous job that ran terraform fmt on any staged files (and add the changes to the commit) because I was really tired of having people push commits that would then fail for trivial things. It was overrideable with an env var. IMO if there’s a formatting issue, and the tool knows how it should look, it should fix it for you.
But if you don't want to have hooks modify code, in a case like this you can also just use `tofu validate`. Our setup does `tflint` and `tofu validate` for this purpose, neither of which modifies the code.
This is also, of course, a reasonable place to have people use `tofu plan`. It you want bad code to fail as quickly as possible, you can do:
tflint -> tfsec -> tofu validate -> tofu plan
That'll catch everything Terraform will let you catch before deploy time— most of it very quickly— without modifying any code.
Re: Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
#119I struggle to see value with git hooks. They're an opt-in, easily opt-out way of calling shell scripts from my understanding--you can't force folks to run them, and they don't integrate/display nicely with CI/CD. Why not just call a shell script directly? How would you use these with a CI/CD platform?
This might be a me problem but I extensively manipulate the git history all the time which makes me loathe git hooks. A commit should take milliseconds, not a minute.
- very fast? run it all the time (shell prompt drawing, if you want, like direnv)
- fast? run it in a pre-commit hook
- a bit slow? run it in a pre-push book
- really slow? run it in CI, during code review, etc.
Fwiw: I also rewrite history often-ish but it's never that fast for me because I have commit signing turned on and that requires verifying my presence to a USB smartcard on each commit. For me, it's okay if a commit takes a second or two. As it creeps up beyond 3 or 4 seconds, I become increasingly annoyed. If a commit took a minute I would consider that broken, and if I were expected to tolerate that or it were forced on me, I'd be furious.I generally expect an individual pre-commit hook to under ~200ms (hopefully less), which seems reasonable to me. Some of the ones we have are kinda slow (more than 1s) and maybe should be moved to pre-push.
Since you seem especially sensitive to that latency, here's what I'd propose if we worked together:
If you own a repo, let's make all the hooks pre-push instead of pre-commit. On my repos, I like many hooks to run pre-commit. But since the hooks we use are managed by a system that honors local overrides via devenv.local.nix, let's make sure that's in .gitignore everywhere. When I'm iterating in your codebases and I want more automated feedback, I'll move more hooks to pre-commit, and when you're working in mine you can move all my hooks to pre-push (or just disable them while tidying up a branch).
Re: Prek: A better, faster, drop-in pre-commit replacement, engineered in Rust
#120I think it was a massive mistake to build on the pre-commit plugin base. pre-commit is probably the most popular tool for pre-commit hooks but the platform is bad. My main critique is that it mixes tool installation with linting—when you will undoubtedly want to use linters _outside_ of hooks. The interface isn't built with parallelism in mind, it's sort of bolted on but not really something I think could work well i…
> My main critique is that it mixes tool installation with linting If you use a tool like this via Devenv instead of using its built-in mechanisms for installing tools: - you can add a linter without putting it on your path - you can put a linter on your path without enabling any git hooks for it - if you are already using a linter in a git hook, adding it to your environment will get you the exact same version as yo…
If you look at hk you will understand what I'm talking about in regards to parallelism. hk uses read/write locks and other techniques like processing --diff output to safely run multiple fixers in parallel without them stomping on each other. treefmt doesn't support this either, it won't let you run multiple fixers on the same file at the same time like hk will.
> If the linters you're running are open source, isn't this what you're ultimately doing anyway?
You have to trust the linters. You don't also need to trust the plugin authors. In hk we don't really use "plugins" but the equivalent is first-party so you're not extending trust to extra parties beyond me and the lint vendors.