auto-push

0.9.0 · MIT · October 5, 2026

One command pulls, asks your AI CLI for the commit message, and pushes upstream.

auto-push reads .auto-push.json, runs each step in order, and pushes HEAD to the branch your local branch already tracks.

Install

Homebrew on macOS. You also need git and a local AI CLI. claude is the default. codex, ollama, or any other CLI can take the generate step. Linux and source builds are below.

brew tap dickwu/tap
brew install dickwu/tap/auto-push

Core pipeline

  1. 1 stash
  2. 2 pull
  3. 3 unstash
  4. 4 stage
  5. 5 generate Example subject feat: add user auth
  6. 6 commit
  7. 7 push

What each core step runs

The names are the step ids --skip uses. This is the documented pipeline, not a guess at your repo. On first run, auto-push writes .auto-push.json with defaults for the AI CLI and project it finds.

  • stashgit stash push -m 'auto-push' || true
  • pullgit pull
  • unstashgit stash pop || true
  • stagegit add -A

generate calls claude directly in the documented pipeline and stores stdout in commit_message. The staged diff is the {{ diff }} argument. Commit style in that config is conventional commits, a 72-character subject, and a body. max_diff_bytes there is 20000.

commit runs git commit -m '{{ commit_message }}', then records the short hash and the subject. push runs git push {{ upstream_remote }} {{ push_refspec }}. If that push fails, the documented on_error waits 2 seconds, pulls the upstream branch, and pushes again.

The example pipeline also runs cargo test and cargo clippy -- -D warnings before stage. Those are project steps. Smart init may add commands that match the repo, such as npm run lint or pnpm build.

The subject in the generate window is the example from auto-push -m "feat: add user auth". It shows the conventional style. It is not a recorded run.

The push follows upstream

A push lands on the branch's upstream, by its name on the remote. That is the same branch git pull follows. main tracking origin/main pushes main. A release worktree checked out as rel-1 from origin/main still pushes main. {{ push_refspec }} is HEAD:main, not a new remote branch named rel-1.

A branch with no upstream pushes its own name to the default remote. While the pipeline runs, git sees push.default=upstream through GIT_CONFIG_* environment variables. auto-push does not write your git config. A bare git push inside any step follows the same rule.

Preflight

[preflight] rel-1 -> origin/main

Smart init writes the pipeline

