Skip to main content

Modular AI push-hook workflow runner

Project description

ai-push-hooks

ai-push-hooks is a configurable pre-push workflow runner for local Git repositories.

It runs module-based steps (collect, LLM, apply, exec, assert) before push so you can automate checks and optional repo maintenance tasks.

Install

Python

uv tool install ai-push-hooks
# or
pipx install ai-push-hooks

Node (wrapper around Python package)

npm install --save-dev ai-push-hooks
# or
pnpm add -D ai-push-hooks

Requirements:

  • Python 3.10+ (python3 or python) is required, including npm installs.
  • opencode-cli (or opencode) is required for llm and apply steps.
  • gh is required only if you use PR creation via gh_pr_create.

Quick start

  1. Install the CLI.

  2. Generate a starter config:

    ai-push-hooks init --template minimal-docs
    
  3. Wire it into Lefthook:

    pre-push:
      commands:
        ai-push-hooks:
          run: ai-push-hooks hook {1} {2}
    
  4. Push as usual. The workflow runs automatically before push completes.

Commands

Command What it does
ai-push-hooks hook <remote-name> <remote-url> Runs the configured pre-push workflow.
ai-push-hooks init --template minimal-docs Writes .ai-push-hooks.toml starter config.
ai-push-hooks init --template minimal-docs --force Overwrites an existing config file.

Configuration overview

  • Config file lookup order: .ai-push-hooks.toml, then ai-push-hooks.toml.
  • If no config file is present, built-in defaults are used.
  • File values are deep-merged over defaults.
  • Prompt resolution precedence for llm and apply steps:
    1. prompt
    2. prompt_file
    3. fallback_prompt_id

Configuration reference

Top-level keys

Key Type Required Default
general table no built-in values
llm table no built-in values
logging table no built-in values
workflow table yes { modules = ["docs"] }
modules table yes { docs = ... }

[general]

Key Type Default Description
enabled bool true Enables or disables the hook globally.
allow_push_on_error bool false If true, push continues even when workflow fails.
require_clean_worktree bool false If true, aborts when local changes exist.
skip_on_sync_branch bool true If true, skips on sync branch/worktree context.

[llm]

Key Type Default Description
runner string "opencode" LLM runner label (currently OpenCode flow).
model string "openai/gpt-5.3-codex-spark" Model passed to OpenCode.
variant string "" Optional OpenCode variant.
timeout_seconds int 800 Timeout per LLM invocation and related OpenCode calls.
max_parallel int 2 Max concurrent read-only steps (collect, llm).
json_max_retries int 2 Retry count for invalid JSON responses.
invalid_json_feedback_max_chars int 6000 Max invalid output included in retry feedback.
json_retry_new_session bool true Starts a new OpenCode session on JSON retry.
delete_session_after_run bool true Deletes OpenCode sessions after completion.
max_diff_bytes int 180000 Max bytes of git diff sent into workflow artifacts.
session_title_prefix string "ai-push-hooks" Prefix for OpenCode session titles.

[logging]

Key Type Default Description
level string "status" Console verbosity (status, info, debug).
jsonl bool true Enables JSONL event logging.
dir string ".git/ai-push-hooks/logs" Directory for hook.jsonl.
capture_llm_transcript bool true Exports OpenCode session transcripts.
transcript_dir string ".git/ai-push-hooks/transcripts" Transcript export directory.
summary_dir string ".git/ai-push-hooks/summaries" Per-run summary JSON directory.
print_llm_output bool false Mirrors raw OpenCode JSON stream to stdout.

[workflow]

Key Type Required Description
modules array of strings yes Ordered module IDs to run. Must contain at least one module and each ID must exist under [modules].

[modules.<module_id>]

Key Type Required Description
enabled bool no Enables or disables that module. Default true.
steps array of step tables yes Ordered workflow steps for the module. Must be non-empty.

[[modules.<module_id>.steps]]

Key Type Required Applies to Description
id string yes all step types Unique step identifier inside the module.
type string yes all step types One of: collect, llm, apply, exec, assert.
inputs array of strings no non-collect steps Artifact references from earlier steps.
output string yes llm Output artifact filename (often .json).
schema string no llm Validates parsed model output shape.
prompt string conditional llm, apply Highest-priority prompt source.
prompt_file string conditional llm, apply Repo-relative or absolute prompt file path.
fallback_prompt_id string conditional llm, apply Built-in prompt ID used when no higher source resolves.
collector string yes collect Collector handler ID.
allow_paths array of strings yes apply File glob allowlist for edits.
executor string yes exec Exec handler ID.
assertion string yes assert Assertion handler ID.
when_env string no any step Runs step only when env var parses as true.

llm and apply are promptable step types: at least one of prompt, prompt_file, or fallback_prompt_id must be set.

Supported handler and schema values

Collectors

Value Purpose
docs_context Collects docs-related context and diff artifacts.
beads_status_context Collects branch/beads alignment context.
pr_context Collects PR composition context.

LLM schemas

Value Expected payload
string_array JSON array of strings.
docs_issue_array JSON array of issue objects with at least file and description.
beads_alignment_result JSON object, optionally with commands string array.
pr_create_payload JSON object for PR creation fields.

Exec handlers

Value Purpose
beads_alignment Runs non-interactive Beads commands and writes action report when needed.
gh_pr_create Creates (or reuses) a GitHub PR via gh.

