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 | [] |
check-licenses |
--check-licenses |
boolean | false |
allowed-licenses |
(config only) | list of SPDX strings | [] |
unknown-license |
--unknown-license |
string | "warn" |
license-ignore |
(config only) | list of dicts | [] |
--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¶
License Checking¶
zaojun can verify that every dependency's license is compatible with your project's own license. See the License Checking guide for the full reference.
--check-licenses, --no-check-licenses¶
Type: Boolean flag
Default: --no-check-licenses
Description: Enable license compliance checking. Also enabled automatically when
allowed-licenses is non-empty.
--unknown-license¶
Type: String ("warn" / "fail" / "allow")
Default: "warn"
Description: Controls how zaojun handles dependencies whose license cannot be
determined from PyPI metadata.
allowed-licenses (config only)¶
Type: List of SPDX identifier strings
Default: [] (auto-derive from project.license)
Description: Explicit allowed set. When empty and check-licenses is true, the
allowed set is derived from project.license.
license-ignore (config only)¶
Type: List of dicts, each with package (PEP 508 specifier) and reason (string)
Default: []
Description: Exempt specific packages from license checking. The reason field is
required.
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