From tani-shi-skills
Set up a git pre-commit hook that auto-updates version strings using date-based versioning (yyyy.mm.dd). Use when the user wants automatic version bumping on commit, date-based versioning, or a pre-commit hook for version management. Trigger on: "version hook", "auto version", "version bump", "pre-commit version", "date-based version", "auto-update version", "set up version hook", or any request to automatically update version strings on git commit.
How this skill is triggered — by the user, by Claude, or both
Slash command
/tani-shi-skills:version-hookThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate and install a git pre-commit hook that automatically updates version strings using date-based versioning.
Generate and install a git pre-commit hook that automatically updates version strings using date-based versioning.
yyyy.mm.dd (e.g., 2026.03.13)yyyy.mm.dd.N where N starts at 1 (e.g., 2026.03.13.1, 2026.03.13.2).1Examine the project root to determine:
version field that should be auto-updatedFind all files containing version strings. Use the pattern reference below to determine which files and fields to target.
Important distinctions — what to update, regenerate, or skip:
| Update (sed) | Regenerate (package manager) | Skip |
|---|---|---|
| The project's own version field | uv.lock (if exists & uv available) | package-lock.json, yarn.lock, pnpm-lock.yaml (npm/yarn/pnpm auto-update) |
| Root-level or package-level version | poetry.lock (if exists & poetry available) | Dependency version constraints |
| Manifest version fields | Cargo.lock (if exists & cargo available) | Version fields inside [dependencies], [dev-dependencies], etc. |
parent version in pom.xml | ||
| Generated or vendored files |
Before generating the hook, present:
Wait for user confirmation before proceeding.
Generate the pre-commit hook script and install it. Follow the hook generation rules below.
After installing the hook, run these verification substeps. Do NOT skip this step.
Run shellcheck <hook-file> to detect syntax errors and semantic issues. If shellcheck is not available, fall back to sh -n <hook-file> for basic syntax validation. Fix any errors before proceeding.
Source the hook file to extract __vh_compute_version, then verify with three test cases:
# Test 1: Past date → today's date
result=$(__vh_compute_version "2020.01.01")
expected=$(date +"%Y.%m.%d")
[ "$result" = "$expected" ] && echo "PASS" || echo "FAIL: got $result, expected $expected"
# Test 2: Today's date → today.1
result=$(__vh_compute_version "$(date +%Y.%m.%d)")
expected="$(date +%Y.%m.%d).1"
[ "$result" = "$expected" ] && echo "PASS" || echo "FAIL: got $result, expected $expected"
# Test 3: today.3 → today.4
result=$(__vh_compute_version "$(date +%Y.%m.%d).3")
expected="$(date +%Y.%m.%d).4"
[ "$result" = "$expected" ] && echo "PASS" || echo "FAIL: got $result, expected $expected"
All three must pass. If any fails, fix the __vh_compute_version function and re-test.
For each target version file, run the sed command in dry-run mode (output to stdout, do not modify the file) and verify the version string is actually replaced. For example:
# For a file using: s/"version": *"[^"]*"/"version": "TEST"/
sed 's/"version": *"[^"]*"/"version": "TEST"/' package.json | grep '"version"'
# Confirm the output shows "version": "TEST"
If the pattern does not produce a replacement, fix the sed pattern in the hook before proceeding.
Perform a real commit to verify the hook works end-to-end:
git reset HEAD~1The generated hook MUST follow this structure:
#!/bin/sh
# --- version-hook: start ---
(
__vh_compute_version() {
CURRENT="$1"
TODAY=$(date +"%Y.%m.%d")
if echo "$CURRENT" | grep -q "^${TODAY}\.[0-9][0-9]*$"; then
N=$(echo "$CURRENT" | sed "s/^${TODAY}\.\([0-9][0-9]*\)$/\1/")
echo "${TODAY}.$((N + 1))"
elif [ "$CURRENT" = "$TODAY" ]; then
echo "${TODAY}.1"
else
echo "$TODAY"
fi
}
# ... per-file update logic here ...
# ... lock file regeneration here (see Lock File Regeneration section) ...
) || true
# --- version-hook: end ---
|| true: The hook must never block a commit. All logic goes inside ( ... ) || true.# --- version-hook: start --- and # --- version-hook: end --- to delimit the hook's section. This allows coexistence with other hook content.__vh_compute_version once and reuse it for all files.sed -i: macOS sed requires sed -i '' while GNU sed uses sed -i. Use this wrapper:
__vh_sed_i() {
if sed --version 2>/dev/null | grep -q GNU; then
sed -i "$@"
else
sed -i '' "$@"
fi
}
git add <file> to include the change in the commit. This includes lock files that are regenerated by package managers.git diff --cached --name-only to determine what is staged..husky/pre-commitlefthook.yml under pre-commit.commandslocal hook in .pre-commit-config.yaml.git/hooks/pre-commit if no framework is detectedchmod +x on the hook file after writing.command -v <tool> >/dev/null 2>&1. Append || : so failures do not block the commit. Stage the regenerated lock file with git add. See the ecosystem reference files for specific commands.__vh_compute_version: Define __vh_compute_version so it can be sourced and called independently for testing. Do not nest it inside constructs that prevent external invocation (e.g., avoid inlining it within a pipeline or command substitution that hides it).Per-ecosystem version file patterns, sed commands, and lock file regeneration rules. Read the relevant reference file based on the project's ecosystem.
When a monorepo is detected:
pnpm-workspace.yaml, lerna.json, Cargo.toml [workspace], etc.)git diff --cached --name-only to detect which packages have changes and only update those.npx claudepluginhub tani-shi/skills --plugin tani-shi-skillsSets up Git hooks with Husky, lint-staged, pre-commit framework, and commitlint to automate linting, formatting, testing, and commit message validation before CI.
Configures pre-commit or prek git hooks for code quality automation, formatting, linting, and commit message processing across multi-language projects.
Guides git hook implementation, framework selection (Husky.Net, lefthook, Husky, pre-commit), and best practices for .NET/C#, JS/TS, Python repos including Conventional Commits, secret scanning, and CI/CD integration.