β Custy v2.1.0 β Cross-Project Compatibility Release
Custy v2.1.0 expands release automation beyond repositories that use an
app/-based Python layout. Custy can now start, initialize, validate, and
resolve version metadata across Python, Node.js, mixed, PHP, documentation-only,
and generic repositories without requiring placeholder directories or files.
The release also strengthens changelog template and repository-link resolution,
message backups, configured-remote workflows, CLI failure handling, dry-run
safety, configurable message editors, interactive Docker workflows, and
project-wide code quality. Commit-message validation now adapts to projects
with or without Commitizen, and Git-hook failures retain the output developers
need to diagnose them. Standalone push is now focused on synchronization,
keeps interactive Docker credential prompts visible, and preserves the Git
details needed to diagnose publication failures. Containers can also use an
optional protected file or environment token fallback without placing secrets
in project configuration. GitHub and GitLab validation are aligned, and
production images are published from reviewed annotated release tags instead
of ordinary commits. Explicit CLI version overrides now accept supported stable
and lifecycle formats, including SemVer release candidates such as
v2.1.0-rc.1 and common PEP 440 forms such as 2.1.0rc1.
This is a backward-compatible Semantic Versioning minor release. Existing
explicit paths remain strict, while newly initialized projects use automatic
project and version discovery by default.
The release brings together the project-compatibility, editor, validation,
credential, CI/CD, and private-package improvements developed across the
untagged v2.1.0 checkpoints. The v2.1.0 commit and annotated tag are the stable
release point for that cumulative work; the notes below focus on supported
commands, installation, and upgrade behavior.
- Runtime detection for Python, Node.js, PHP, mixed, and generic repository layouts.
- Automatic source selection with a safe project-root fallback.
- Automatic version metadata discovery for Python
__version__.py,pyproject.toml, andpackage.json. - Mixed-project synchronization for supported Python and Node.js metadata.
- Python version-module updates preserve final newlines so standard end-of-file hooks do not rewrite generated metadata and reject release commits.
- Adaptive
auto,custy,commitizen, andgitcommit-message validation providers. - Optional Commitizen integration with a strict mode for projects that require it.
- Adaptive
auto,native, andpre_commitGit-hook execution policies. - Native behavior for projects without installed pre-commit hooks or with only
an unused.pre-commit-config.yamlfile. - Safe direct execution for recognized Windows-generated pre-commit wrappers
mounted into Linux containers, without silently bypassing custom hooks. - Actionable Git-hook failures that preserve the hook's stdout, stderr, and exit status.
- Non-empty reviewed commit and tag messages are preserved; generated fallbacks
are limited to missing or empty files and use the detected project name. - Git-tag-only versioning for projects that intentionally have no supported version file.
- Explicit stable and lifecycle tag validation for SemVer-style and common
PEP 440-style alpha, beta, release-candidate, development, post-release, and
metadata-bearing values. - Project-aware
custy initthat does not create Python files in non-Python repositories. - Packaged changelog-template fallback for projects that have not run
custy inityet. - Project-owned changelog templates retain override priority, with clear errors for missing explicit custom templates.
- Automatic changelog repository-link discovery when the generated repository setting is left empty.
- Tag-message backups now honor the configured backup directory.
- Predictable main, backup, all-remote, and explicit CLI remote selection.
- Complete remote, synchronization, tag, and skip-tag propagation through supported pipelines.
- A focused three-step standalone push profile that validates the repository
and remotes before synchronization without initializing a release workflow. - Exclusive terminal ownership during Git push and workflow confirmation so
credential and confirmation prompts remain visible. - Disabled Rich rendering for hidden direct-command pipelines so standalone
custy pushretains the same stable prompts ascusty run push. - Direct terminal-stream passthrough when no managed token resolves, with clear
PAT guidance before native Git asks for HTTPS credentials. - Actionable push failures that preserve Git stdout, stderr, operation, exit
status, remote, and tag context. - Clear Docker credential-boundary guidance without storing or managing tokens
in Custy configuration. - Native-first GitHub and GitLab HTTPS token fallback for containers, sourced
from protected external files or named environment variables. - Guided
custy configure credentialssetup, secret-free status output,
read-only access testing, and explicit provider removal. - Opt-in Docker, Compose, and remote-image Make helpers with writable mounts
limited to setup and read-only mounts for inspection and runtime use. - Safe rejection of hidden PAT setup without
docker run -it, avoiding the
echoed-input fallback used by non-interactive password prompts. - Per-push credential-helper injection without changing persistent Git config,
plus non-interactive failure behavior that avoids indefinite prompts. - Configurable Windows, Linux, macOS, and container editor priorities.
- Reliable Visual Studio Code launching on Windows installations that expose
code.cmd. - Micro, Nano, Vim, and Vi included in the production image for interactive release workflows.
- Clean terminal-editor buffers by suspending live pipeline progress until editing finishes.
- Expanded Make helpers and refreshed pre-commit hooks improve Python 3.14 contributor workflows.
- Clearer CLI errors with detailed tracebacks available through
--debug. - Successful no-command help behavior for local and container-based discovery.
- Verified Docker operation from a Docusaurus project without an
app/directory. - GitHub and GitLab production image publication driven by annotated release
tags with non-empty messages and matching normalized package versions, with
latestreserved for stable releases and no separate commit-SHA image tag. - Clean Python 3.14 CI state without tracked bytecode artifacts, plus portable
CLI help assertions across GitHub and GitLab runners. - Authorized installation of
custy==2.1.0from a private GitLab Python package
registry. - Updated English and Indonesian documentation for project detection, initialization, versioning, CLI errors, and Docker usage.
Changelog generation no longer depends on an editable template already existing
under .config/custy/. Before initialization, Custy safely uses the packaged
default. After initialization, the project's editable template remains the
preferred override.
If a project explicitly configures a custom template that does not exist, Custy
reports the invalid path instead of silently selecting another template. Tag
message backups also use the directory selected in project configuration.
When the changelog repository value is empty, Custy can derive a supported
repository URL from eligible Git remote metadata. An explicit configured URL
remains authoritative. If no usable repository URL can be resolved, changelog
generation can continue without links where the configured output permits it.
Custy now applies one consistent remote-resolution model across direct commands
and supported custy run pipelines:
- An explicit CLI remote has the highest priority for a focused operation.
- Configured
push_tobehavior selects main, backup, or all remote groups. - All-remote execution combines configured main and backup remotes.
- Backup synchronization can extend a main-remote operation without replacing its primary destination.
- Selected remotes are validated before mutation.
- Dry-run performs the required discovery and validation but simulates local and remote changes.
- Standalone
custy pushandcusty run pushdo not calculate a version,
initialize release state, or wait for release confirmation.
The changelog repository URL and Git remote names serve different purposes.
The repository URL creates public changelog links, while default_remote,
main_remotes, and backup_remotes control Git operations and synchronization.
Custy continues to use normal Git credential helpers and SSH first. When an
HTTPS push runs inside a container that cannot inherit the host credential
manager, users may opt into a GitHub or GitLab token fallback:
filereads a protected token file from/run/secrets/custyby default;environmentreads the configured variable, such as
CUSTY_GITHUB_TOKENorCUSTY_GITLAB_TOKEN;container_only = truekeeps local execution on native Git authentication;custy configure credentialsprovides guided setup without a visible token
command-line option;statusnever displays token values andtestuses read-only
git ls-remote;- SSH private keys remain outside Custy's ownership and must be supplied by the
normal Git/SSH environment.
The fallback is injected only for the active Git command. Custy does not alter
system, global, or repository credential-helper configuration. Dry-run does not
read a token or contact the remote.
The Make interface keeps runtime credential mounting disabled by default. Use
CUSTY_CREDENTIALS_MOUNT=true only when a Docker, Compose, or remote-image run
should receive the external directory. Credential setup targets mount it
writable; status, access testing, and runtime targets mount it read-only. Token
values are never passed through Make variables.
Custy now resolves the editor used for commit and tag messages from a clear,
validated priority model:
VISUALand thenEDITOR, when environment precedence is enabled.- The active platform or container list from
[tool.custy.editor.candidates]. - Built-in platform defaults, when fallback is enabled.
Supported identifiers are vscode, notepad, micro, nano, vim, vi,
and neovim; code and nvim are accepted aliases. Custy now launches the
resolved executable path directly, which fixes Windows Visual Studio Code
installations where command discovery returns the code.cmd shim.
Unavailable candidates are skipped in priority order. Terminal editors are
skipped without an interactive TTY, and a launched editor that exits with an
error produces EDITOR_PROCESS_FAILED instead of unexpectedly opening another
editor. Dry-run resolves and reports the planned editor without launching a
process.
While a blocking terminal editor is open, Custy hides and stops the live
pipeline progress display so refreshes cannot overwrite the message buffer.
Custy restores the current step and resumes progress after the editor exits,
including the cleanup path for editor failures.
Custy now provides Make helpers for installing, updating, validating, cleaning,
refreshing, and running pre-commit hooks through the project virtual environment.
The refreshed hook set uses Ruff v0.16.5, pre-commit-hooks v6.0.0, and Black
26.5.1.
Ruff handles linting and safe lint fixes, while Black remains the single Python
formatter. Historical, copied, deprecated, development, and temporary reference
files are consistently excluded, including when pre-commit supplies their paths
explicitly.
Custy no longer assumes that every target repository installs or configures
Commitizen. Projects can choose one of four providers:
autodetects project-owned Commitizen configuration and usesczwhen it is available, otherwise it uses Custy's built-in validator;custyalways applies Custy's Conventional Commit rules;commitizenrequires project configuration and the externalczcommand;gitapplies basic message-file safety checks and leaves message-policy enforcement to Git hooks or other repository tooling.
Set require_tool = true to turn an unavailable or invalid detected external
provider into a blocking error. The existing --check-cz option remains a
strict one-run Commitizen override for backward compatibility. Commit-message
validation is independent from the version strategy, so a SemVer release may
still use Commitizen validation.
When git commit is rejected, Custy now keeps the actual Git and hook output.
Hook failures use GIT_HOOK_FAILED, while non-hook commit failures use
GIT_COMMIT_FAILED. This makes incompatible host hooks mounted into a Linux
container visible instead of reporting only a generic commit error.
[tool.custy.git.hooks].mode = "auto" is the recommended default. It keeps
normal Git execution when no relevant hook is installed, so projects that do
not use pre-commit need no additional dependency. A configuration file alone
does not opt a project into hook execution.
When Custy recognizes a pre-commit-generated wrapper that cannot run in the
current environment, such as a CRLF Windows hook mounted into Linux Docker, it
runs the equivalent configured stages through pre-commit directly. Git uses
--no-verify only after those stages pass. Unknown custom hooks are never
silently bypassed; Custy stops with an actionable policy error instead.
The production image includes the optional hook runtime. Local installations
can add it with custy[hooks] when direct execution is required.
Custy now treats non-empty configured commit and tag message files as reviewed
project-owned input. The release workflow preserves them through artifact
generation and editing. Fallback messages are generated only for missing or
empty files, use the detected target-project name, contain a valid release
header, and end with a final newline.
Newly generated configuration uses:
[tool.custy.project]
project_source = "auto"
[tool.custy.cli.paths]
version_file = "auto"Custy selects a useful source directory when one exists and otherwise uses the
project root. It recognizes conventional Python, Node.js, and PHP metadata but
does not require a supported framework or programming language just to start.
In automatic mode, Custy can update:
- an existing Python
__version__.py; - static
[project].versionmetadata inpyproject.toml; versioninpackage.jsonand supported root lockfile metadata;- both Python and Node.js metadata in a mixed repository.
When none of these targets exists, the project remains valid and Git tags can
act as the version source. Custy does not invent a Python version module for a
Node.js, Docusaurus, PHP, or generic project.
Project metadata stores the normalized version, such as 2.1.0, while the Git
release tag may retain the conventional v2.1.0 form.
When Custy updates an existing Python version module, it preserves the line
ending around the __version__ assignment and adds a final newline only when
one is missing. This keeps generated metadata stable when repositories enforce
end-of-file formatting through pre-commit hooks.
Use an approved explicit tag when the exact release version is already known.
Custy accepts stable versions such as v2.1.0, SemVer lifecycle versions such
as v2.1.0-rc.1, and common PEP 440 lifecycle versions such as 2.1.0rc1.
An omitted v prefix is added automatically. Malformed versions and arbitrary
lifecycle identifiers remain rejected before the workflow starts.
custy init now adapts version-file creation to the detected project:
- Existing version metadata is preserved.
- A missing Python version module is created only when a Python project needs one.
- Non-Python and generic projects receive Custy configuration and templates without an unrelated Python file.
- Nested commit and tag message examples continue to copy recursively.
- Dry-run initialization lists every planned directory and file without changing the target project.
Known configuration and validation failures now use consistent Custy error
panels instead of exposing a raw Python traceback. Unexpected errors are
summarized with a recovery hint in normal mode. Use --debug before the command
when a full traceback is needed.
Running custy with no subcommand now displays root help and exits successfully,
which makes image and installation discovery easier.
The production image can be mounted into projects that do not have app/:
docker run --rm -it -v "${PWD}:/workspace" -w /workspace custy-prod:latest
docker run --rm -it -v "${PWD}:/workspace" -w /workspace custy-prod:latest --help
docker run --rm -it -v "${PWD}:/workspace" -w /workspace custy-prod:latest --dry-run init --mode allThe dry-run form previews initialization without writing the intended Custy
configuration, template, example, or project-version files.
Standalone Docker push uses credentials available inside the container. It
does not inherit a credential-manager session from the host. When no managed
token resolves, Custy releases captured streams, gives native Git direct
terminal ownership, and explains that an HTTPS password prompt expects a PAT.
Credentials remain owned by Git and the execution environment rather than
Custy configuration.
Interactive images include Micro, Nano, Vim, and Vi. Custy prefers Micro by
default and loads its settings from /etc/custy/editors. Micro and Vim provide
Alt+Z undo and Alt+Y redo aliases in addition to native bindings. Nano keeps
its native Alt+U undo and Alt+E redo bindings because Alt+Z and Alt+Y
already serve Nano interface functions.
Ordinary pushes to main continue through the normal validation workflow but
do not publish a production container. GitHub and GitLab build production
images only from supported annotated v* tags with non-empty messages and a
normalized package version matching the selected release tag. GitHub also
supports explicitly selecting an existing annotated tag for a manual rebuild.
Every stable or prerelease build publishes its exact release tag. A stable tag
such as v2.1.0 also updates the v2.1, v2, and latest aliases;
prerelease tags such as v2.1.0-rc.1 never replace a stable alias. Buildx
provenance remains enabled, so referenced untagged OCI manifests may still
appear in GHCR alongside the tagged image.
GitHub and GitLab Releases both preserve the reviewed annotated tag message as
their public release notes. GitLab appends project, commit, pipeline, container,
and package-artifact information instead of using a generic automated-release
placeholder. GitHub appends populated release metadata plus literal commands for
pulling the exact image and verifying the Custy CLI. Release-note generation
does not execute those commands or include transient runner output.
Authorized users can install the stable package from the project's private
GitLab PyPI registry. Configure pip authentication with a deploy token limited
to read_package_registry, then use the token-free project index URL:
python -m pip install \
--index-url "https://gitlab.com/api/v4/projects/<project-id>/packages/pypi/simple" \
"custy==2.1.0"Supply the deploy-token username and token through an approved protected pip
credential mechanism or its interactive authentication flow. Never place a
token in committed configuration, shared command history, or a repository URL.
The protected release pipeline verifies one wheel and one source distribution
before publication. Unprotected tags validate those artifacts but cannot
publish them.
- Existing configuration is not rewritten automatically.
- Values such as
project_source = "app"andversion_file = "app/__version__.py"are explicit overrides and still require those paths to exist. - Change either value to
"auto"when automatic discovery is preferred. - Review
[tool.custy.changelog.links].repository; leave it empty for automatic discovery or set the canonical repository URL explicitly. - Review
default_remote,main_remotes,backup_remotes,push_to, and backup-synchronization settings before enabling remote mutations. - Review
[tool.custy.editor]and[tool.custy.editor.candidates]when the platform defaults do not match the preferred local or container editor. - Review
[tool.custy.commit.validation]; keepprovider = "auto"for adaptive behavior or choose an explicit provider when repository policy requires one. - Review
[tool.custy.git.hooks]; keepmode = "auto"for native no-hook
behavior plus safe cross-platform adaptation, or choose an explicit mode
only when repository policy requires it. - Install
custy[commitizen]for strict local Commitizen validation; the production image already includes the extra. - Install
custy[hooks]when local direct pre-commit execution is required;
projects without installed hooks do not need this extra. - Ensure hooks stored in
.git/hooks/are executable by the environment that runs Custy, especially when mounting a Windows repository into a Linux container. - Authenticate Git in the environment that performs a push. A Linux container
does not automatically inherit Windows Git Credential Manager or another
host credential session. - Keep
[tool.custy.git.credentials].mode = "native"for Git-only behavior, or
usecusty configure credentialsto enable the optional container fallback. - Mount a protected external token directory or pass an approved token
environment variable into Docker; do not copy tokens into the image or
repository. - Use a writable credential mount during
configure credentials set, then a
read-only mount for status, access testing, and push. Without the mount,
--rmremoves token files stored only in the container filesystem. - Do not place GitHub or GitLab tokens in Custy configuration, message
templates, Docker image layers, or repository remote URLs. - Use
docker run -itfor workflows that open a terminal editor; host GUI editors are not automatically available inside the container. - Rebuild or pull the intended Custy image if progress rows still appear inside a terminal editor; stale overlays indicate an older executable or cached image.
- Review the dry-run output before replacing customized configuration.
- Reinstall an editable source checkout with
python -m pip install -e .so the localcustyconsole script uses the protected entry point. - The
custy workflowbranch-policy command remains experimental.
These are recorded development results, not a claim that final publication
checks have already completed:
- Complete test suite: 1,361 passed.
- Overall test coverage: 83%.
- Commit-validation provider and Git-hook diagnostic regressions: passed.
- Ruff validation: passed.
- Black formatting validation: passed.
- Diff whitespace validation: passed.
- Pre-commit configuration validation: passed.
- GitHub Actions and GitLab CI validation: passed with active source, tests,
helpers, and generated bytecode handled correctly. - Production publication policy: exact annotated release tag, plus matching
major, minor, andlatestaliases only for stable releases. - Container editors and Custy-managed settings: Micro, Nano, Vim, and Vi verified.
- Container editor resolution: Micro β Nano β Vim β Vi verified.
- Docusaurus cross-project startup: verified.
- Container dry-run initialization: verified with no intended project-file changes.
- Repository-link and configured-remote regression coverage: passed.
- Standalone push resolution: three-step repository validation, remote
validation, and push profile verified. - Push terminal ownership and preserved Git diagnostics: regression coverage
passed. - English and Indonesian documentation: TypeScript validation and production builds passed.
Before publishing v2.1.0, re-run the applicable release checks against the exact
stable commit, complete the credential-enabled image rebuild and packaged-helper
check, and verify a container push dry-run with the configured destinations and
no target-project or remote mutation. Review the final changelog, package
metadata, image destinations, and annotated tag message at the same time.
The canonical Custy documentation now describes v2.1.0 behavior:
-
English: https://devalltect00.github.io/devalltect-docs/docs/custy
-
Indonesian: https://devalltect00.github.io/devalltect-docs/id/docs/custy
-
Version:
v2.1.0 -
Previous version:
v2.0.0 -
Development lineage: untagged foundation checkpoint plus checkpoints 1β9
-
Strategy: Semantic Versioning
-
Stability: Stable for supported commands
-
Documentation: English and Indonesian aligned with v2.1.0
-
Changelog links: Explicit configuration with automatic Git-remote fallback
-
Remote workflows: Explicit, main, backup, and all-remote selection supported
-
Standalone push: Focused three-step synchronization without release initialization
-
Container push UX: Interactive Git prompts receive direct terminal ownership during live pipelines
-
Push diagnostics: Git output, exit status, remote, and tag context preserved
-
Credential ownership: Native Git first, with an optional protected external token fallback for supported container HTTPS pushes
-
Make credential mounts: Explicit opt-in at runtime, writable only for setup, and read-only for inspection and push
-
Python version metadata: Final-newline preservation for pre-commit compatibility
-
Explicit tags: Stable and supported lifecycle formats with early validation
-
Message editors: Configurable per platform and container with safe fallback behavior and exclusive terminal-progress handoff
-
Commit validation: Adaptive built-in, Commitizen, and Git-policy modes with strict opt-in enforcement
-
Git hooks: Native no-hook behavior, safe direct pre-commit adaptation, and no silent custom-hook bypass
-
Release messages: Reviewed non-empty files preserved with project-aware generated fallbacks
-
Commit diagnostics: Git-hook output and exit status preserved
-
Production images: Annotated release tags only; stable releases also update matching major, minor, and
latestaliases -
OCI provenance: Enabled, with referenced registry manifests retained
-
Experimental feature:
custy workflowremains experimental
Release: v2.1.0
Author: Devalltect / Rizky Fernandes
π Release Information
- Version:
2.1.0 - Release Type:
stable - Repository:
devalltect00/Custy - Commit:
63145b3ae4ef808c70b757fc9521a60db3d88a22 - Workflow:
π Release
π³ Docker Image
Pull the exact release image:
docker pull ghcr.io/devalltect00/custy:v2.1.0Verify the CLI:
docker run --rm ghcr.io/devalltect00/custy:v2.1.0 --helpStable releases also update the latest image tag.
π₯ Python Package
Wheel and source-distribution artifacts are attached to this release.