Release CLI Reference
myk-claude-tools release is the release-focused command group in this repository. It gives you four building blocks:
infochecks whether the repository is ready for a release and lists commits since the last matching tagdetect-versionsfinds version files the tool knows how to updatebump-versionrewrites those files to a new versioncreatepublishes the GitHub release from a changelog file
The CLI is installed as the myk-claude-tools command and requires Python 3.10+:
requires-python = ">=3.10"
# ... other project metadata ...
[project.scripts]
myk-claude-tools = "myk_claude_tools.cli:main"
At A Glance
| Command | What it does | External tools |
|---|---|---|
release info |
Validates branch state, working tree, and remote sync, then returns tags and commits | git, gh |
release detect-versions |
Scans the current directory for known version files | None |
release bump-version |
Updates detected version files to a new version | None |
release create |
Creates a GitHub release from a changelog file | gh |
Note: All four commands print JSON to stdout.
release info,release bump-version, andrelease createexit with status code1on failure.release detect-versionsreports “nothing found” with"count": 0instead of failing.
myk-claude-tools release info
Use release info first. It tells you whether the current checkout is in a releasable state, and if it is, it returns the last tag and the commits that would be included in the release.
Syntax: myk-claude-tools release info [--repo OWNER/REPO] [--target BRANCH] [--tag-match GLOB]
Example commands used by the project release workflow:
myk-claude-tools release info --target <branch>
myk-claude-tools release info --target <branch> --tag-match <pattern>
myk-claude-tools release info
Inputs
| Input | Required | Description |
|---|---|---|
--repo OWNER/REPO |
No | Repository in owner/repo format. If omitted, the command asks gh for the current repository. |
--target BRANCH |
No | Branch that must match the current checkout for release validation to pass. |
--tag-match GLOB |
No | Glob used to filter tags, such as v2.10.*. This is a glob, not a regular expression. |
How target branch selection works
- If you pass
--target, that branch becomes the release target. - If you do not pass
--targetand your current branch looks likev2.10, that branch becomes the target automatically. - In that auto-detected version-branch case,
tag_matchalso defaults tov2.10.*unless you already provided--tag-match. - Otherwise, the target branch is the repository default branch from GitHub, with a fallback to
main.
Note: The version-branch shortcut is designed for branch names in the
vMAJOR.MINORformat, such asv2.10.
What it validates
Before it gathers tags or commits, release info checks all of the following:
- You are on the effective target branch.
- The working tree is clean, including both staged and unstaged changes.
git fetch origin <target>succeeds.- The local branch has no unpushed commits relative to
origin/<target>. - The local branch is not behind
origin/<target>.
Note: Remote sync checks are always done against
origin/<target>. If your release flow uses another remote, this command will not follow it automatically.Warning: If any validation fails,
release infodoes not return partial history. In that case,last_tagisnull,all_tagsandcommitsare empty,commit_countis0, andis_first_releaseisnull.Tip:
all_tagsis limited to the 10 most recent matching tags, andcommitsis limited to 100 entries. This command is meant for release preparation, not full-history export.
Success JSON
Top-level fields:
| Field | Type | Meaning |
|---|---|---|
metadata |
object | Repository metadata: owner, repo, current_branch, and default_branch. |
validations |
object | Detailed validation results. |
last_tag |
string \| null |
Most recent matching tag, or null if none was found. |
all_tags |
string[] |
Recent matching tags, sorted by version, newest first. |
commits |
object[] |
Commits since last_tag, or from HEAD if this is the first release. Each item contains hash, short_hash, subject, body, author, and date. |
commit_count |
number |
Number of commit objects returned. |
is_first_release |
boolean \| null |
true if no matching tag exists, false otherwise, and null when validation failed before history collection. |
target_branch |
string |
The effective target branch after applying defaults and auto-detection. |
tag_match |
string \| null |
The effective tag filter, whether explicit or auto-detected. |
validations fields:
| Field | Type | Meaning |
|---|---|---|
on_target_branch |
boolean |
Whether current_branch matches the effective target branch. |
default_branch |
string |
Repository default branch. |
current_branch |
string |
Current local branch name. |
working_tree_clean |
boolean |
Whether both staged and unstaged changes are absent. |
dirty_files |
string |
Up to the first 10 git status --porcelain lines when the tree is dirty; empty string when clean. |
fetch_successful |
boolean |
Whether git fetch origin <target> succeeded. |
synced_with_remote |
boolean |
Whether the local target branch is neither ahead of nor behind origin/<target>. |
unpushed_commits |
number |
Number of commits local is ahead of origin/<target>. |
behind_remote |
number |
Number of commits local is behind origin/<target>. |
all_passed |
boolean |
Final release-readiness result. |
Failure JSON
On failure, release info returns a bare error object:
| Field | Type | Meaning |
|---|---|---|
error |
string |
Reason the command failed, such as missing git or gh, an invalid repository format, an invalid target branch, or an invalid tag-match pattern. |
Tip:
release infois the only release command that fails with{"error": "..."}instead of{"status": "failed", "error": "..."}. If you are scripting the CLI, handle it separately.
myk-claude-tools release detect-versions
Use release detect-versions to see which files the CLI can version-bump automatically in the current directory.
Syntax: myk-claude-tools release detect-versions
Example from the project workflow:
myk-claude-tools release detect-versions
What it scans
| Source | What it reads | Output type |
|---|---|---|
pyproject.toml |
project.version |
pyproject |
package.json |
Top-level version |
package_json |
setup.cfg |
[metadata] version only |
setup_cfg |
Cargo.toml |
[package] version |
cargo |
build.gradle |
version assignment |
gradle |
build.gradle.kts |
version assignment |
gradle |
__init__.py |
__version__ = "..." |
python_version |
version.py |
__version__ = "..." |
python_version |
A few important details:
- Recursive scanning is only used for
__init__.pyandversion.py. setup.cfgis only detected when the version is static. Dynamic forms likeattr:andfile:are skipped.- The command skips hidden directories and common generated or dependency directories such as
.git,.venv,node_modules,dist,build,target, and cache folders.
Tip: Run
detect-versionsfrom the repository root. The returnedversion_files[].pathvalues are repo-relative paths, and they are the exact values you should feed back intorelease bump-version --files.Note: Malformed or unsupported files are skipped rather than causing the whole command to fail. If nothing matches, you get
"count": 0.
JSON output
| Field | Type | Meaning |
|---|---|---|
version_files |
object[] |
Detected files. Each item contains path, current_version, and type. |
count |
number |
Number of detected version files. |
Each version_files[] item contains:
| Field | Type | Meaning |
|---|---|---|
path |
string |
Repo-relative path such as pyproject.toml or mypackage/__init__.py. |
current_version |
string |
The version string currently found in that file. |
type |
string |
One of pyproject, package_json, setup_cfg, cargo, gradle, or python_version. |
myk-claude-tools release bump-version
Use release bump-version to rewrite version strings in the files discovered by release detect-versions.
Syntax: myk-claude-tools release bump-version VERSION [--files PATH]...
Example from the project workflow:
myk-claude-tools release bump-version <VERSION> --files <file1> --files <file2>
Inputs
| Input | Required | Description |
|---|---|---|
VERSION |
Yes | New version string, such as 1.2.0. It must be non-empty, single-line, and must not start with v or V. |
--files PATH |
No | Repeatable filter. Limits the update to specific files returned by release detect-versions. If omitted, all detected version files are updated. |
Warning: Pass the bare version number, such as
1.2.0, notv1.2.0. The command rejects a leadingvorV.Warning: If you use
--files, every listed file must match the output ofrelease detect-versions. One bad path makes the whole command fail before any file is rewritten.
What gets updated
Detected type |
Update behavior |
|---|---|
pyproject |
Rewrites version inside the [project] section only. |
package_json |
Rewrites the top-level version field. |
setup_cfg |
Rewrites version inside [metadata] only. Dynamic attr: and file: versions are skipped. |
cargo |
Rewrites version inside [package] only. |
gradle |
Rewrites the first matching version assignment. |
python_version |
Rewrites the first matching __version__ = "..." assignment. |
Behavior
- The command uses the same file-detection logic as
release detect-versions. - It only updates files that are already recognized by that detector.
- Rewrites are done atomically, so a file is written through a temporary file and then replaced.
- The command does not run
git add,git commit, or any other Git operation. - A run can succeed even when some files are skipped. It only fails when zero files were updated, or when input validation fails.
Tip: For automation, treat
updated[]as the source of truth for what actually changed.skipped[]tells you which files were ignored and why.
JSON output
| Field | Appears when | Type | Meaning |
|---|---|---|---|
status |
Always | string |
success or failed. |
version |
Success | string |
The new version that was written. |
updated |
Success | object[] |
Files that were updated. Each item contains path, old_version, and new_version. |
skipped |
Success or some failures | object[] |
Files that were not updated. Each item contains path and reason. |
error |
Failure | string |
Why the command failed, such as an invalid version string, no detected version files, unmatched --files, or no files updated. |
updated[] items:
| Field | Type | Meaning |
|---|---|---|
path |
string |
Updated file path. |
old_version |
string |
Version found before the rewrite. |
new_version |
string |
Version written to the file. |
skipped[] items:
| Field | Type | Meaning |
|---|---|---|
path |
string |
Skipped file path. |
reason |
string |
Reason the file was skipped, such as an unrecognized pattern or I/O error. |
myk-claude-tools release create
Use release create to publish the GitHub release once you have a final tag and a changelog file.
Syntax: myk-claude-tools release create OWNER/REPO TAG CHANGELOG_FILE [--prerelease] [--draft] [--target BRANCH] [--title TEXT]
Example from the project workflow:
CHANGELOG_FILE=$(mktemp /tmp/claude-release-XXXXXX.md)
trap "rm -f $CHANGELOG_FILE" EXIT
cat > "$CHANGELOG_FILE" << 'EOF'
<changelog content from Phase 3>
EOF
myk-claude-tools release create {owner}/{repo} {tag} "$CHANGELOG_FILE" [--prerelease] [--draft] [--target {target_branch}]
Inputs
| Input | Required | Description |
|---|---|---|
OWNER/REPO |
Yes | Repository in owner/repo format. |
TAG |
Yes | Release tag, usually something like v1.2.0. |
CHANGELOG_FILE |
Yes | Path to a file containing the release notes. The file must already exist. |
--prerelease |
No | Marks the release as a prerelease. |
--draft |
No | Creates the release as a draft. |
--target BRANCH |
No | Target branch passed through to GitHub. |
--title TEXT |
No | Release title. If omitted or blank, the tag is used as the title. |
Behavior
- The command validates that
OWNER/REPOlooks likeowner/repo. - It validates that
CHANGELOG_FILEexists before callinggh. - It runs
gh release createwith a 300-second timeout. - If
ghprints a release URL, that URL is returned. If not, the CLI constructs the standard GitHub release URL from the repo and tag. - The success payload echoes
prereleaseanddraft, but it does not echotargetortitle.
Warning:
release createhas real side effects. It creates a GitHub release in the repository named byOWNER/REPOusing your currentghauthentication and GitHub context.Note: A tag that does not look like
vX.Y.ZorvX.Y.Z-suffixonly triggers a warning on stderr. The command still attempts to create the release.Tip:
release createis independent. If you already have a tag and a changelog file, you can use it without running the other release commands first.
JSON output
| Field | Appears when | Type | Meaning |
|---|---|---|---|
status |
Always | string |
success or failed. |
tag |
Success | string |
Tag used for the release. |
url |
Success | string |
GitHub release URL, either extracted from gh output or constructed by the CLI. |
prerelease |
Success | boolean |
Whether the release was created as a prerelease. |
draft |
Success | boolean |
Whether the release was created as a draft. |
error |
Failure | string |
Why the command failed, such as a missing gh installation, invalid repo format, missing changelog file, or gh release create failure. |