What happened?
Two related issues hit on a fresh fallow init --hooks against a Husky-using repo:
$ fallow init --hooks
Error: .husky/pre-commit already exists. Add the following line to your existing hook:
fallow dead-code --changed-since <base> --fail-on-issues --quiet
1. Why only dead-code and not fallow audit?
crates/cli/src/init.rs hard-codes a single command in both the generated script and the "already exists" error message:
fallow dead-code --changed-since {base_ref} --fail-on-issues --quiet
But fallow audit already exists, takes --changed-since + --fail-on-issues, and bundles all three analyses (dead-code + dupes + health) into one verdict. Is audit deliberately excluded from pre-commit (too slow / too noisy on partial diffs?) or is this a doc/CLI gap? Either way, docs.fallow.tools/cli/init doesn't say.
2. The base ref is baked in at install time
The auto-detected (or --branch-supplied) ref is format!'d literally into the shell script:
fallow dead-code --changed-since main --fail-on-issues --quiet
That works for a feature → main topology. It breaks on any repo with multiple long-lived integration branches (next-release / hotfix / LTS), because the right base depends on which integration branch the feature targets — not on the global default sampled at hook-install time. Concrete failure modes:
- Hotfix branched off a non-default integration branch → hook diffs against the wrong base, producing false positives (code "missing" on default) or false negatives.
- No way to say "diff against the merge-base with my upstream" (
git merge-base @{upstream} HEAD), which is the topology-agnostic answer.
Combined ask
-
Document why dead-code (not audit) is the recommended pre-commit gate, or add --hooks-command audit.
-
Have the generated hook resolve the base ref at commit time rather than baking it in, e.g.:
UPSTREAM="$(git rev-parse --abbrev-ref --symbolic-full-name @{upstream} 2>/dev/null || true)"
BASE="${UPSTREAM#*/}"
fallow dead-code --changed-since "${BASE:-main}" --fail-on-issues --quiet
Reproduction
mkdir -p /tmp/fallow-init-hooks-repro && cd /tmp/fallow-init-hooks-repro
git init -q && git -c user.email=a@b -c user.name=a commit --allow-empty -qm init
mkdir -p .husky && echo '#!/bin/sh' > .husky/pre-commit && chmod +x .husky/pre-commit
# 1. Hook installer only suggests dead-code, never audit:
fallow init --hooks
# => Error: .husky/pre-commit already exists. Add the following line ...
# fallow dead-code --changed-since main --fail-on-issues --quiet
# 2. --branch is baked in literally; switching feature branches later doesn't change it:
rm .husky/pre-commit
fallow init --hooks --branch develop
grep fallow .husky/pre-commit
# => fallow dead-code --changed-since develop --fail-on-issues --quiet
Expected behavior
Either documented or implemented:
- Doc explains the
dead-code-vs-audit choice and the recommended setup for repos with multiple integration branches; or
fallow init --hooks resolves the base ref at hook execution time (e.g. via @{upstream}); or
fallow init --hooks --hooks-command audit opt-in to scaffold fallow audit instead of fallow dead-code.
Fallow version
2.56.0
Operating system
macOS
Configuration
No `.fallowrc.json` / `fallow.toml` is required to reproduce — the issue is in the hook scaffolder itself, not in analysis configuration.
What happened?
Two related issues hit on a fresh
fallow init --hooksagainst a Husky-using repo:1. Why only
dead-codeand notfallow audit?crates/cli/src/init.rshard-codes a single command in both the generated script and the "already exists" error message:But
fallow auditalready exists, takes--changed-since+--fail-on-issues, and bundles all three analyses (dead-code + dupes + health) into one verdict. Isauditdeliberately excluded from pre-commit (too slow / too noisy on partial diffs?) or is this a doc/CLI gap? Either way,docs.fallow.tools/cli/initdoesn't say.2. The base ref is baked in at install time
The auto-detected (or
--branch-supplied) ref isformat!'d literally into the shell script:That works for a
feature → maintopology. It breaks on any repo with multiple long-lived integration branches (next-release / hotfix / LTS), because the right base depends on which integration branch the feature targets — not on the global default sampled at hook-install time. Concrete failure modes:git merge-base @{upstream} HEAD), which is the topology-agnostic answer.Combined ask
Document why
dead-code(notaudit) is the recommended pre-commit gate, or add--hooks-command audit.Have the generated hook resolve the base ref at commit time rather than baking it in, e.g.:
Reproduction
Expected behavior
Either documented or implemented:
dead-code-vs-auditchoice and the recommended setup for repos with multiple integration branches; orfallow init --hooksresolves the base ref at hook execution time (e.g. via@{upstream}); orfallow init --hooks --hooks-command auditopt-in to scaffoldfallow auditinstead offallow dead-code.Fallow version
2.56.0
Operating system
macOS
Configuration
No `.fallowrc.json` / `fallow.toml` is required to reproduce — the issue is in the hook scaffolder itself, not in analysis configuration.