diff --git a/howto/puppet.md b/howto/puppet.md
index 21eb0cb447a59a26d7efd3b162f54c3a77a68069..4681f35aeb37a6f9cbf2308952939ab3848c6eb4 100644
--- a/howto/puppet.md
+++ b/howto/puppet.md
@@ -285,6 +285,21 @@ Finally, to run the tests, you need to wrap your invocation with
 
     bundle exec rake test
 
+## Validating Puppet code
+
+You SHOULD run validation checks on commit locally before pushing your
+manifests. To install those hooks, you should clone this repository:
+
+    git clone https://github.com/anarcat/puppet-git-hooks
+
+... and deploy it as a pre-commit hook:
+
+    ln -s $PWD/puppet-git-hooks tor-puppet/.git/hooks/pre-commit
+
+A server-side validation hook hasn't been enabled yet because our
+manifests would sometimes fail and the hook was found to be somewhat
+slow. That is being worked on in [issue 31226][].
+
 ## Listing all hosts under puppet
 
 This will list all active hosts known to the Puppet master:
@@ -1475,6 +1490,11 @@ The GitLab CI would be indicative: an operator would need to push to a
 topic branch there first to confirm tests pass but would still push
 directly to the Puppet server for production.
 
+Note that we are working on (client-side) validation hooks for now,
+see [issue 31226][].
+
+[issue 31226]: https://gitlab.torproject.org/tpo/tpa/team/-/issues/31226
+
 ### OpenPGP verification and web hook
 
 To stop pushing directly to the Puppet server, we could implement
@@ -1661,8 +1681,8 @@ the last one supporting "passenger" (the puppetmaster deployment
 method currently available in Debian, deprecated and dropped from
 puppet 6). They [patched it](https://redmine.koumbit.net/projects/theforeman-puppet/repository/revisions/5b1b0b42f2d7d7b01eacde6584d3) to support `puppetlabs/apache < 6`.
 They push to a bare repo on the puppet master, then they have
-validation hooks (the inspiration for our #31226), and a hook deploys
-the code to the right branch.
+validation hooks (the inspiration for our own hook implementation, see
+[issue 31226][]), and a hook deploys the code to the right branch.
 
 They were using r10k but stopped because they had issues when r10k
 would fail to deploy code atomically, leaving the puppetmaster (and