Command Reference¶
This document provides a complete reference for all Zaojun command-line options and arguments.
Command Syntax¶
Arguments¶
PYPROJECT_TOML¶
Type: Path (optional)
Default: ./pyproject.toml
Description: Path to the pyproject.toml file to check
Examples:
# Check current directory
zaojun
# Check specific file
zaojun /path/to/project/pyproject.toml
# Check file with different name
zaojun dependencies.toml
Configuration File¶
Zaojun reads defaults from a [tool.zaojun] section in the same pyproject.toml it is
checking. CLI flags always take priority over config values.
Supported keys¶
| TOML key | CLI equivalent | Type | Default |
|---|---|---|---|
short |
--short |
boolean | false |
groups |
--groups |
boolean | false |
compat-ok |
--compat-ok |
boolean | false |
cache |
--cache |
boolean | false |
cache-stats |
--cache-stats |
boolean | false |
min-age |
--min-age |
integer | 0 |
library |
--library |
boolean | false |
format |
--format |
string | "text" |
index-url |
--index-url |
string | "https://pypi.org/pypi" |
flag-major |
--flag-major |
boolean | true |
major-ok |
--major-ok |
boolean | false |
vuln-ignore |
(config only) | list of strings | [] |
--clear-cache is intentionally absent — it is a one-shot action that does not make
sense as a persistent default.
Example¶
[tool.zaojun]
cache = true
groups = true
min-age = 7
vuln-ignore = [
"requests", # ignore all advisories for requests
"pillow == 10.3.0", # ignore only when PyPI latest is exactly 10.3.0
"urllib3 < 2.0", # ignore when latest is in this range
"CVE-2024-35195", # ignore this CVE across all packages
"GHSA-gc5v-m9x4-r6x2", # ignore by GHSA ID
"PYSEC-2024-001", # ignore by OSV ID
]
Running zaojun with this config is equivalent to zaojun --cache --groups --min-age 7
(plus the vulnerability ignore rules applied at runtime).
Precedence¶
CLI flags always override config values, including --no-X negations. Passing
--no-cache on the command line disables caching even when cache = true is set in
[tool.zaojun].
Warnings¶
Unknown keys or type mismatches in [tool.zaojun] emit a warning to stderr and are
ignored. They do not cause a non-zero exit code.
Options¶
Vulnerability Scanning¶
zaojun automatically checks for known security advisories using data that is already present in the PyPI JSON response — no additional HTTP requests are made.
Output¶
When a package has open (non-withdrawn) advisories, its dependency line gains a 🔒
indicator, and a Vulnerabilities section is appended after the main report:
⚠️ requests: ~=2.28.0 → Latest: 2.32.3 🔒 1 vuln
✅️ httpx~=0.28.1 is up to date
Vulnerabilities
───────────────
requests
PYSEC-2024-xxx (CVE-2024-35195)
Fixed in: 2.32.0
Verify that cert verification is enforced for redirect targets using HTTPS.
The Vulnerabilities block is suppressed by --short; the 🔒 inline indicator is
always shown when vulns are present (even in --short mode).
Packages with open advisories set exit code 1, just like version updates.
vuln-ignore (config only)¶
Suppress specific advisories by adding a vuln-ignore list to [tool.zaojun].
Two entry shapes are supported:
Vuln-ID entries (prefix CVE-, GHSA-, PYSEC-): match a single advisory by
its primary ID or any alias, across all packages:
Package entries (package name + optional version specifier): suppress all advisories for a package, optionally only when the PyPI-latest version satisfies the specifier:
vuln-ignore = [
"requests", # unconditional — suppress forever
"pillow == 10.3.0", # re-alert when PyPI ships 10.3.1+
"urllib3 >= 1.0, < 2.0",
]
The version in package entries is matched against the latest version on PyPI (the
same value shown in the report), not the installed version. This gives a natural
"re-check on next release" behaviour: a == X.Y.Z rule stops suppressing as soon as
a newer release appears.
Invalid entries (parse errors) emit a warning to stderr and are skipped — they do not hard-fail a run.
--short, --no-short¶
Type: Boolean flag
Default: --no-short (show full output)
Description: Show only the shortest possible output
When enabled (--short):
- Only shows dependencies that need updates
- Omits "up to date" messages
- Omits section headers
- Useful for scripts and CI/CD pipelines
Examples:
# Full output (default)
zaojun
# Output: Shows all dependencies with status
# Short output
zaojun --short
# Output: Only shows packages needing updates
--groups, --no-groups¶
Type: Boolean flag
Default: --no-groups (check only main dependencies)
Description: Check dependencies in all dependency groups
When enabled (--groups):
- Checks [project.dependencies] section
- Checks all [dependency-groups] sections
- Shows each group separately in output
- Useful for projects with development, test, or documentation dependencies
Examples:
# Check only main dependencies (default)
zaojun
# Output: Only checks [project.dependencies]
# Check all dependency groups
zaojun --groups
# Output: Checks [project.dependencies] and all [dependency-groups]
--compat-ok, --no-compat-ok¶
Type: Boolean flag
Default: --no-compat-ok (compatible updates cause exit code 1)
Description: Treat compatible version updates as acceptable
When enabled (--compat-ok):
- Compatible updates (⚠️) don't cause exit code 1
- Only incompatible updates (❌) cause exit code 1
- Useful during development or in CI/CD where you want to allow compatible updates
Examples:
# Default: All updates cause exit code 1
zaojun
# Exit code: 1 if any ⚠️ or ❌ updates
# Compatible updates don't cause errors
zaojun --compat-ok
# Exit code: 1 only if ❌ updates, 0 if only ⚠️ updates
--cache, --no-cache¶
Type: Boolean flag
Default: --no-cache (caching disabled)
Description: Enable caching of PyPI API responses
When enabled (--cache):
- PyPI API responses are cached locally for 24 hours
- Subsequent runs use cached data for faster execution
- Cache is stored in ~/.cache/zaojun/pypi_cache/
- Useful for repeated checks during development
Examples:
# Default: No caching (backward compatible)
zaojun
# Always fetches fresh data from PyPI
# Enable caching for faster repeated runs
zaojun --cache
# First run: Fetches from PyPI and caches results
# Subsequent runs: Uses cached data (much faster)
# Explicitly disable caching
zaojun --no-cache
# Always fetches fresh data from PyPI
--clear-cache, --no-clear-cache¶
Type: Boolean flag
Default: --no-clear-cache (preserve cache)
Description: Clear all cache entries before checking
When enabled (--clear-cache):
- All cached PyPI API responses are deleted
- Fresh data is fetched from PyPI
- Cache statistics are reset
- Useful when you want to force fresh data or troubleshoot cache issues
Examples:
# Clear cache and check dependencies
zaojun --clear-cache
# Output: "Cleared X cache entries" then normal output
# Clear cache with caching enabled
zaojun --cache --clear-cache
# Clears cache, then fetches fresh data and caches it
# Clear cache with groups
zaojun --groups --clear-cache
# Clears cache, then checks all dependency groups
--cache-stats, --no-cache-stats¶
Type: Boolean flag
Default: --no-cache-stats (don't show statistics)
Description: Show cache statistics after checking
When enabled (--cache-stats):
- Shows cache hit/miss statistics
- Displays cache configuration and status
- Useful for monitoring cache effectiveness
- When combined with --short, a warning is emitted to stderr and stats are suppressed
Examples:
# Show cache statistics
zaojun --cache-stats
# Output: Normal output followed by cache statistics
# Enable caching and show statistics
zaojun --cache --cache-stats
# Output: Normal output with cache hits/misses
# Clear cache and show statistics
zaojun --clear-cache --cache-stats
# Output: Shows cleared entries, normal output, then statistics
--library, --no-library¶
Type: Boolean flag
Default: --no-library (application mode)
Description: Enable library mode: check constraint hygiene and flag only incompatible updates
Library mode is designed for Python packages that are consumed by other packages. It runs two checks per dependency:
- Constraint hygiene (local, no PyPI needed): flags version specifiers that are too restrictive for a library:
- Exact pins (
==X.Y.Z) — blocks all other versions for downstream consumers - Patch-level compatible releases (
~=X.Y.Z) — too tight; minor-level (~=X.Y) is fine - Tight upper bounds (
<X.Ywhere Y ≠ 0) — use<X(major boundary) instead -
No specifier at all — warns that consumers get no minimum guarantee
-
Incompatible staleness (PyPI): flags dependencies where the latest version falls outside the allowed range (e.g.
~=1.0when2.xis out). Compatible updates — where the latest version already satisfies the spec — are always silent in library mode regardless of--compat-ok.
--min-age works normally in library mode and applies to incompatible updates.
Examples:
# Check a library's pyproject.toml
zaojun --library
# Library check with supply-chain quarantine
zaojun --library --min-age 7
# Library check covering all dependency groups
zaojun --library --groups
# Output examples:
# ❌ pydantic: exact pin (==2.5.0) blocks consumers
# ❌ httpx: patch-level compatible release (~=0.27.2) is too tight for a library
# ❌ packaging: tight upper bound (<25.0) — use <26 instead
# ⚠️ requests: no version constraint — consumers get no minimum guarantee
# ❌ typer: ~=0.9.0 → Latest: 1.2.0 (incompatible staleness)
# ✅️ cyclopts>=2.0 is up to date
--flag-major, --no-flag-major¶
Type: Boolean flag
Default: --flag-major (major-bump detection enabled)
Description: Flag compatible updates that cross a major version boundary with 💥
When the latest version satisfies your spec but has a higher major version than the one
your spec implies (e.g. spec >=2.0, latest 3.0.0), zaojun emits 💥 instead of ⚠️.
This only fires for compatible updates; incompatible updates remain ❌ regardless.
CalVer note: Packages that use full-year versioning (YYYY.x, e.g. black, pip,
certifi) are automatically excluded — a year increment is not a breaking-change signal.
Short-year schemes (24.x, 25.x) are indistinguishable from numeric major versions and
are not auto-detected; use --no-flag-major or flag-major = false in [tool.zaojun]
to suppress false positives for those packages.
Use --major-ok if you want to see 💥 without failing CI.
Examples:
# Disable major-version detection (major bumps appear as ⚠️)
zaojun --no-flag-major
# Persistent default in config
# [tool.zaojun]
# flag-major = false
--major-ok, --no-major-ok¶
Type: Boolean flag
Default: --no-major-ok (💥 triggers exit code 1)
Description: Show 💥 for major-version bumps but do not exit with code 1
Mirrors --compat-ok for compatible updates: the 💥 signal is still displayed so nothing
is silently hidden, but the exit code stays 0.
Interaction table:
| Flags | 💥 displayed | Exit code |
|---|---|---|
| default | yes | 1 |
--major-ok |
yes | 0 |
--no-flag-major |
no (shown as ⚠️) | n/a |
--compat-ok alone |
yes | 1 (compat-ok does not affect major_update) |
When to use:
-
Deliberate deferral — your team has triaged a major bump (e.g. Django 4→5 requires a migration sprint) and doesn't want CI failing every day for something already on the backlog.
--major-okkeeps 💥 visible in output without blocking. -
Routine major-bump tracking — projects that actively follow major releases and handle them via a dedicated process. The 💥 signal is informative but should never gate a deploy.
Contrast with --no-flag-major: that suppresses the signal entirely (major bumps become
⚠️). Use --major-ok when you want visibility without blocking; use --no-flag-major
when you've consciously decided not to track major bumps at all.
Examples:
# See major bumps without blocking CI
zaojun --major-ok --cache
# Persistent default in config
# [tool.zaojun]
# major-ok = true
--min-age, --min-age N¶
Type: Integer
Default: 0 (age check disabled)
Description: Ignore updates younger than N days (supply-chain quarantine)
When set to a positive integer: - Updates released fewer than N days ago show ⏳ instead of ⚠️/❌ - These packages do not trigger exit code 1 - Useful for reducing exposure to compromised packages in the window before the community reacts - If the release date is unavailable (old cache entry), the age check is skipped gracefully
Examples:
# Ignore updates less than 7 days old
zaojun --min-age 7
# Stricter quarantine: wait 30 days
zaojun --min-age 30 --groups
# Example output when a package is too new:
# ⏳ requests: 2.32.0 is only 2 day(s) old (min-age: 7)
--format¶
Type: String
Default: text
Allowed values: text, json
Description: Select output format
When set to json, all results are printed as a single JSON object to stdout instead of
human-readable text. The JSON format is stable and suitable for scripting and CI pipelines.
JSON output shape:
{
"dependencies": [
{"name": "requests", "spec": "==2.28.0", "latest": "2.28.0", "status": "up_to_date",
"vulnerabilities": [
{"id": "PYSEC-2024-xxx", "aliases": ["CVE-2024-35195"],
"fixed_in": ["2.32.0"], "details": "...", "link": "https://osv.dev/..."}
]},
{"name": "flask", "spec": "~=2.3.0", "latest": "3.0.0", "status": "incompatible_update"}
],
"groups": {"dev": [...]},
"needs_update": false
}
groups is only present when --groups is used. --short has no effect in JSON mode.
vulnerabilities is only present on records that have open (non-ignored) advisories.
Status values:
| Status | Meaning |
|---|---|
up_to_date |
On the latest version (or compatible update in library/compat-ok mode) |
incompatible_update |
Newer version available that breaks the version spec |
compatible_update |
Newer version available that satisfies the spec |
major_update |
Latest is a major-version bump relative to the spec's lower bound; satisfies the spec but signals a potentially breaking upgrade. Includes needs_update: true unless --major-ok |
too_new |
Update quarantined by --min-age; also includes age_days and min_age fields |
error |
Parse or network error; also includes an error field with the message |
Examples:
# Machine-readable output
zaojun --format json
# Parse with jq
zaojun --format json | jq '.needs_update'
# Filter to only outdated packages
zaojun --format json | jq '[.dependencies[] | select(.status != "up_to_date")]'
# Set as persistent default in config
# [tool.zaojun]
# format = "json"
--index-url¶
Type: String
Default: https://pypi.org/pypi
Description: Base URL of a PyPI-compatible JSON API index
Use this option to point zaojun at a private package index such as Artifactory, devpi,
or a corporate PyPI mirror. The index must implement the PyPI JSON API at
{index-url}/{package}/json.
Cache note: The cache key is based on package name only and does not include the index URL. If you switch between indexes for the same package name, run
--clear-cachebetween runs to avoid stale results.
Examples:
# Private Artifactory repository
zaojun --index-url https://artifactory.example.com/artifactory/api/pypi/pypi-local/pypi
# devpi server
zaojun --index-url https://devpi.example.com/root/pypi
# Set as persistent default in config
# [tool.zaojun]
# index-url = "https://my.private.index/pypi"
--help, -h¶
Type: Boolean flag Description: Show help message and exit
Displays usage information, available options, and examples.
Example:
Cache Management¶
Zaojun includes a powerful caching system to improve performance for repeated dependency checks.
Cache Location¶
Cache files are stored in a platform-appropriate location:
- Linux/Unix: ~/.cache/zaojun/pypi_cache/ (respects XDG_CACHE_HOME)
- macOS: ~/Library/Caches/zaojun/pypi_cache/
- Windows: %LOCALAPPDATA%\zaojun\pypi_cache\
Cache Expiration¶
- Cache entries expire after 24 hours (configurable)
- Expired entries are automatically removed on access
- Manual clearing via
--clear-cacheoption
Cache Contents¶
Each cached package includes:
- Package metadata (name, version, release info)
- Upload timestamp (used by --min-age)
- Timestamp for TTL calculation
- Full PyPI response data
Cache Performance¶
- First run with
--cache: Cache misses (fetches from PyPI) - Subsequent runs: Cache hits (uses local data)
- Performance improvement: 10-100x faster for repeated checks
--version¶
Type: Boolean flag Description: Show version information and exit
Displays the current Zaojun version.
Example:
Exit Codes¶
Zaojun uses the following exit codes to indicate results:
| Code | Meaning | Description |
|---|---|---|
0 |
Success | All dependencies are up to date (or only compatible/quarantined updates) with no open advisories |
1 |
Updates needed | Incompatible updates available; compatible updates without --compat-ok; open security advisories; in library mode, also hygiene errors |
2 |
Error | Invalid arguments, file not found, or other errors |
Hygiene warnings (bare dep with no specifier) do not affect the exit code.
Advisories suppressed via vuln-ignore do not affect the exit code.
Environment Variables¶
Zaojun respects the following environment variables:
HTTP_PROXY, HTTPS_PROXY¶
Type: URL Description: Proxy server for HTTP/HTTPS requests
Use these variables if you need to access PyPI through a proxy server.
Example:
NO_PROXY¶
Type: Comma-separated list Description: Hosts that should not use the proxy
Example:
Common Option Combinations¶
CI/CD Pipeline Check¶
- Minimal output for clean logs - Checks all dependency groups - Exit code 1 if any updates neededDevelopment with Caching¶
- Enables caching for faster repeated checks - Shows cache statistics to monitor effectiveness - Checks all dependency groups - Ideal for development workflowsCache Management¶
- Clears existing cache entries - Enables caching for future runs - Shows cache statistics - Useful for forcing fresh dataDevelopment Environment¶
- Checks all dependencies - Allows compatible updates - Enables caching for faster repeated checks - Warns about incompatible updatesSupply-Chain Quarantine¶
- Suppresses updates released in the last 7 days - ⏳ shown for quarantined packages (exit code stays 0) - Combine with--cache for fast repeated checks
Library Hygiene Check¶
- Flags exact pins, patch-level compatible releases, and tight upper bounds - Compatible updates are silent (no PyPI noise for open-range specs) - Exit code 1 on any hygiene error or incompatible updatePrivate Index Check¶
- Queries the private index for all dependency groups - Combine with--cache for faster repeated checks
- If switching between indexes, use --clear-cache to avoid stale results
Aware of Major Bumps but Not Blocked¶
- 💥 shown for major-version bumps, but exit code stays 0 - Useful when a major bump is already on the backlogSuppress Major-Bump Detection Entirely¶
- Major-version bumps are treated as ordinary compatible updates (⚠️) - Use when you've deliberately decided not to track major bumps at allLibrary Check with Quarantine¶
- Full library hygiene + staleness check - Recent incompatible releases are quarantined (⏳) - Cached for fast CI runsQuick Status Check¶
- Fast, minimal output - Quick overview of update status - Enables caching for repeated checks - Easy to parse in scriptsComprehensive Check¶
- Full detailed output - Checks everything - Enables caching for performance - Shows cache statistics - Complete dependency statusOption Precedence¶
When multiple options conflict or interact:
- File path is always processed first
- Output format (
--short) affects all output - Scope (
--groups) determines what to check - Tolerance (
--compat-ok) affects exit code
Examples with Multiple Options¶
Complete Project Check¶
- Checks specific file - Includes all dependency groups - Compatible updates don't cause errors - Enables caching for faster future checksScript-Friendly Output¶
- Minimal, parseable output - Includes all groups - Enables caching for performance - Clear exit code for automationDevelopment Workflow with Caching¶
# Initial check with caching
zaojun --groups --cache --cache-stats
# If updates needed, check with compat-ok
zaojun --groups --compat-ok --cache
# Update if only compatible updates
zaojun --short --compat-ok --cache
if [ $? -eq 0 ]; then
uv sync -U --all-groups
fi
# Clear cache periodically
zaojun --clear-cache --cache-stats
Cache Option Interactions¶
Cache options interact with other options in specific ways:
--cachewith--clear-cache: Cache is cleared, then new data is fetched and cached--cache-statswith--short: A warning is emitted to stderr; statistics are suppressed--no-cachewith--clear-cache: Cache is cleared, but no new data is cached--cachewith network errors: Falls back gracefully, doesn't affect cached data
Deprecated Options¶
No options are currently deprecated. All options shown here are supported in the current version.
Version Compatibility¶
- Cache options: Available in Zaojun 1.0.0 and later
- Other options: Available in Zaojun 0.9.0 and later
- Earlier versions: May not support cache options
Version History¶
- 1.5.0: CVE/vulnerability scanning — 🔒 inline indicator +
Vulnerabilitiesdetail block;vuln-ignoreconfig list to suppress by ID or package/version - 1.5.0:
--flag-major(default on) flags compatible major-version bumps with 💥;--major-okopts out of exit code 1 - 1.5.0:
--index-urlfor querying private PyPI-compatible indexes (Artifactory, devpi, etc.) - 1.3.0:
--librarymode for library constraint hygiene and incompatible-only staleness checks - 1.2.0:
--min-ageflag for supply-chain quarantine; upload time stored in cache - 1.0.0: Initial cache implementation with TTL-based expiration
Related Commands¶
zaojun vs pip list --outdated¶
- Zaojun: Checks against version constraints in
pyproject.toml - pip: Shows all installed packages with newer versions available
zaojun vs uv pip compile --upgrade¶
- Zaojun: Reports what updates are available, supports caching
- uv pip compile: Generates updated lock files
zaojun Cache vs Other Tools¶
- Zaojun cache: Project-specific, respects version constraints
- pip cache: Package installation cache
- HTTP cache: General HTTP response caching
Getting Help¶
For more information or to report issues:
- Run
zaojun --helpfor command-line help - Visit the Codeberg repository for documentation
- Check the issue tracker for known issues
See Also¶
- Basic Usage - Fundamental usage patterns
- Examples - Real-world use cases
- Installation - Installation instructions