Is prek much better?
The prek documentation has a list of many large projects (such as CPython and FastAPI, to name a few) who use it; each link is a PR of how they integrated it into CI if you want to see more: https://prek.j178.dev/#who-is-using-prek
I'm sure this is more reliably than pre-commit, but you still have hooks building Python wheels and whatnot, which fails annoyingly often.
The VFS stuff is not quite finished yet though (it's really complicated). If anyone wants to help me with that it would be welcome!
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 anything special.
I have something a bit like that implemented in SelfCI (a minimalistic local-first Unix-philosophy-abiding CI) https://app.radicle.xyz/nodes/radicle.dpc.pw/rad%3Az2tDzYbAX... and it replaced my use of pre-commit hooks entirely. And users already told me that it does feel like commit hooks done right.
I personally can't stand my git commit command to be slow or to fail.
[0]: such as https://github.com/watchexec/watchexec
I haven't yet submitted it to upstream for design discussion, but I pushed up my branch[1]. You can also declare a revset that the target revision must match, for extra belts and suspenders (eg., '~conflicts()')
[1] https://github.com/paulsmith/jj/tree/protected-bookmarks
It's a little surprising that git doesn't pass pre-commit hooks any information, like a list of which files were changed in the soon-to-be-made commit. git does so for pre-push, where it writes to a hook's stdin some information about the refs and remotes involved in the push.
I wonder if many pre-commit hooks, like the kind which run formatters, would be better off as `clean` filters, which run on files when they are staged. The filter mechanism makes it easier to apply just to the files which were changed. In the git docs, they even use a formatter (`indent`) as an example.
https://git-scm.com/book/ms/v2/Customizing-Git-Git-Attribute...
This is a long standing sore point in pre-commit, see https://github.com/pre-commit/pre-commit/issues/860 and also linked duplicates (some of which are not duplicates).
https://devenv.sh/blog/2025/11/26/devenv-111-module-changelo...
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.
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:
We were coming from a an application perspective where blocking the users intent is a no-go.
Do you have a link to a discussion where the JJ community is discussing checks?