Assertion handlers

Value Purpose
docs_apply_requires_manual_commit Fails when docs were auto-edited and still need user review/commit.
beads_alignment_clean Fails when Beads alignment reports unresolved work.

Built-in fallback prompt IDs

Value Purpose
docs-query-basic Generate doc search queries from diff.
docs-analysis-basic Identify factual documentation drift.
docs-apply-basic Apply minimal doc fixes within allowlist.
beads-plan-basic Build Beads alignment command/report payload.
pr-compose-basic Draft PR title/body/base/head payload.

Environment variable overrides

Boolean env parsing accepts: 1, true, yes, y, on and 0, false, no, n, off.

Env var Effect
AI_PUSH_HOOKS_SKIP If true, sets general.enabled = false.
AI_PUSH_HOOKS_ALLOW_PUSH_ON_ERROR Overrides general.allow_push_on_error.
AI_PUSH_HOOKS_REQUIRE_CLEAN Overrides general.require_clean_worktree.
AI_PUSH_HOOKS_ALLOW_DIRTY If true, forces general.require_clean_worktree = false.
AI_PUSH_HOOKS_LOG_LEVEL Overrides logging.level.
AI_PUSH_HOOKS_PRINT_LLM_OUTPUT Overrides logging.print_llm_output.
AI_PUSH_HOOKS_MODEL Overrides llm.model.
AI_PUSH_HOOKS_VARIANT Overrides llm.variant.
AI_PUSH_HOOKS_TIMEOUT_SECONDS Overrides llm.timeout_seconds (integer).

when_env is step-level and can point to any env var. A common example is AI_PUSH_HOOKS_CREATE_PR to gate PR creation steps.

Example: docs + PR with opt-in creation

[workflow]
modules = ["docs", "pr"]

[modules.docs]
enabled = true

[[modules.docs.steps]]
id = "collect"
type = "collect"
collector = "docs_context"

[[modules.docs.steps]]
id = "query"
type = "llm"
fallback_prompt_id = "docs-query-basic"
inputs = ["collect/push.diff", "collect/changed-files.txt"]
output = "queries.json"
schema = "string_array"

[[modules.docs.steps]]
id = "analyze"
type = "llm"
fallback_prompt_id = "docs-analysis-basic"
inputs = ["collect/push.diff", "collect/docs-context.txt", "query/queries.json", "collect/recent-commits.txt"]
output = "issues.json"
schema = "docs_issue_array"

[[modules.docs.steps]]
id = "apply"
type = "apply"
fallback_prompt_id = "docs-apply-basic"
inputs = ["collect/push.diff", "collect/docs-context.txt", "analyze/issues.json"]
allow_paths = ["README.md", "docs/**/*.md"]

[[modules.docs.steps]]
id = "assert"
type = "assert"
assertion = "docs_apply_requires_manual_commit"
inputs = ["apply/result.json"]

[modules.pr]
enabled = true

[[modules.pr.steps]]
id = "collect"
type = "collect"
collector = "pr_context"

[[modules.pr.steps]]
id = "compose"
type = "llm"
fallback_prompt_id = "pr-compose-basic"
inputs = ["collect/pr-context.txt", "collect/changed-files.txt", "collect/push.diff", "collect/commits.txt"]
output = "pr-draft.json"
schema = "pr_create_payload"

[[modules.pr.steps]]
id = "create"
type = "exec"
executor = "gh_pr_create"
when_env = "AI_PUSH_HOOKS_CREATE_PR"
inputs = ["compose/pr-draft.json"]

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ai_push_hooks-0.1.11.tar.gz (32.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ai_push_hooks-0.1.11-py3-none-any.whl (33.3 kB view details)

Uploaded Python 3

File details

Details for the file ai_push_hooks-0.1.11.tar.gz.

File metadata

  • Download URL: ai_push_hooks-0.1.11.tar.gz
  • Upload date:
  • Size: 32.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ai_push_hooks-0.1.11.tar.gz
Algorithm Hash digest
SHA256 5a08f8c1d3c1030a942f90c3cd3efa7bf914f35ffa1607b26ee6a2d6417017f7
MD5 06a4172c3c21decadfdb1ede8fbce05e
BLAKE2b-256 3510ff19291656e5d051b4dd0b732383bebbdccefb9e60fa2c83ed2ff9187098

See more details on using hashes here.

Provenance

The following attestation bundles were made for ai_push_hooks-0.1.11.tar.gz:

Publisher: release.yml on shanebishop1/ai-push-hooks

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ai_push_hooks-0.1.11-py3-none-any.whl.

File metadata

  • Download URL: ai_push_hooks-0.1.11-py3-none-any.whl
  • Upload date:
  • Size: 33.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ai_push_hooks-0.1.11-py3-none-any.whl
Algorithm Hash digest
SHA256 22ac93dceb134c6f1d134432bc9e549aee824e74ba4351fcdd05bcafdeed8f68
MD5 e9e48eeeb483c43270080665aeb161da
BLAKE2b-256 3c0ee68f6d2bee0e61f8c7c4723b9b964f9d260f260bd4d35eed69812485714b

See more details on using hashes here.

Provenance

The following attestation bundles were made for ai_push_hooks-0.1.11-py3-none-any.whl:

Publisher: release.yml on shanebishop1/ai-push-hooks

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page