← back to Cli Printing Press
chore(cli): add lefthook pre-push lint and deny --no-verify bypass (#39)
99d2dde8137a5983988379c546c7db1e506f751b · 2026-03-28 23:08:20 -0700 · Trevin Chow
* chore(cli): add lefthook pre-push lint and deny --no-verify bypass
Adds lefthook.yml with a pre-push hook that runs golangci-lint on
changed files, catching lint errors before they reach CI. Updates
AGENTS.md with the lint command, README with setup instructions,
and .claude/settings.json to deny --no-verify bypass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(cli): add PATH troubleshooting note to lefthook install instructions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Files touched
M .claude/settings.jsonM AGENTS.mdM README.mdA lefthook.yml
Diff
commit 99d2dde8137a5983988379c546c7db1e506f751b
Author: Trevin Chow <trevin@trevinchow.com>
Date: Sat Mar 28 23:08:20 2026 -0700
chore(cli): add lefthook pre-push lint and deny --no-verify bypass (#39)
* chore(cli): add lefthook pre-push lint and deny --no-verify bypass
Adds lefthook.yml with a pre-push hook that runs golangci-lint on
changed files, catching lint errors before they reach CI. Updates
AGENTS.md with the lint command, README with setup instructions,
and .claude/settings.json to deny --no-verify bypass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(cli): add PATH troubleshooting note to lefthook install instructions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---
.claude/settings.json | 6 ++++++
AGENTS.md | 5 ++++-
README.md | 23 +++++++++++++++++++++++
lefthook.yml | 6 ++++++
4 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/.claude/settings.json b/.claude/settings.json
index 4dc3775a..51a1f5f4 100644
--- a/.claude/settings.json
+++ b/.claude/settings.json
@@ -2,6 +2,12 @@
"enabledPlugins": {
"compound-engineering@every-marketplace": true
},
+ "permissions": {
+ "deny": [
+ "Bash(git commit --no-verify:*)",
+ "Bash(git push --no-verify:*)"
+ ]
+ },
"hooks": {
"PostToolUse": [
{
diff --git a/AGENTS.md b/AGENTS.md
index 2bf49f13..43c71a26 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,12 +1,15 @@
# CLI Printing Press - Development Conventions
-## Build & Test
+## Build, Test & Lint
```bash
go build -o ./printing-press ./cmd/printing-press
go test ./...
+golangci-lint run --new-from-rev=origin/main ./...
```
+A pre-push hook runs `golangci-lint` automatically on `git push`. The same config (`.golangci.yml`: errcheck, govet, staticcheck, unused) runs in CI. To run lint manually: `golangci-lint run --new-from-rev=origin/main ./...`
+
**IMPORTANT: Always use relative paths for build output.** Never build to `/tmp` or any shared absolute path. Multiple worktrees run concurrently and will stomp on each other. Use `./printing-press` exactly as shown above.
## Project Structure
diff --git a/README.md b/README.md
index 051ab97c..abd308b9 100644
--- a/README.md
+++ b/README.md
@@ -351,6 +351,29 @@ Synthesized from post-mortems on Notion and Linear runs. 14 changes to the skill
**Emboss:** Now opt-in only. Offered at end of run, never triggered automatically.
+## Development
+
+After cloning, install git hooks so lint errors are caught before they reach CI:
+
+```bash
+go install github.com/evilmartians/lefthook@latest
+~/go/bin/lefthook install
+```
+
+> **Note:** If `lefthook` isn't found after `go install`, your `$GOPATH/bin` (`~/go/bin` by default) may not be in your `PATH`. Either use the full path as shown above, or add `export PATH="$HOME/go/bin:$PATH"` to your `~/.zshrc`.
+
+This adds a pre-push hook that runs `golangci-lint` on changed files. The same linter config (`.golangci.yml`) runs in CI — lefthook just catches failures locally first.
+
+If you also want `golangci-lint` locally:
+
+```bash
+# macOS
+brew install golangci-lint
+
+# or via go
+go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
+```
+
## Credits
- **Peter Steinberger** ([@steipete](https://github.com/steipete)) - [discrawl](https://github.com/steipete/discrawl) and [gogcli](https://github.com/steipete/gogcli) set the bar. The quality scoring system is inspired by his work. discrawl v0.2.0's sync architecture directly influenced the printing press templates.
diff --git a/lefthook.yml b/lefthook.yml
new file mode 100644
index 00000000..1c98da7a
--- /dev/null
+++ b/lefthook.yml
@@ -0,0 +1,6 @@
+pre-push:
+ commands:
+ lint:
+ glob: "*.go"
+ run: golangci-lint run --new-from-rev=origin/main ./...
+ fail_text: "golangci-lint failed. Fix lint errors before pushing."
← cc098e67 feat(cli): accept name or path in emboss command (#38)
·
back to Cli Printing Press
·
ci: re-trigger release-please after enabling PR creation per 7d9f8c7c →