CLI Commands¶
Complete reference for every Zenzic command, flag, and exit code.
Command Specification Matrix¶
Select a command tab to view its execution flags, default behaviors, and usage examples.
Version baseline: Zenzic v0.30.0 — all flags verified against uv run zenzic <command> --help.
Run full or targeted static analysis checks across the workspace.
zenzic check is a command group with the following sub-commands:
| Sub-command | Description |
|---|---|
zenzic check links | Check for broken internal links and enforce strict warning policy. |
zenzic check orphans | Detect .md files not listed in the nav. |
zenzic check snippets | Validate Python code blocks in documentation Markdown files. |
zenzic check references | Run the Three-Pass Reference Pipeline: harvest definitions, check integrity, run credential scan. |
zenzic check assets | Detect unused images and assets in the documentation. |
zenzic check placeholders | Detect pages with < 50 words or containing TODOs/stubs. |
zenzic check all | Run all checks: links, orphans, snippets, placeholders, assets, references. |
Flags available on all check sub-commands:
| Flag | Short | Default | Description |
|---|---|---|---|
--format | -f | text | Output format: text, json, or sarif. |
--ci | — | false | Run in CI mode (forces github-annotations output format and --strict). |
--only | — | — | Comma-separated list of Z-Codes to filter. Findings not matching these codes are discarded. |
--show-info | — | false | Show info-level findings (e.g. circular links) in the report. |
Additional flags on check all:
| Flag | Short | Default | Description |
|---|---|---|---|
--strict | -s | false | Treats warnings as errors (exit non-zero on any warning). On check links and check all, also activates external HTTP link validation (Z109). Combine with --no-external to promote warnings without performing network I/O. |
--exit-zero | — | false | Always exit 0; report issues without failing. |
--quiet | -q | false | Minimal one-line output for pre-commit hooks. |
--engine | — | auto | Override the build engine adapter (e.g. mkdocs, zensical). Auto-detected from .zenzic.toml when omitted. |
--exclude-dir | — | — | Additional directories to exclude from scanning (repeatable). |
--include-dir | — | — | Directories to force-include even if excluded by config (repeatable). Cannot override system guardrails. |
--offline | — | false | Force flat URL resolution for offline builds. |
--no-external | — | false | Skip HTTP validation of external URLs (Pass 3). Credential scanner (Z201) always active regardless. |
Additional flags on check references:
| Flag | Short | Default | Description |
|---|---|---|---|
--strict | -s | false | Treat warnings as errors (exit non-zero on any warning). |
--links | -l | false | Also validate external HTTP/HTTPS reference URLs via async HEAD requests. |
Usage Examples:
# Execute full validation suite
zenzic check all
# Run with strict mode (warnings become errors) in CI
zenzic check all --strict --ci
# Export SARIF results for GitHub Code Scanning
zenzic check all --format sarif > zenzic-results.sarif
# Run only credential scanner and link checks
zenzic check all --only Z201,Z104
Compute the weighted Document Quality Score (DQS 0–100) and category breakdown:
| Flag | Short | Default | Description |
|---|---|---|---|
--fail-under | — | 0 | Minimum required score. Fails quality gate (Exit 1) if score falls below threshold. |
--stamp | — | false | Updates README.md status badge with the newly computed DQS score. |
--format | -f | text | Output format: text or json. |
--json | — | false | Shorthand for --format json. Suppresses all rich/text output and emits a single JSON object on stdout. Preferred for programmatic consumers (e.g., editor integrations, shell scripts). |
--strict | -s | false | Includes external HTTP link validation in score calculation. |
--breakdown | — | false | Expands category breakdown showing individual Z-Codes and transparent penalty math. |
--save | — | false | Saves score snapshot to .zenzic-score.json for use with zenzic diff. |
--check-stamp | — | false | Verifies badge stamp files contain the current score URL. Exits 1 if any badge is stale. |
--no-header | — | false | Suppresses the Zenzic banner (set automatically by --ci). |
--ci | — | false | CI shorthand: sets --no-header. |
Usage Examples:
# Compute score and display category breakdown
zenzic score
# Enforce score floor in CI
zenzic score --fail-under 95
# Stamp status badge into README.md
zenzic score --stamp
# Emit machine-readable JSON for programmatic consumers (editor integrations, scripts)
zenzic score --json
# Equivalent long form
zenzic score --format json
JSON Output Schema (--json)
When --json (or --format json) is passed, the command emits a single JSON object on stdout with no rich/text output. Suitable for piping to jq or parsing in editor extensions.
{
"project": "<project-name>",
"score": 98,
"threshold": 0,
"status": "success",
"timestamp": "2026-07-26T16:49:29+00:00",
"categories": [
{ "name": "structural", "weight": 0.30, "issues": 0, "category_score": 1.0,
"contribution": 0.30, "raw_penalty": 0, "is_capped": false },
{ "name": "navigation", "weight": 0.25, "issues": 0, "category_score": 1.0,
"contribution": 0.25, "raw_penalty": 0, "is_capped": false },
{ "name": "content", "weight": 0.20, "issues": 0, "category_score": 1.0,
"contribution": 0.20, "raw_penalty": 0, "is_capped": false },
{ "name": "brand", "weight": 0.25, "issues": 0, "category_score": 1.0,
"contribution": 0.25, "raw_penalty": 0, "is_capped": false }
],
"suppression_count": 2,
"suppression_cap": 30,
"suppression_debt_pts": 2,
"debt_status": "MANAGED DEBT"
}
Possible values of status: success, failing (score < fail_under), security_breach (Z2xx finding detected).
Generate a formal compliance audit report detailing active Policy-as-Code rules, DQS score calculation, technical debt suppressions, baseline drift, and governance posture:
| Flag | Short | Default | Description |
|---|---|---|---|
--format | -f | text | Output format: text (Rich terminal panels, default) or json (deterministic machine-readable compliance payload). |
--strict | -s | false | Treat warnings as errors (exit 1 on any warning). |
--no-external | — | false | Skip HTTP validation of external URLs for air-gapped / offline builds. |
--offline | — | false | Force flat URL resolution for offline builds. |
--only | — | — | Comma-separated list of Z-Codes to include in audit findings. |
--baseline | — | — | Path to custom baseline snapshot file. |
--ci | — | false | Run in CI mode (non-interactive, explicit exit codes). |
Audit Report & Determinism:
- Accepts
--format text(default) for Rich interactive terminal panels and--format jsonfor automated compliance pipelines. - The JSON output is 100% deterministic (timestamps are excluded from the payload hash) to guarantee reproducible compliance builds in CI/CD.
Usage Examples:
Compare current documentation score against the saved snapshot.
| Flag | Short | Default | Description |
|---|---|---|---|
--strict | -s | false | Treat warnings as errors. The score gate is controlled exclusively by --fail-under. |
--format | -f | text | Output format: text or json. |
--threshold | — | 0 | Exit non-zero only if score dropped by more than this many points (0 = any drop). |
--base | — | — | Path to a JSON report file to use as baseline instead of the saved snapshot. |
--no-header | — | false | Suppress the Zenzic banner. |
--ci | — | false | CI shorthand: sets --no-header. |
| Argument | Description |
|---|---|
PATH | Repository root or docs directory to compare (default: configured docs directory). |
Usage Examples:
Show rule metadata, scoring weight, and config genealogy for a rule code.
| Argument / Flag | Description |
|---|---|
RULE_ID (required) | Rule code to explain (e.g. Z101, Z601). |
--path TEXT | Project root to resolve config genealogy (default: current working directory). |
Usage Examples:
Scaffold a Zenzic configuration in the current project.
| Argument / Flag | Default | Description |
|---|---|---|
PATH | CWD | Directory to initialize (default: current project root). |
--plugin NAME | — | Generate a starter Python package for a Zenzic plugin rule. |
--force / -f | false | Overwrite an existing plugin scaffold when used with --plugin. Not supported for configuration initialization. |
--pyproject | false | Write configuration into pyproject.toml instead of .zenzic.toml. |
--local | false | Create only .zenzic.local.toml (machine-local overlay, gitignored). Use this when cloning a repo that already has .zenzic.toml committed. |
--engine ENGINE | auto | Override the build engine adapter (mkdocs, zensical, standalone). Auto-detected from project files when omitted. |
Usage Examples:
Auto-fix deterministic structural violations.
| Argument / Flag | Default | Description |
|---|---|---|
PATH | docs root | Markdown file or directory to auto-fix. |
--dry-run (default) / --apply | --dry-run | Show unified diff without saving changes (--dry-run, default). Apply fixes directly to files (--apply). |
Usage Examples:
Safely remove unused documentation files.
zenzic clean is a command group with the following sub-command:
| Sub-command | Description |
|---|---|
zenzic clean assets | Delete unused images and assets from the documentation. |
Usage Examples:
Run the fast pre-commit secret guard for Markdown/MDX files.
zenzic guard is a command group with the following sub-commands:
| Sub-command | Description |
|---|---|
zenzic guard scan | Run pre-commit credential scan using built-in signatures and local forbidden patterns. |
zenzic guard init | Create or update .pre-commit-hooks.yaml with the native Secret Guard hook. |
zenzic guard scan flags:
| Flag | Default | Description |
|---|---|---|
--staged | false | Scan only staged Markdown/MDX files from git index (pre-commit fast path). |
--format / -f | text | Output format: text or json. |
zenzic guard init flags:
| Flag | Default | Description |
|---|---|---|
--path TEXT | .pre-commit-hooks.yaml | Path of the pre-commit hooks definition file to create/update. |
Usage Examples:
Inspect the active Zenzic configuration and the origin of each value.
zenzic config is a command group with the following sub-command:
| Sub-command | Description |
|---|---|
zenzic config explain | Show the active configuration and the origin of every value. |
Usage Examples:
Start the Language Server Protocol (ZLS) server over stdio:
| Communication Protocol | Client Compatibility | Description |
|---|---|---|
JSON-RPC 2.0 (stdio) | VS Code, Neovim, Emacs, Zed | Language server process executed by editor extension infrastructure. |
Usage & Diagnostics Examples:
# Verify LSP server response over stdio using an inline JSON-RPC shutdown request (exact byte length 44)
printf 'Content-Length: 44\r\n\r\n{"jsonrpc":"2.0","id":1,"method":"shutdown"}' | zenzic lsp
Interactive TTY Behavior
When zenzic lsp is launched directly in an interactive terminal shell (without stdin piping), it detects a TTY, displays an informational notice on stderr, and waits for Ctrl+C to exit cleanly. Editor clients launch zenzic lsp in background non-TTY pipes.
Output core environment diagnostics to assist in debugging path resolution and runtime configuration issues in CI/CD or tool integrations:
| Flag | Short | Default | Description |
|---|---|---|---|
--json | — | false | Outputs environment diagnostics in a single machine-readable JSON object on stdout. |
Usage Examples:
# Display environment diagnostics in human-readable format
zenzic env
# Emit machine-readable JSON object
zenzic env --json
JSON Output Schema (--json)
When --json is specified, zenzic env emits a single JSON object on stdout reporting the Zenzic version, Python executable path, Zenzic module path, current working directory, and resolved active configuration path.
Shared Execution Flags¶
This section details the specifications and guidelines for Shared Execution Flags within the Zenzic ecosystem.
Global flags¶
These flags control Zenzic's signal-to-noise profile across routine scans, CI gates, and incident response workflows.
--strict¶
--strict controls the pipeline gate, not the display of findings. Zenzic always shows every finding it detects — errors and warnings alike — regardless of this flag. What changes is how warnings affect the exit code:
- Without
--strict: warnings → Exit 0 (pipeline passes). Hard errors still cause Exit 1. - With
--strict: warnings are promoted to blocking errors → Exit 1 (pipeline fails).
When strict mode is active Zenzic prints a STRICT MODE: Warnings have been promoted to errors. line in the report footer, so the CI log is unambiguous even when the same findings would otherwise be non-blocking.
| Command | Effect |
|---|---|
check links --strict | Activates Pass 3: concurrent HTTP HEAD validation of external URLs (Z109) |
check all --strict | Activates external URL validation (Z109) + promotes warnings to errors |
check references --strict | Treats Dead Definitions (unused reference links) as hard errors |
score --strict / diff --strict | Runs link check in strict mode |
The --strict flag enforces rigorous validation: for link checking, it validates external HTTP/HTTPS links via active network requests (which are disabled by default for performance, emitting Z109 on failure); for references, it treats Dead Definitions as fatal errors instead of warnings.
Air-Gapped CI Environments
Combine --strict with --no-external to retain strict warning promotion while disabling network I/O entirely. This is the recommended pattern for offline or air-gapped CI environments where external URL reachability cannot be verified:
This keeps Pass 1 (filesystem resolution) and Pass 2 (internal link graph) fully active. Only Pass 3 (Z109 external HTTP validation) is suppressed.
You can also set strict = true in .zenzic.toml to make it the permanent default.
--ci¶
--ci is a convenience shorthand designed specifically for GitHub Actions pipelines, available on check all, score, and diff. It acts as an implicit non-interactive mode and suppresses the ASCII art header globally (no_header = True).
For check all, it forces two additional behaviors simultaneously:
- Sets
strict = true(warnings promote to errors). - Sets
--format github-annotations(if no other format is specified).
This flag bypasses ZenzicReporter completely, outputting raw ::error:: strings that GitHub Actions parses natively to create inline annotations on pull requests.
--only¶
--only applies a destructive engine-level filter to the Zenzic findings pipeline. It accepts a comma-separated list of Z-Codes. Any findings that do not match the specified codes are silently discarded before being processed by the formatter.
Use this to run highly targeted, isolated checks—for example, if you only want to scan for broken links (Z104) and orphans (Z402) without running the rest of the validations, or if you want to silence everything except credential leaks (Z201).
--exit-zero¶
Always exits with code 0 even when issues are found. All findings are still printed and scored — only the exit code is suppressed. Useful for observation-only pipelines.
Security events are never downgraded by this flag: Exit 2 (credential scanner breach) and Exit 3 (path traversal guard system-path incident) always keep priority over ordinary failures.
You can also set exit_zero = true in .zenzic.toml to make it the permanent default.
--show-info¶
By default, info-level findings are hidden to keep everyday output focused on actionable violations. Use --show-info to surface structural telemetry — non-blocking measurements that inform architectural decisions without signalling defects.
The canonical example is CIRCULAR_LINK (Z106): documentation Knowledge Graphs naturally produce link cycles, and the analyzer tracks them as topological metrics rather than errors. High cycle density on a specific page is a data point for Information Architecture review, not a quality gate trigger.
Available on all zenzic check commands.
--quiet¶
--quiet is available on zenzic check all and is designed for silent builders (pre-commit and CI hooks) that need minimal output.
- Suppresses the rich analysis panel and per-file verbose report.
- Prints a compact one-line summary for error/warning totals.
- Prints an explicit security one-liner for credential scanner findings (Exit 2).
- Still enforces fatal exit behavior, including security priority (
3 > 2 > 1).
--offline¶
--offline is available on check all, check links, and check orphans. It forces all adapters (MkDocs and Zensical) to resolve URLs without use_directory_urls, producing flat .html paths instead of clean directory-based slugs.
Use this flag when linting documentation that will be distributed as static files — for example, bundled onto a USB drive or served over an intranet without a web server.
zenzic check all --offline # flat URL mode: guide/install.md → /guide/install.html
zenzic check links --offline
zenzic check orphans --offline
When active, Zenzic banner displays:
Engine parity
The --offline flag has identical behaviour on MkDocs and Zensical adapters. This ensures Zenzic remains a consistent Structural Custodian regardless of your build engine.
--no-external¶
--no-external is available on check all and check links. Within the link-validator pipeline, it skips Pass 3 — concurrent HTTP HEAD validation of external URLs — while keeping Pass 1 (filesystem and target-map resolution) and Pass 2 (internal link validation) active.
Use this flag in air-gapped or offline development environments where external URL reachability cannot be verified, or as a speed optimisation when external link health is confirmed by other means.
zenzic check all --strict --no-external # enforce structural/quality checks; skip external HTTP
zenzic check links --no-external # internal links only; skip external HTTP checks
When active, the report appends a transparency notice:
Never use in CI
--no-external is a developer scope control, not a CI flag. Omit it in unattended CI pipelines — external link failures are legitimate gate failures. The permanent mechanism for excluding known-unstable URLs is excluded_external_urls in .zenzic.toml.
| Concern | Affected by --no-external? |
|---|---|
| Pass 1 — Filesystem and target-map resolution | ❌ Never skipped |
| Pass 2 — Internal link validation | ❌ Never skipped |
| Pass 3 — External HTTP HEAD requests | ✅ Skipped |
Credential scanner and path traversal guard run in dedicated security checks and are not controlled by --no-external.
--exclude-url¶
--exclude-url <PREFIX> is available on check all and check links. It bypasses external URL validation for any URL that starts with the given prefix — at runtime, without touching .zenzic.toml. The flag is repeatable.
# Suppress a domain whose DNS is not yet live
zenzic check all --strict --exclude-url https://staging.example.com/
# Suppress multiple CI/CD paradox URLs in a single invocation
zenzic check all --strict \
--exclude-url https://my-site.example.com/blog/ \
--exclude-url https://github.com/org/repo/releases/tag/v<version>
Runtime prefixes are merged with any excluded_external_urls entries already present in .zenzic.toml — the two mechanisms co-exist and accumulate.
CI/CD deployment paradox
Use --exclude-url in your CI workflow for URLs referencing published artefacts not yet reachable at build time (e.g. a GitHub Release page, a staging deployment, or a blog post scheduled for future publication). Inject the flag via an environment variable:
Permanent exclusions belong in .zenzic.toml
For URLs that are always unreachable (e.g. GitHub auth pages, rate-limited private APIs), use excluded_external_urls in .zenzic.toml — that list is version-controlled and auditable. Reserve --exclude-url for transient deployment-time paradoxes.
--exclude-dir / --include-dir¶
Available on zenzic check all (and individual sub-commands). These flags provide one-shot directory scope overrides per invocation without touching .zenzic.toml:
| Flag | Effect |
|---|---|
--exclude-dir DIR | Skip this directory during the scan (repeatable) |
--include-dir DIR | Force-include a directory even if excluded by config (repeatable) |
--include-dir cannot override system guardrails (Level 1a/1b exclusions such as node_modules/ or adapter metadata files).
# Exclude a generated folder for this run only
zenzic check all --exclude-dir build/ --exclude-dir .cache/
# Force-include a directory that was excluded in .zenzic.toml
zenzic check all --include-dir legacy-docs/
--no-color / --force-color¶
These global flags (accepted by all commands) control ANSI output independently of TTY detection.
| Flag | Effect |
|---|---|
--no-color | Strip all ANSI color and style codes from output |
--force-color | Emit ANSI codes even when stdout is not a TTY |
Environment variables:
| Variable | Equivalent to |
|---|---|
NO_COLOR (any value) | --no-color |
FORCE_COLOR (any value) | --force-color |
NO_COLOR conforms to the NO_COLOR standard convention (no-color.org). When both NO_COLOR and FORCE_COLOR are set, --no-color / NO_COLOR always wins.
Default behaviour: Zenzic uses Rich's TTY auto-detection. Colors are active when stdout is a terminal; they are stripped automatically when piped or redirected — no flag required.
# Strip color: CI log aggregators, plain-text files
zenzic check all --no-color
NO_COLOR=1 zenzic check all
# Force color: CI systems that support ANSI but do not report a TTY
zenzic check all --force-color
FORCE_COLOR=1 zenzic check all
# Pair with --format json for fully machine-readable output
zenzic check all --no-color --format json > report.json
Initialization¶
zenzic init # Scaffold .zenzic.toml in the current project
zenzic init ../new-project # Initialize a remote directory (creates it if needed)
zenzic init --pyproject # Write config into pyproject.toml [tool.zenzic]
zenzic init --force # Overwrite existing config without prompting
zenzic init --local # Scaffold only .zenzic.local.toml (machine-local overlay)
zenzic init --plugin plugin-scaffold-demo # Scaffold a plugin SDK package
Smart detection — when pyproject.toml exists in the project root, zenzic init asks whether to embed the configuration there as a [tool.zenzic] table instead of creating a separate .zenzic.toml. Pass --pyproject to skip the prompt and write directly into pyproject.toml.
Nomad mode — zenzic init <path> treats the given path as the target project root. The directory is created if it does not exist. The caller's CWD is not affected.
Engine auto-detection is included in both modes: if mkdocs.yml or zensical.toml is present, the generated configuration pre-sets the engine field accordingly. When no engine config file is found, standalone (engine-agnostic) defaults apply.
zenzic init --plugin <name> generates a Python package skeleton with a ready zenzic.rules entry-point and a BaseRule template (src/<module>/rules.py). It also includes a minimal docs fixture so the generated project can immediately run zenzic check all as a smoke test.
Governance-Ready Blueprint¶
zenzic init generates a Governance-Ready configuration pair:
.zenzic.toml(shared constitution, versioned).zenzic.local.toml(machine-local sanctuary, git-ignored)
The global file is not an empty shell: it is a governance-ready blueprint with didactic comments, active CAP defaults, and a direct playbook pointer.
# SPDX-FileCopyrightText: 2026 [Your Name] <[Your Email]>
# SPDX-License-Identifier: Apache-2.0
# --- PROJECT IDENTITY ---
# [project]
# name = "My Awesome App" # Used for personalized CLI Governance headers
# --- CORE SETTINGS ---
docs_dir = "docs"
strict = true
fail_under = 100
# --- ENGINE CONTEXT ---
[build_context]
engine = "zensical" # Supported: mkdocs, zensical, standalone
base_url = "/"
default_locale = "en"
# --- BRAND INTEGRITY ---
[project_metadata]
release_name = "MyRelease"
[governance]
# Maximum allowed architectural debt (inline + per-file suppressions).
# Default: 30. Build fails if exceeded.
suppression_cap = 30
suppression_cap_fail_hard = true
# Terms that should no longer appear in your documentation.
brand_obsolescence = ["OldProduct", "LegacyTerm"]
# Governance Playbook:
# /developers/how-to/release-governance-protocol
# --- I18N PARITY (Optional) ---
# [i18n]
# enabled = true
# base_lang = "en"
# base_source = "docs"
# strict_parity = true
# [i18n.targets]
# it = "docs-it"
# --- GATE 4: CI/CD (GitHub Actions, Optional) ---
# Add this workflow snippet to .github/workflows/zenzic.yml
#
# name: zenzic
# on: [pull_request, push]
# jobs:
# zenzic-check:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: actions/setup-python@v5
# with:
# python-version: '3.12'
# - run: pipx run zenzic check all --strict
When suppression_cap_fail_hard = true and active suppressions exceed the CAP, the GitHub Actions job summary renders:
Local Sanctuary (.zenzic.local.toml)¶
zenzic init also scaffolds a didactic local overlay used for private workstation overrides. This file is never intended for commit and is automatically protected via .gitignore in Git repositories.
# --- ZENZIC LOCAL OVERRIDES ---
# This file is machine-local and must stay in .gitignore.
# Values declared here override shared config for your workstation only.
[core]
# docs_dir = "my/custom/path/to/docs"
# Z204 Privacy Gate (local secret terms, literal and case-insensitive).
# forbidden_patterns = ["Project Titan", "internal-api.corp", "staging.acme.io"]
forbidden_patterns = []
[governance]
# suppression_cap = 100
# suppression_cap_fail_hard = false
[secrets]
# Store API tokens here (never in shared .zenzic.toml).
# github_pat = "YOUR_GITHUB_PAT"
[debug]
# log_level = "DEBUG"
[env]
# ZENZIC_FORCE_COLOR = "true"
Best practice¶
Uncomment [project].name in the generated file to personalize Governance headers in CLI output. If pyproject.toml or package.json already contains a project name, zenzic init auto-injects that name as the commented hint.
Keep secrets and machine-specific overrides in .zenzic.local.toml only. Use .zenzic.toml only for team policy and reproducible CI rules.
After generation, first run:
You should immediately see your first clean audit badge.
Autofix & Cleanup¶
zenzic fix # Auto-fix structural violations (e.g. Z108) with a dry-run diff
zenzic fix --apply # Apply fixes directly to files via atomic file writes
zenzic clean assets # Delete unused assets interactively (prompt before each)
zenzic clean assets -y # Delete unused assets immediately (no prompt)
zenzic clean assets --dry-run # Preview what would be deleted without deleting
Zenzic is read-only by default. Auto-fixing is an explicit, opt-in operation protected by atomic file writes. The zenzic fix command performs a safe, memory-only dry run by default and outputs a unified diff. Explicitly passing --apply commits the changes to disk. All modifications use an Atomic Write Barrier to guarantee file integrity (if a crash occurs mid-write, the original file is never corrupted).
Currently, zenzic fix supports auto-fixing:
- Z108 (EMPTY_LINK_TEXT): Injects a placeholder label for empty link text.
- Z505 (UNTAGGED_CODE_BLOCK): Injects default
textlanguage specifier for untagged fenced code blocks. - Z603 (DEAD_SUPPRESSION): Cleanly extracts dead/unused inline suppression comments (
<!-- zenzic:ignore: Zxxx -->) anddata-zenzic-ignoreHTML attributes without corrupting the surrounding text.
zenzic clean assets respects excluded_assets, excluded_dirs, and excluded_build_artifacts from .zenzic.toml — it will never delete files that match these patterns.
Exit codes¶
| Code | Meaning |
|---|---|
0 | All selected checks passed (or --exit-zero was set) |
1 | One or more checks reported issues |
2 | SECURITY CRITICAL — credential scanner detected a leaked credential |
3 | SECURITY INCIDENT — Path Traversal Guard: link targets an OS system directory |
Exit code 2 is reserved for security events
Exit code 2 is issued by zenzic check references and zenzic check all when the credential scanner detects a known credential pattern embedded in a reference URL. It is never used for ordinary check failures. If you receive exit code 2, treat it as a build-blocking security incident and rotate the exposed credential immediately.
Exit code 3 — Path Traversal Guard Incident
Exit code 3 is issued when the path traversal guard detects a link that resolves to an OS system directory (/etc/, /root/, /var/, /proc/, /sys/, /usr/). Unlike exit code 1, this is a security incident and takes priority over all other exit codes. It is never suppressed by --exit-zero. See Checks: Path Traversal Guard for details.
Each exit code has a distinct visual signature in the Zenzic Report:
Exit 0 — Zenzic Audit Badge¶
This section details the specifications and guidelines for Exit 0 — Zenzic Audit Badge within the Zenzic ecosystem.
Exit 1 — Quality findings¶
This section details the specifications and guidelines for Exit 1 — Quality findings within the Zenzic ecosystem.
Exit 2 — credential scanner security breach¶
JSON output¶
All concrete check subcommands support --format json for machine-readable output.
check all¶
The aggregated report groups findings by check:
{
"links": [],
"orphans": [],
"snippets": [],
"placeholders": [],
"unused_assets": [],
"references": [],
"nav_contract": [],
"suppression_count": 0,
"suppression_cap": 30,
"suppression_debt_pts": 0,
"debt_status": "CLEAN"
}
Each key holds a list of issue strings or objects. An empty list means the check passed. nav_contract validates extra.alternate links in mkdocs.yml against the Virtual Site Map — always empty for non-MkDocs projects.
For the authoritative machine contract (including score --format json and CAP fail-hard payloads), see API JSON Contract.
Individual commands¶
check links, check orphans, check snippets, check references, and check assets each accept --format json and return a uniform findings structure:
{
"findings": [
{
"rel_path": "guides/setup.md",
"line_no": 42,
"code": "Z104",
"severity": "error",
"message": "guides/setup.md:42: 'install.md' not found in docs"
}
],
"summary": {
"errors": 1,
"warnings": 0,
"info": 0,
"security_incidents": 0,
"security_breaches": 0,
"elapsed_seconds": 0.042
}
}
Exit codes are preserved in JSON mode: exit 0 when only warnings are found, exit 1 on errors (or warnings under --strict), exit 2 on credential scanner breaches, exit 3 on path traversal guard path traversal — the same contract as text output.
SARIF output¶
Concrete check subcommands support --format sarif to emit a SARIF-compliant report, ready for direct upload to GitHub Code Scanning.
Machine Silence — Rule R20
When --format sarif (or --format json) is active, all Rich banners and informational panels are suppressed on stdout. Only the machine-readable payload is emitted. This guarantees the output is always valid against the SARIF schema, regardless of terminal state.
Zxxx → SARIF ruleId mapping¶
Every Zenzic finding maps verbatim: the Zxxx code becomes the ruleId. The tool.driver.rules array is populated dynamically — only codes that produced at least one result in the run are declared. Each rule entry carries a helpUri pointing to the anchor in this reference page.
| Finding | ruleId | SARIF level |
|---|---|---|
| Z101 LINK_BROKEN | Z101 | error |
| Z102 ANCHOR_MISSING | Z102 | error |
| Z103 ORPHAN_LINK | Z103 | error |
| Z104 FILE_NOT_FOUND | Z104 | error |
| Z105 ABSOLUTE_PATH | Z105 | error |
| Z106 CIRCULAR_LINK | Z106 | note |
| Z107 CIRCULAR_ANCHOR | Z107 | error |
| Z108 EMPTY_LINK_TEXT | Z108 | error |
| Z110 STALE_ALLOWLIST_ENTRY | Z110 | warning |
| Z111 VIRTUAL_ROUTE_BROKEN | Z111 | error |
| Z113 AUTHOR_KEY_COLLISION | Z113 | error |
| Z114 LARGE_PAGINATION_SET | Z114 | note |
| Z201 CREDENTIAL_SECRET | Z201 | error |
| Z202 PATH_TRAVERSAL | Z202 | error |
| Z203 PATH_TRAVERSAL_FATAL | Z203 | error |
| Z204 FORBIDDEN_TERM | Z204 | error |
| Z301–Z303 Reference Integrity | Z301–Z303 | warning |
| Z401–Z406 Structure | Z401–Z406 | warning |
| Z501–Z505 Content Quality | Z501–Z505 | warning |
| Z601 Governance | Z601 | warning |
| Z901–Z902 System | Z901–Z902 | warning |
| Z906 NO_FILES_FOUND | Z906 | note |
Example SARIF output¶
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "zenzic",
"version": "<version>",
"informationUri": "https://zenzic.dev",
"rules": [
{
"id": "Z104",
"name": "FILE_NOT_FOUND",
"shortDescription": { "text": "File not found" },
"defaultConfiguration": { "level": "error" },
"helpUri": "./finding-codes.md#z104"
},
{
"id": "Z201",
"name": "CREDENTIAL_SECRET",
"shortDescription": { "text": "Credential detected" },
"defaultConfiguration": { "level": "error" },
"helpUri": "./finding-codes.md#z201"
}
]
}
},
"results": [
{
"ruleId": "Z104",
"level": "error",
"message": { "text": "docs/guides/setup.md:42: 'install.md' not found in docs" },
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "docs/guides/setup.md",
"uriBaseId": "%SRCROOT%"
},
"region": { "startLine": 42 }
}
}
]
}
]
}
]
}
For automated upload to GitHub Code Scanning, use the Zenzic GitHub Action — it validates SARIF integrity before upload (truncation guard) and surfaces findings as inline PR annotations.
Engine override¶
The --engine flag overrides the build engine adapter for a single run without modifying .zenzic.toml. Accepted by check orphans and check all:
zenzic check orphans --engine mkdocs
zenzic check all --engine zensical
zenzic check all --engine standalone # disable orphan check regardless of config
If you pass an engine name with no registered adapter, Zenzic lists available adapters and exits with code 1:
ERROR: Unknown engine adapter 'hugo'.
Installed adapters: mkdocs, standalone, zensical
Install a third-party adapter or choose from the list above.
Third-party adapters are discovered automatically once installed — no Zenzic update required. See Writing an Adapter.
Quality scoring¶
Individual checks answer a binary question: pass or fail. zenzic score answers a different one: how healthy is this documentation, and is it getting better or worse over time?
zenzic score # Compute 0–100 quality score
zenzic score --save # Compute and persist snapshot to .zenzic-score.json
zenzic score --stamp # Update audit+score markers in badge_stamp_files
zenzic score --fail-under 80 # Exit 1 if score is below threshold
zenzic score --format json # Machine-readable score report
zenzic score --ci # Run in CI mode (suppresses header)
zenzic score [PATH] # Score a remote project (sovereign root)
zenzic diff # Compare current score against saved snapshot
zenzic diff --threshold 5 # Exit 1 only if score dropped by more than 5 points
zenzic diff --format json # Machine-readable diff report
zenzic diff --ci # Run in CI mode (suppresses header)
zenzic diff [PATH] # Diff a remote project against its saved baseline
How the score is computed¶
Each check category carries a fixed weight that reflects its impact on the reader experience:
| Category | Weight | Rationale |
|---|---|---|
| links | 35 % | A broken link is an immediate dead end for the reader |
| orphans | 20 % | Unreachable pages are invisible — they might as well not exist |
| snippets | 20 % | Invalid code examples actively mislead developers |
| placeholders | 15 % | Placeholder content signals an unfinished or abandoned page |
| assets | 10 % | Unused assets are waste, but they do not block the reader |
Within each category, the score decays linearly: the first issue costs 20 % of the category weight, the second costs another 20 %, floored at zero. A category with five or more issues contributes nothing to the total. The weighted contributions are summed and rounded to an integer.
Regression tracking¶
# On main — establish or refresh the baseline
zenzic score --save
# On every pull request — block documentation regressions
zenzic diff --threshold 5
--threshold 5 gives contributors a five-point margin. Set it to 0 for a strict gate where any regression fails the pipeline.
Minimum score floor¶
Use this when the team has committed to maintaining a defined quality level, regardless of what the score was last week. You can also set fail_under = 80 in .zenzic.toml to make it persistent.
Inline badge stamping¶
Updates both marker types in all files listed in badge_stamp_files (default: README.md):
<!-- zenzic:audit-badge -->→ deterministicpassing/failinggovernance badge<!-- zenzic:score-badge -->→ numeric score badge (0..100) with brand color
The Shields.io badge URL on the line immediately following each marker is replaced in place.
| Color | Hex | Condition |
|---|---|---|
| Indigo | 4f46e5 | Score = 100 |
| Amber | f59e0b | Score ≥ fail_under (passing) |
| Red | ef4444 | Score < fail_under or security override |
The stamp always runs before exit-code checks, so the badge reflects the actual score even when the build fails. When the score is below fail_under locally, the red badge is immediate feedback before the push — it will never appear on main because the CI blocks the commit. See Official Badges for setup and the full CI/CD snippet.
To surface the score without blocking the pipeline:
zenzic check all --exit-zero # full report, exit 0 regardless
zenzic score # show score for visibility
Detailed score breakdown (--breakdown)¶
Use the --breakdown flag to output a detailed category breakdown of occurred Z-Codes (including informational or zero-point codes like Z106 or Z401) and the transparent DQS mathematical formula calculations:
Example output:
DETAILED CATEGORY BREAKDOWN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STRUCTURAL CATEGORY (Weight: 30%, Max: 30.0 pts)
✗ Z106 (CIRCULAR_LINK): 24 occurrence(s) x -0.0 pts = -0.0 pts
Category Raw Penalty: 0.0 pts
Category Net Score: 30.0 / 30.0 pts
NAVIGATION CATEGORY (Weight: 25%, Max: 25.0 pts)
✓ No issues detected
Category Raw Penalty: 0.0 pts
Category Net Score: 25.0 / 25.0 pts
CONTENT CATEGORY (Weight: 20%, Max: 20.0 pts)
✓ No issues detected
Category Raw Penalty: 0.0 pts
Category Net Score: 20.0 / 20.0 pts
BRAND CATEGORY (Weight: 25%, Max: 25.0 pts)
✓ No issues detected
Category Raw Penalty: 0.0 pts
Category Net Score: 25.0 / 25.0 pts
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
DQS MATHEMATICAL TRANSPARENCY
Base Score: 100.0 pts
+ Structural Contribution: +30.0 pts (max 30.0)
+ Navigation Contribution: +25.0 pts (max 25.0)
+ Content Contribution: +20.0 pts (max 20.0)
+ Brand Contribution: +25.0 pts (max 25.0)
─────────────────────────────────────
Category Subtotal: 100.0 / 100.0 pts
- Gravity Cap Loss: -0.0 pts (Brand bucket zeroed cap)
- Technical Debt Penalty: -0.0 pts (0 suppression(s) x -1.0 pt)
─────────────────────────────────────
Final Quality Score: 100 / 100
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Arsenal Inspection¶
zenzic inspect capabilities # Show all built-in scanners, plugin rules, and engine-specific link bypasses
zenzic inspect capabilities shows Zenzic's complete scanner arsenal in two sections:
Section A — Core Scanners (Built-in): scanners compiled into Zenzic itself from the canonical registry. The credential scanner (Z201) and path traversal guard (Z202–203) use dedicated exit codes (2 and 3 respectively) that are never suppressible with --exit-zero.
Section B — Extensible Rules (Plugin System): rules registered via the zenzic.rules entry-point group from any installed third-party package.
Each row in the Extensible Rules table shows the entry-point name and the rule's stable rule_id. It also displays the origin distribution ((core) for built-in rules, or the package name for third-party plugins) alongside the fully qualified Python class name.
Use this command to verify which rules are active after installing a plugin package.
inspect codes — Tiered code registry¶
inspect codes renders the canonical code registry grouped by tier:
coregovernanceplugincustom
The table always uses four columns: Tier, Code, Name, Status.
Governance activation is read from loaded configuration:
Z601is[ACTIVE]when[governance].brand_obsolescenceis non-empty.
For plugin rules, status is [ACTIVE] only when the plugin source is enabled in plugins. Custom rules from custom_rules are shown in the custom tier.
Invalid tiers fail fast with exit code 1:
inspect routes — Site map export¶
zenzic inspect routes
zenzic inspect routes --kind physical
zenzic inspect routes --kind virtual
zenzic inspect routes --json
inspect routes exports the Virtual Site Map as route records. --kind accepts only physical, virtual, or all.
With --json, stdout contains only valid JSON in this shape:
{
"routes": [
{
"url": "/guide/install",
"kind": "physical",
"source_files": ["docs/guide/install.md"],
"digest": "...sha256..."
}
]
}
Field contract:
url: canonical URL.kind:physical,tag,tag_index,pagination,author, orauthor_index.source_files: repo-relative POSIX source paths that activate the route.digest: SHA-256 ofurl + ':' + ','.join(sorted(source_files)).
If --kind is invalid, the command exits 1 and emits the error to stderr when --json is active, preserving JSON purity on stdout.
Interactive Lab¶
zenzic lab is an interactive showcase that runs bundled Z-code gallery scenarios against Zenzic and reports whether each scenario met its expected outcome.
Scenario selection¶
| Syntax | Behaviour |
|---|---|
zenzic lab | Display the gallery menu |
zenzic lab z101 | Run a single Z-code scenario |
zenzic lab all | Run all 5 gallery scenarios in sequence |
zenzic lab --list | Print the gallery index without running |
Gallery¶
| Z-Code | Title | Expects |
|---|---|---|
Z101 | Link Integrity | FAIL |
Z201 | Credential Scanner | BREACH |
Z405 | Asset Integrity | FAIL |
Z601 | Brand Obsolescence | FAIL |
Outcome labels¶
Each scenario declares its expected outcome. After execution, the lab reports whether the expectation was met:
| Label | Meaning |
|---|---|
PASS ✓ | Expected clean run — zero findings |
EXPECTED FAIL ✓ | Expected errors were found |
BREACH ✓ | Expected credential scanner detection |
FAIL (unexpected) | Scenario expected to pass but errors found |
BREACH expected — not triggered | Expected credential scanner hit was not produced |
Examples¶
# Run the credential scanner scenario
zenzic lab z201
# Run the full gallery
zenzic lab all
# Run a single Z-code scenario
zenzic lab z101
# Print the gallery index without running
zenzic lab --list
uvx vs uv run vs bare zenzic¶
| Invocation | Behaviour | When to use |
|---|---|---|
uvx zenzic ... | Downloads and runs in an isolated, ephemeral environment | One-off jobs, pre-commit hooks, CI with no project install phase |
uvx --from zenzic zenzic ... | Runs via uvx with explicit package source | When you want explicit package resolution while staying outside project env |
zenzic ... (bare) | Requires Zenzic on $PATH | Developer machines with a global install |
CI recommendation
Prefer uvx zenzic ... for CI steps that do not already install project dependencies — it avoids adding Zenzic to your production dependency set.