Skip to content

Migrate git hooks scripts from Bash to Rust #1843

@josecelano

Description

@josecelano

Goal

Replace the three Bash scripts that implement pre-commit checks, pre-push checks, and git hook installation with a single Rust binary that improves testability, type safety, and maintainability, and that adds real-time feedback during long-running checks so developers and automation agents can see hook progress without cancelling valid runs.

Scripts to replace

Script Purpose
contrib/dev-tools/git/hooks/pre-commit.sh Runs fast quality checks (cargo machete --with-metadata, linter, doc tests)
contrib/dev-tools/git/hooks/pre-push.sh Runs comprehensive checks (machete, linters, nightly build, tests, E2E)
contrib/dev-tools/git/install-git-hooks.sh Installs hooks from .githooks/ to .git/hooks/

Motivation

The scripts have grown beyond simple orchestration (engineering policy #3 in AGENTS.md). They now implement structured argument parsing, a multi-step runner with timing and log management, and two output modes — logic that is duplicated across both scripts. This also creates feedback UX and redundant-execution problems:

  • Hooks appear hung during long checks (pre-push takes ~15 min); no intermediate progress is visible.
  • If only Markdown files are staged, the full Rust suite still runs unnecessarily.
  • Hooks re-run even when they already passed for the same set of changes.

Implementation plan (two phases)

Phase 1 — Core migration: implement the same steps as the current scripts using NDJSON output (no --format=text|json switch), switch over, and remove the Bash scripts.

Phase 2 — Enhancements: heartbeat events for long steps, smart step skipping for docs-only commits, and idempotency cache to skip hooks that already passed for the same changes.

Full spec

See docs/issues/open/ for the complete implementation spec once the spec-only PR is merged.

Compliance

The new binary must comply with the global CLI output contract ADR (docs/adrs/20260519000000_define_global_cli_output_contract.md) from day one: no-stdout-result class, NDJSON on stderr, exit codes 0/1/2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No fields configured for Task.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions