Basic Usage¶
This document covers the fundamental usage patterns for Zaojun, from simple checks to more advanced scenarios including caching for improved performance.
Command Structure¶
The basic Zaojun command follows this pattern:
Where:
- [PYPROJECT_TOML]: Optional path to a pyproject.toml file (defaults to ./pyproject.toml)
- [OPTIONS]: Various command-line options to control behavior
Default Behavior¶
When run without any arguments, Zaojun:
- Looks for
pyproject.tomlin the current directory - Checks all dependencies in the
[project.dependencies]section - Shows detailed output with emoji indicators
- Returns exit code 1 if any updates are needed
Specifying a pyproject.toml File¶
You can check dependencies in any pyproject.toml file:
# Check a specific file
zaojun /path/to/project/pyproject.toml
# Check a file in a parent directory
zaojun ../pyproject.toml
# Check a file with a different name
zaojun my-dependencies.toml
Persistent Defaults via Config¶
Add a [tool.zaojun] section to your pyproject.toml to set defaults that apply on every
run without repeating CLI flags:
Running zaojun with this config is equivalent to zaojun --cache --groups --min-age 7.
CLI flags always override config values — pass --no-cache to disable caching for a
single run even when cache = true is configured.
See the Command Reference for the full list of supported keys and precedence rules.
Caching for Performance¶
Zaojun includes a caching system to improve performance for repeated dependency checks. By default, caching is disabled to maintain backward compatibility.
Enabling Caching¶
# Enable caching for faster repeated checks
zaojun --cache
# Enable caching and show statistics
zaojun --cache --cache-stats
# Clear existing cache and enable caching
zaojun --clear-cache --cache
Cache Benefits¶
- First run with
--cache: Fetches data from PyPI and caches it - Subsequent runs: Uses cached data (10-100x faster)
- Offline capability: Partial functionality when PyPI is unavailable
- Rate limiting: Reduces load on PyPI infrastructure
Cache Management¶
# Show cache statistics
zaojun --cache-stats
# Clear all cache entries
zaojun --clear-cache
# Disable caching (default behavior)
zaojun --no-cache
Cache Location¶
Cache files are stored in:
- Linux/Unix: ~/.cache/zaojun/pypi_cache/
- macOS: ~/Library/Caches/zaojun/pypi_cache/
- Windows: %LOCALAPPDATA%\zaojun\pypi_cache\
Cache entries expire after 24 hours and are automatically cleaned up.
Understanding Version Constraints¶
Zaojun understands various Python version constraint formats:
Exact Versions¶
Version Ranges¶
dependencies = [
"package>=1.0.0", # Version 1.0.0 or higher
"package<2.0.0", # Version less than 2.0.0
"package>=1.0.0,<2.0.0", # Between 1.0.0 and 2.0.0
]
Compatible Releases¶
Multiple Constraints¶
JSON Output¶
Use --format json to get machine-readable output suitable for scripts and CI pipelines:
{
"dependencies": [
{"name": "httpx", "spec": "~=0.28.1", "latest": "0.28.1", "status": "up_to_date"},
{"name": "flask", "spec": "~=2.3.0", "latest": "3.0.0", "status": "incompatible_update"}
],
"needs_update": true
}
The needs_update top-level field mirrors the exit code (true = exit 1). Parse it directly:
zaojun --format json | jq '.needs_update'
# false
zaojun --format json | jq '[.dependencies[] | select(.status != "up_to_date")]'
# [...list of packages needing attention...]
You can also set this as a persistent default in [tool.zaojun]:
Output Interpretation¶
Status Indicators¶
Zaojun uses three types of indicators:
-
✅ Up to date
The latest version on PyPI matches your constraint. -
⚠️ Compatible update available
A newer version exists that satisfies your version constraints. -
💥 Major-version bump available
The latest version satisfies your spec but crosses a major version boundary — likely has breaking changes. Triggers exit code 1 by default; suppress with--major-ok(show 💥 but exit 0) or--no-flag-major(treat as ⚠️). -
❌ Incompatible update available
A newer version exists that does NOT satisfy your version constraints. -
⏳ Update quarantined (too new)
The latest version is newer than your--min-agethreshold. No action required yet.
Example Scenarios¶
Scenario 1: Everything up to date
$ zaojun
Checking dependencies in /home/user/project/pyproject.toml
✅️ httpx~=0.28.1 is up to date
✅️ packaging~=26.0 is up to date
✅️ cyclopts>=2.0.0 is up to date
Scenario 2: Mixed status
$ zaojun
Checking dependencies in /home/user/project/pyproject.toml
✅️ httpx~=0.28.1 is up to date
⚠️ packaging: ~=23.0 → Latest: 24.0
❌ typer: ==0.9.0 → Latest: 1.0.0
Library Mode¶
If you maintain a Python library (a package consumed by other packages), use --library to check that your dependency constraints are appropriate for a library:
Library mode runs two checks for each dependency:
- Constraint hygiene (local, no network): flags specifier styles that create version conflicts for downstream consumers:
pydantic==2.5.0— exact pins block all other versionspydantic~=2.5.3— patch-level compatible release is too tightpydantic>=2.0,<2.5— tight upper bound; use<3(major boundary) instead-
pydantic(bare) — warns that consumers get no minimum guarantee -
Incompatible staleness (PyPI): flags dependencies where the latest version falls outside your allowed range — e.g.,
~=1.0when2.xis current.
Compatible updates are always silent in library mode. If pydantic>=2.0 is your spec and the latest is 2.8, there is nothing to flag — your range already covers it.
--min-age, --groups, --cache, and --short all work with --library.
Supply-Chain Quarantine¶
Supply chain attacks often target the window between a package being published and users installing it. Use --min-age N to skip flagging updates younger than N days:
# Wait 7 days before considering an update actionable
zaojun --min-age 7
# Stricter policy — wait 30 days
zaojun --min-age 30 --groups --cache
Quarantined packages show ⏳ and do not trigger exit code 1. If a package's release date is unknown (e.g. old cache entry), the age check is skipped.
Vulnerability Scanning¶
zaojun automatically surfaces known CVEs and security advisories from the PyPI vulnerability feed. No extra configuration is needed — the data arrives in the same HTTP response already fetched per package (zero additional requests).
When a package has open advisories, its line gains a 🔒 indicator and a detail block appears at the end of the run:
⚠️ requests: ~=2.28.0 → Latest: 2.32.3 🔒 1 vuln
Vulnerabilities
───────────────
requests
PYSEC-2024-xxx (CVE-2024-35195)
Fixed in: 2.32.0
Verify that cert verification is enforced for redirect targets using HTTPS.
Packages with open (non-ignored) advisories set exit code 1.
Suppressing advisories with vuln-ignore¶
Add a vuln-ignore list to [tool.zaojun] to suppress advisories you have already
triaged or cannot immediately fix:
[tool.zaojun]
vuln-ignore = [
"CVE-2024-35195", # specific CVE, all packages
"GHSA-gc5v-m9x4-r6x2", # specific GHSA, all packages
"requests", # all advisories for requests, any version
"pillow == 10.3.0", # suppress only while PyPI latest is 10.3.0
"urllib3 >= 1.0, < 2.0", # suppress for the entire 1.x line
]
The version in package entries is compared against the latest version on PyPI.
A == X.Y.Z entry automatically re-alerts when a newer release appears — no stale
ignore entries.
Addressing Discovered Vulnerabilities¶
When zaojun flags a vulnerability in one of your direct dependencies, update the lower bound in your specifier to require a fixed version:
zaojun only checks packages listed in [project.dependencies] (and
[dependency-groups] when --groups is used). It does not inspect transitive
dependencies — advisories on packages you don't declare directly will not appear in the
report.
Common Patterns¶
Regular Project Maintenance¶
# Check your project regularly with caching for speed
zaojun --cache
# If updates are needed, update your constraints
# Then update your dependencies
uv sync -U --all-groups
# Clear cache periodically for fresh data
zaojun --clear-cache --cache
Development Workflow with Caching¶
# Daily development checks (fast with caching)
zaojun --cache --cache-stats --groups
# Before committing code
zaojun --short --cache
# Force fresh data when needed
zaojun --clear-cache --cache-stats
Checking Before Commits¶
# Run before committing to ensure dependencies are current
zaojun --short --cache
# If you see output, consider updating
Integration with Other Tools¶
# Combine with grep to extract package names needing updates
zaojun --short --cache | grep -E "^[⚠❌]" | cut -d' ' -f2
# Count how many packages need updates
zaojun --short --cache | grep -c -E "^[⚠❌]"
# Check cache effectiveness
zaojun --cache --cache-stats | grep "Hits:"
Working with Different File Structures¶
Monorepo Structure¶
# Check each project in a monorepo
zaojun packages/app/pyproject.toml
zaojun packages/lib/pyproject.toml
zaojun tools/scripts/pyproject.toml
Nested Projects¶
# Check a nested project
zaojun src/backend/pyproject.toml
# Check multiple levels
zaojun ../../shared-lib/pyproject.toml
Temporary Files¶
# Check a generated pyproject.toml
zaojun /tmp/test-deps.toml --cache
# Check from stdin (advanced usage)
cat deps.toml | python -c "
import sys, tempfile, subprocess
with tempfile.NamedTemporaryFile(mode='w', suffix='.toml') as f:
f.write(sys.stdin.read())
f.flush()
subprocess.run(['zaojun', f.name, '--cache'])
"
Error Handling¶
File Not Found¶
Invalid TOML¶
Network Issues¶
$ zaojun
Checking dependencies in /home/user/project/pyproject.toml
❌ Network error for httpx: HTTPStatusError('404 Not Found')
Invalid Dependency Format¶
$ zaojun
Checking dependencies in /home/user/project/pyproject.toml
❌ Error checking 'invalid-package-@-1.0': ValueError("Invalid dependency format 'invalid-package-@-1.0'")
Best Practices¶
- Run Regularly: Check dependencies at least weekly
- Use Caching: Enable
--cachefor faster repeated checks during development - Use in CI: Add to your continuous integration pipeline (consider
--no-cachefor consistency) - Review Before Updating: Understand what changes in new versions
- Test After Updates: Always test your application after dependency updates
- Use Version Pinning: Consider pinning exact versions in production
- Monitor Cache: Use
--cache-statsperiodically to ensure cache effectiveness - Clear Cache: Use
--clear-cachewhen you suspect stale data or after major dependency changes
Next Steps¶
- Learn about Command Reference for all available options
- See Examples for real-world use cases