Automation scripts, CI pipelines, and package managers all query --version to verify which release is installed before running. Without a working version flag, a script cannot confirm it's using the correct build, which leads to silent version mismatches in production. A hardcoded version string that drifts from package.json (or pyproject.toml / Cargo.toml) compounds the problem: tools report a version they are not. ISO 25010:2011 usability.learnability directly penalizes discoverable interfaces that omit this basic contract.
High because a missing or stale `--version` flag breaks automated upgrade checks and CI gating, causing silent version drift in production.
Wire the version flag directly to your package manifest so it can never drift. In commander, read from package.json at startup:
import { readFileSync } from 'fs'
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
program.version(pkg.version, '-v, --version')
In click, pull from importlib.metadata:
from importlib.metadata import version
@click.group()
@click.version_option(version=version('my-tool'))
def cli(): pass
In cobra, set the version at build time via ldflags so it never needs a runtime read:
var rootCmd = &cobra.Command{Version: version}
ID: cli-quality.command-structure.version-flag
Severity: high
What to look for: List all entry points for the CLI. For each, check that --version (and ideally -v or -V) outputs the version string to stdout and exits with code 0. In commander, check for .version() call. In yargs, check for .version(). In click, check for @click.version_option(). In cobra, check the Version field on the root command. In clap, check for #[command(version)] or .version().
Pass criteria: Running with --version outputs a version string (just the version number or tool-name vX.Y.Z) to stdout and exits 0. The version value should come from package.json, pyproject.toml, Cargo.toml, or a version constant — not be hardcoded as a duplicate string — at least 1 --version flag must output a semver-compatible version string. Report: "X entry points found, all Y respond to --version."
Fail criteria: No --version flag is registered, or the version is hardcoded as a string literal that could drift from the package version, or --version writes to stderr instead of stdout.
Skip (N/A) when: All checks skip when no CLI entry point is detected.
Detail on fail: "No .version() call on the commander program — --version flag not available" or "Version is hardcoded as '1.2.0' string literal instead of reading from package.json"
Remediation: Users and scripts need to check which version is installed. Wire up the version from your package manifest:
// commander (Node.js)
import { readFileSync } from 'fs'
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
program.version(pkg.version, '-v, --version')
# click (Python)
from importlib.metadata import version
@click.group()
@click.version_option(version=version("my-tool"))
def cli():
pass
// cobra (Go) — set at build time via ldflags
var rootCmd = &cobra.Command{
Use: "mytool",
Version: version, // var version string, set by -ldflags
}