auto-push --smart-init builds a project pipeline and walks you through it before anything is written.

  1. Scan the repo

    Reads manifests such as package.json, Cargo.toml, and pyproject.toml, CI config, Docker files, and git remotes. Credentials in remote URLs are redacted before anything is sent to the AI.

  2. Detect the workspace

    Finds sub-workspaces and monorepos: npm workspaces, Cargo workspace, Lerna, Nx, and pnpm-workspace.yaml. Known directories such as src-tauri or packages/* are labeled.

  3. Ask your AI CLI

    Sends the project fingerprint and file tree. The reply is a JSON pipeline: the seven core steps, plus project commands. --provider chooses the CLI and writes that provider into the generated generate step.

  4. Walk each step

    Shows the command, a confidence of high, medium, or low, and any alternatives. Accept, edit, or remove each step.

  5. Write the file

    Writes .auto-push.json. If a config file is already there, you are asked before it is overwritten.

Five layers, top one wins

Each layer deep-merges into the one below it. Arrays, including pipeline, are replaced, not merged. The flag you type outranks the file in the repo.

  1. CLI flags --skip, --var, -m

    One run. Nothing is written to a config file.

  2. Branch overrides branches in the repo file

    Glob keys such as main or feature/* replace settings for that branch. The documented example sets an empty pipeline on main, and raises the subject length to 100 on feature/*.

  3. Repo config .auto-push.json

    Project pipeline, generate style, and user variables. Created on first run when it is missing.

  4. Global config ~/.auto-push.json

    Preferences that apply in every repository.

  5. Built-in defaults conventional commits

    The standard pipeline and commit style, used until a file replaces them.

Older configs that still use pre_push or after_push are migrated to pipeline at runtime, with a deprecation warning. --no-pull, --no-push, --no-generate, and --no-stash remain for one major version. --rebase means setting git pull --rebase in the pipeline.

Shell mode and argv mode

Shell mode

A run string is passed to sh -c. Use it for short commands. It cannot be combined with command.

{ "name": "tests", "run": "cargo test" }

Argv mode

command and args are passed directly, so quotes, newlines, and a large diff do not go through a shell. Use this for the AI CLI.

{
  "name": "generate",
  "command": "claude",
  "args": ["-p", "{{ diff }}", "--system-prompt", "{{ system_prompt }}"],
  "capture": "commit_message"
}

Commands

Every flag below is in the CLI reference. Copy the line you want to run.

  • auto-push Pull, stage all, generate a commit message, commit, and push.
  • auto-push --confirm Prompt before each step.
  • auto-push --dry-run Preview without executing.
  • auto-push --skip pull --skip tests Skip pipeline commands by name. --skip is repeatable.
  • auto-push --skip push Commit, and skip the push step.
  • auto-push -m "feat: add user auth" Use a manual commit message. Generation is skipped.
  • auto-push --var slack_channel=#urgent Override or add a template variable. --var is repeatable.
  • auto-push --provider codex Override the generate command's provider for this run.
  • auto-push --show-config Show the merged config for the current branch and exit.
  • auto-push --smart-init Scan the project and generate a tailored pipeline.
  • auto-push --smart-init --yes Auto-accept non-dangerous steps. Requires --smart-init.
  • auto-push --force Auto-accept all confirmation prompts.

Install without Homebrew

Prebuilt binaries exist for macOS (Apple silicon and Intel) and Linux (aarch64 and x86_64). The formula installs 0.9.0. The script installs the latest GitHub release. Release tag: v0.9.0.

  • Linux or macOS script

    Downloads the release tarball for this machine and installs the auto-push binary into /usr/local/bin. If that directory is not writable, the script uses sudo.

    curl -fsSL https://raw.githubusercontent.com/dickwu/auto-push/main/install.sh | bash
  • Custom directory

    Same script. INSTALL_DIR replaces /usr/local/bin.

    INSTALL_DIR=~/.local/bin curl -fsSL https://raw.githubusercontent.com/dickwu/auto-push/main/install.sh | bash
  • From source

    Builds with Cargo from the git repository. The formula homepage and the source are the same repo.

    cargo install --git https://github.com/dickwu/auto-push

Questions

What does one auto-push command do?
One auto-push command runs the pipeline in .auto-push.json. The core steps are stash, pull, unstash, stage, generate, commit, and push. The generate step asks a local AI CLI for the commit message. You can skip a step, dry-run the pipeline, or pass your own message and skip generation.
How do I install auto-push with Homebrew?
Run brew tap dickwu/tap, then brew install dickwu/tap/auto-push. That installs the auto-push binary from the dickwu/tap formula. The formula version is 0.9.0, released October 5, 2026, under the MIT license. The formula homepage is https://github.com/dickwu/auto-push.
Which operating systems have prebuilt binaries?
macOS on Apple silicon and Intel, and Linux on aarch64 and x86_64. The install script at https://raw.githubusercontent.com/dickwu/auto-push/main/install.sh installs the latest release into /usr/local/bin, or into INSTALL_DIR if you set it, and uses sudo when that directory is not writable. cargo install --git https://github.com/dickwu/auto-push builds from source.
Which AI CLI does the generate step call?
The default generate command calls the claude CLI and passes the staged diff as {{ diff }}. auto-push --provider codex uses Codex for that run. The generate step can call codex, ollama, or any custom CLI instead.
Where does the push go?
The push lands on the branch's upstream, by its name on the remote, the same branch git pull follows. A local branch named rel-1 that tracks origin/main prints [preflight] rel-1 -> origin/main and pushes with the refspec HEAD:main. A branch with no upstream pushes its own name to the default remote. While the pipeline runs, git sees push.default=upstream through GIT_CONFIG_* environment variables, so your git config is left unchanged.
What does smart-init do?
auto-push --smart-init scans the repository, redacts credentials in remote URLs, and sends the project fingerprint and file tree to your AI CLI for a pipeline suited to the stack. It shows each proposed step with a confidence of high, medium, or low, and any alternatives, so you can accept, edit, or remove it, then writes .auto-push.json. Commands that match curl | sh, eval, sudo, rm -rf /, or a pipe to a shell are rejected and are neither shown nor written. auto-push --smart-init --yes skips the interactive prompts, including the overwrite confirmation. If claude, codex, and ollama are all absent, smart-init uses its heuristic init.
How do I preview or skip steps?
auto-push --dry-run previews the pipeline and does not execute it. auto-push --confirm prompts before each step. --skip is repeatable, as in auto-push --skip pull --skip tests. auto-push --skip push commits and does not push. auto-push -m "feat: add user auth" uses that message and skips generation. auto-push --force auto-accepts confirmation prompts.
Where is the source and the license?
auto-push is MIT licensed. The source repository and the formula homepage are https://github.com/dickwu/auto-push. The Homebrew formula is https://github.com/dickwu/homebrew-tap/blob/main/Formula/auto-push.rb. The LifeFarmer catalog is https://lifefarmer.ca.