A robust Python CLI tool to manage Git workflows with intelligent commit, push, tagging, changelog generation, GitHub releases, hook execution, and error handling.
Project description
pnp — Push and Publish
pnp is a lightweight CLI tool to automate common Git workflow steps for any project type:
- Staging and committing changes
- Pushing to Git remotes
- Automatically bumping semantic version tags
- Publishing releases (including GitHub releases)
It's designed for fast iteration, CI integration, and monorepo-aware projects.
Features
- Initialize Git repo if not present
- Detect uncommitted changes and auto-commit
- Push commits to a remote branch (with optional forced push)
- Bump semantic version tags (
major,minor,patch) automatically - Generate changelog from commit messages between tags
- Optional GPG signing of tags
- Pre-push hooks for tests, linters, or build steps
- CI mode: non-interactive, fail-fast for automation pipelines
- Monorepo support: operate on sub-packages
- GitHub releases: create releases from tags with optional asset uploads
- Dry-run mode for safe testing
- Optional git-machete checks/sync before push/publish
Project Detection
pnp treats a directory as a project root when one or more
common manifest markers are present:
pyproject.tomlpackage.jsongo.modCargo.tomlpom.xmlbuild.gradle/build.gradle.ktscomposer.jsonGemfilemix.exsProject.toml
These markers are used for monorepo subproject detection and doctor metadata checks.
Support Matrix
| Area | Supported |
|---|---|
| Python | 3.10, 3.11, 3.12 |
| OS | Linux, macOS, Windows |
| Git | 2.30+ |
| Shells | POSIX sh, Bash/Zsh/Fish, PowerShell/CMD |
Installation
Install via PyPI:
pip install git-pnp
Usage
Basic push and publish
# Stage, commit, push, bump tag, and push tag
git pnp . --push --publish
Interactive mode
git pnp . --push --publish --interactive
Compose commit message in editor
git pnp . --push --publish --edit-message
GitHub release with assets
git pnp . --push --publish --gh-release \
--gh-repo "username/pkg" \
--gh-assets "dist/pkg-0.1.0-py3-none-any.whl" \
--interactive
Run pre-push hooks
git pnp . --push --publish --hooks "pytest -q; flake8"
Dry-run mode
git pnp . --push --publish --dry-run
Check-only preflight (no mutation)
git pnp . --check-only --push --publish
git pnp . --check-only --strict --push --publish
git pnp . --check-only --check-json
--check-only exit codes:
0: clean10: warnings only20: blockers found
Git-machete integration
git pnp . --push --publish --status
git pnp . --push --publish --sync
Environment doctor
pnp --doctor
Machine-readable doctor output:
pnp --doctor --doctor-json
pnp --doctor --doctor-report pnplog/doctor.json
Show effective config
pnp --show-config
Install git extension shim
pnp --install-git-ext
Optional custom install directory:
pnp --install-git-ext --git-ext-dir ~/bin
PATH setup examples:
-
Bash/Zsh (Linux/macOS):
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc # or ~/.zshrc
-
Fish (Linux/macOS):
fish_add_path $HOME/.local/bin -
PowerShell (Windows):
[Environment]::SetEnvironmentVariable( "Path", "$HOME\.local\bin;" + $env:Path, "User" )
-
CMD (Windows):
setx PATH "%USERPROFILE%\.local\bin;%PATH%"
After updating PATH, start a new shell and verify:
git pnp --version
Command-line Options
path (positional): Path to the project root (default .)
-
--push: Push commits to remote -
--publish: Create and push a tag -
--interactive / -i: Prompt per step -
--dry-run: Show actions without executing -
--safe-reset: Explicitly allow safe reset remediation during--auto-fix -
--destructive-reset: Explicitly allow destructive reset remediation during--auto-fix -
--version: Show installedpnpversion -
--doctor: Run local preflight checks -
--doctor-json: Emit doctor results as JSON -
--doctor-report: Write doctor JSON report to a file -
--check-only: Run non-mutating workflow preflight and exit -
--check-json: Emit machine-readable JSON for--check-only -
--strict: Treat warnings as blockers (recommended with--check-onlyin CI)
JSON schema contracts:
-
docs/JSON_CONTRACTS.md -
docs/ERROR_ENVELOPE.md -
Resolver taxonomy and codes:
docs/ERROR_CODES.md -
CI gate script:
tools/schema_gate.py -
--show-config: Print effective merged runtime configuration -
--install-git-ext: Installgit-pnpshim (enablesgit pnp) -
--uninstall-git-ext: Remove installedgit-pnpshim -
--git-ext-dir: Directory for extension shim install/remove -
--status: Rungit machete statusbefore workflow mutating steps -
--sync: Rungit machete statusandgit machete traverse --fetch --sync -
--traverse: Rungit machete statusandgit machete traverse -
--force: Force push remote if needed -
--ci: Non-interactive mode for CI pipelines -
--remote: Remote name to push (default: origin or upstream) -
--project-type: Adapter selection (auto,generic,python,node,rust,go,java,php,ruby,elixir,julia) -
--tag-bump: Type of version bump (major, minor, patch) -
--tag-prefix: Tag prefix (default v) -
--tag-message,-m: Tag message -
--edit-message,-e: Open editor to compose commit message via temp file (temp file is auto-deleted after workflow completion) -
--editor: Editor command override for--edit-message(otherwise inherits Git/editor env) -
--tag-sign: Sign the tag with GPG -
--hooks: Semicolon-separated pre-push commands -
--changelog-file: Save changelog to file -
--gh-release: Create a GitHub release for the tag -
--gh-repo: GitHub repository in owner/repo format -
--gh-token: GitHub personal access token (or env GITHUB_TOKEN) -
--gh-draft: Create release as draft -
--gh-prerelease: Mark release as prerelease -
--gh-assets: Comma-separated list of files to attach to release
Configuration precedence
Runtime options can be set from:
- Defaults in CLI
- Project config (
[tool.pnp]in nearestpyproject.toml) - Git config (
pnp.<key>), global then local repo - Environment variables (
PNP_<KEY>) - Explicit CLI flags (highest priority)
Examples:
# pyproject.toml
[tool.pnp]
push = true
publish = true
tag-bump = "minor"
machete-status = true
[tool.pnp.node]
pre-publish-hooks = ["drace lint .", "python -m unittest -q"]
build-script = "build"
test-script = "test"
publish-command = "npm publish --access public"
# git/env overrides
git config --global pnp.push true
git config --global pnp.publish true
git config --global pnp.tag-bump minor
git config --global pnp.machete-status true
git config --global pnp.check-only true
git config --global pnp.check-json true
git config --global pnp.strict true
export PNP_REMOTE=origin
Contribution
- Fork the repository
- Create a feature branch
- Install dev tooling:
pip install -e ".[dev]"
- Run checks locally:
make check - Submit a pull request
Release process references:
CHANGELOG.mddocs/release-notes-template.md
Internal Layout
pnp/cli.py: CLI argument parsing and dispatchpnp/workflow_engine.py: orchestration and workflow step sequencingpnp/ops.py: shared process/git/editor utility operationspnp/audit.py: doctor and check-only audit flows
CI Workflows
Publish to PyPIworkflow runs onv*tags via.github/workflows/publish.yml.- Recommended local gate before tagging:
make check.
Compatibility Policy
- Runtime support targets Python
3.10+. - CI validates Python
3.10,3.11,3.12on Linux/macOS/Windows. - Git
2.30+is required for expected workflow behavior. git pnpextension shims target:- POSIX shells via
git-pnp - Windows shells via
git-pnp.cmd(and POSIX shim for Git Bash)
- POSIX shells via
- Interactive TUI output assumes a TTY; CI/non-interactive paths remain plain and deterministic.
License
This project is licensed under the MIT License. See LICENSE
Disclaimer
pnp automates Git and GitHub operations. Use with caution on important repositories. Always test with --dry-run if unsure.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file git_pnp-3.0.0.tar.gz.
File metadata
- Download URL: git_pnp-3.0.0.tar.gz
- Upload date:
- Size: 111.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2684a5ab8550da9a4ca15437826c269f57bda8ea1b32c23594077227479fd7d7
|
|
| MD5 |
fedb596e6fef28e038dc648998097528
|
|
| BLAKE2b-256 |
b69d3b1149c087fad789219a17c57b242a18ae78fc9510b8d6e9588165bc824d
|
Provenance
The following attestation bundles were made for git_pnp-3.0.0.tar.gz:
Publisher:
publish.yml on 2kDarki/pnp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_pnp-3.0.0.tar.gz -
Subject digest:
2684a5ab8550da9a4ca15437826c269f57bda8ea1b32c23594077227479fd7d7 - Sigstore transparency entry: 1155294975
- Sigstore integration time:
-
Permalink:
2kDarki/pnp@92332023c0481aff802624d5a1d25a21b44eaffd -
Branch / Tag:
refs/tags/v3.0.0 - Owner: https://github.com/2kDarki
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@92332023c0481aff802624d5a1d25a21b44eaffd -
Trigger Event:
push
-
Statement type:
File details
Details for the file git_pnp-3.0.0-py3-none-any.whl.
File metadata
- Download URL: git_pnp-3.0.0-py3-none-any.whl
- Upload date:
- Size: 134.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2c582a8f28d6faa3472d349536e2da77d787ac423f5911e6b44419aedd4d716
|
|
| MD5 |
9c43cf8e6768b82540d3f0ab24a33e6e
|
|
| BLAKE2b-256 |
e0355752d2b12e9c1fca66bf6d60ae37fe708ea9f1cda0822cfdafb3cdc1e2b6
|
Provenance
The following attestation bundles were made for git_pnp-3.0.0-py3-none-any.whl:
Publisher:
publish.yml on 2kDarki/pnp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_pnp-3.0.0-py3-none-any.whl -
Subject digest:
d2c582a8f28d6faa3472d349536e2da77d787ac423f5911e6b44419aedd4d716 - Sigstore transparency entry: 1155294979
- Sigstore integration time:
-
Permalink:
2kDarki/pnp@92332023c0481aff802624d5a1d25a21b44eaffd -
Branch / Tag:
refs/tags/v3.0.0 - Owner: https://github.com/2kDarki
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@92332023c0481aff802624d5a1d25a21b44eaffd -
Trigger Event:
push
-
Statement type: