Custy is a Python developer-productivity CLI for config-driven Git workflow and release automation. It initializes project resources, validates repository readiness, manages versions, generates changelogs, creates commits and tags, synchronizes multiple remotes, and combines those operations into repeatable development and release pipelines.
Custy supports SemVer, PEP 440, date-based, and Git-count version strategies. Its Typer and Rich interface also provides dry-run safety, configurable templates, backup and cleanup tools, and an experimental workflow-policy layer.
- โ๏ธ Configuration-driven behavior through
.config/custy/config.toml - ๐ฆ Project initialization for configuration, templates, and examples
- โ Repository, configuration, version, and commit-message validation
- ๐ข SemVer, PEP 440, date-based, and Git-count version strategies
- ๐ Configurable
CHANGELOG.mdgeneration using Jinja templates - ๐งฉ Structured commit and annotated tag workflows
- ๐ Primary, backup, and multi-remote push support
- ๐งฑ Focused
commit,tag,push,dev,release, andfullprofiles - ๐ Automatic project and version-file discovery with explicit overrides
- ๐ Native Git authentication first, with an optional container token fallback
- ๐งช Global dry-run, debug, and configurable logging options
- ๐งฐ Commit/tag-message backup and stale-resource cleanup commands
- ๐ณ Local Docker, Docker Compose, GHCR, and Makefile workflows
- ๐ง Experimental branch and release workflow-policy checks
After installing Custy, initialize its project resources and validate the repository:
custy init
custy validatePreview the daily development profile:
custy --dry-run run devReview the plan before removing --dry-run for a live operation.
Preview a release pipeline without applying its side effects:
custy --dry-run run releaseDry-run still performs read-only discovery, such as file inspection and Git or configured-remote queries, so its preview reflects the current repository. File writes, deletions, editor launches, Git mutations, and remote mutations are simulated. Normal diagnostic logs may still be written.
Use custy --help or custy <command> --help to inspect the available commands
and options.
Choose the method that fits your environment. Custy is currently distributed from its source repositories, release artifacts, container registries, and a private GitLab PyPI registry for authorized users. The private Python registry is distinct from GHCR container images and does not require a public PyPI release.
For a local Python installation:
- Python 3.14 or newer
- Git
pipthrough the selected Python interpreter- A virtual environment is recommended
Docker already provides Python, Git, and Custy inside the image. Install Docker only when you want to use the container method. Make is optional and is used by the repository's development helpers.
This is the recommended method for Custy contributors and local development.
Windows PowerShell
git clone https://github.com/devalltect00/Custy.git
Set-Location Custy
py -3.14 -m venv venv
.\venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e .Linux and macOS
git clone https://github.com/devalltect00/Custy.git
cd Custy
python3.14 -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e .Install contributor and local documentation dependencies when needed:
python -m pip install -e ".[dev,docs]"Use a version tag for a reproducible installation into another project or environment:
python -m pip install "git+https://github.com/devalltect00/Custy.git@v<version>"Install the latest main branch when you intentionally want current source:
python -m pip install "git+https://github.com/devalltect00/Custy.git@main"The GitLab mirror can be used in the same way:
python -m pip install "git+https://gitlab.com/devalltects-group/custy.git@main"Replace v<version> with an available release tag such as v1.2.3.
The GitHub Releases page provides versioned Python distribution artifacts generated by the release workflow. Download a wheel or source archive, then install the local file:
python -m pip install ./custy-<version>-py3-none-any.whlor:
python -m pip install ./custy-<version>.tar.gzContainer images are distributed through GitHub Packages / GitHub Container Registry (GHCR). They are referenced by GitHub Releases, but are pulled from GHCR rather than downloaded as release assets.
Pull the latest production image:
docker pull ghcr.io/devalltect00/custy:latestFor reproducible use, replace latest with an available version tag such as
v1.2.3. Development and immutable commit images may also be published with
dev and sha-<commit> tags.
Custy operates on a Git repository, so mount the project you want to manage at
/workspace.
Windows PowerShell
docker run --rm -it `
--volume "${PWD}:/workspace" `
--workdir /workspace `
ghcr.io/devalltect00/custy:latest --helpLinux and macOS
docker run --rm -it \
--volume "$(pwd):/workspace" \
--workdir /workspace \
ghcr.io/devalltect00/custy:latest --helpPass Custy arguments after the image name. For example:
docker run --rm -it \
--volume "$(pwd):/workspace" \
--workdir /workspace \
ghcr.io/devalltect00/custy:v<version> --dry-run run releaseThe image contains Git, but authenticated fetch, push, and multi-remote operations still require suitable repository credentials inside the container. Do not mount or copy credentials into an image; provide them securely at runtime.
Choose a version already published in the target project's registry. In an activated virtual environment, replace the placeholders:
python -m pip install --index-url "https://gitlab.com/api/v4/projects/<project-id>/packages/pypi/simple" "custy==<package-version>"
custy --help
Use a deploy token with read_package_registry. Supply credentials through
pip authentication,
not committed files or shared command history. The package version is PEP 440:
for example, v2.1.0 becomes 2.1.0.
Use --index-url, not --extra-index-url; review
GitLab package forwarding
if dependencies must stay private.
See installation and registry guidance for authentication, other installation methods, and registry setup.
For a Python installation:
custy --help
custy --versionFor Docker:
docker run --rm ghcr.io/devalltect00/custy:latest --versionThe Makefile is optional and contains local, Docker, Compose, registry, testing, quality, documentation, and release helpers. Use its built-in help instead of relying on a copied command list that may become outdated:
make helpUse a focused help view for one workflow family:
make help-local
make help-docker
make help-compose
make help-remoteFor example, the remote-image helpers can pull and run Custy from GHCR:
make r-custy-pull
make r-custy-run-releaseThe same remote catalog exposes the current Reflow workflows, including safe preview targets:
make r-reflow-releases-recover-dryrun
make r-reflow-tags-convert-dryrun
make r-reflow-dockerize-dryrunStart with make help-local for environment setup, tests, formatting,
documentation, builds, and local Custy commands.
custy init
custy validatecusty changelog generatecusty commit --auto-stage
custy tag --bump patch
custy push --all-remotecusty run dev
custy run release
custy run fullRun custy run --help before choosing a supported profile.
| Command | Purpose |
|---|---|
custy configure credentials |
Manage optional container credential fallback |
custy backup commit |
Back up the commit-message template |
custy backup tag |
Back up the tag-message template |
custy backup all |
Back up both message templates |
custy cleanup backups |
Remove old message-template backups |
custy cleanup branches |
Remove matching temporary branches |
custy cleanup all |
Run backup and branch cleanup together |
custy version update |
Resolve and synchronize project versions |
custy changelog generate |
Generate CHANGELOG.md from repository history |
custy workflow branch --enforce |
Enforce experimental workflow policy checks |
Use each command's --help output before running an operation that changes the
repository. Global options such as --dry-run must appear before the command.
- ๐ Custy documentation portal
- ๐ Getting started
- ๐ฅ๏ธ Command guides
- โ๏ธ Configuration reference
- ๐งฑ Pipeline guides
- ๐ฎ๐ฉ Dokumentasi Bahasa Indonesia
- ๐ Local usage notes
- ๐ Local CLI command reference
- ๐ ๏ธ Local Make workflow guide
The optional metadata sync script is source-checkout tooling, not an installed application command. Run it from this repository's root:
python scripts/repository/src/sync_metadata.py --dry-runIt reads [project].description and the separate
[tool.devalltect.github].topics / [tool.devalltect.gitlab].topics tables
in pyproject.toml. Package keywords are not repository topics.
Review GITHUB_REMOTES and GITLAB_REMOTES in the script: the current
defaults are origin and backup. Each list contains fallback candidates;
the first valid fetch URL selects one repository per provider. Both providers
must resolve. This helper currently targets GitHub.com and GitLab.com.
Dry-run uses Python and read-only Git discovery; it does not call provider
APIs. Live synchronization additionally needs authenticated gh and glab
with access to update those repositories. Their authentication is separate from
Custy's optional Git credential fallback.
Before removing --dry-run, review the targets and metadata carefully:
the live helper does not ask for confirmation, replaces the topic lists, and
clears existing topics when a list is empty or missing. A failure can leave
earlier updates applied; there is no cross-provider rollback.
Known follow-up: the script's docstring still shows the old path, and its GitHub topic-limit constant is 50 despite GitHub's maximum of 20 topics. Use the path above and keep the GitHub list within 20 until corrected. These issues and isolated test coverage are tracked in the TODO history.
See docs/project_structure.md for the detailed
repository layout.
Contributions, issues, and suggestions are welcome. See
CONTRIBUTING.md for the contributor workflow.
See SECURITY.md for the security policy and reporting process.
See CHANGELOG.md for release history.
Custy is open-source software licensed under the MIT License.
Handcrafted with โค๏ธ by Devalltect / Rizky Fernandes