Zenable CLI - conformance checking, IDE management, and hook handling for agentic IDEs.The zenable CLI is the native Go binary for conformance checking, IDE management, and hook handling.
Note: You can use unified commands like install cursor or install claude-code, or use subcommands like install mcp cursor and install hook claude-code. The unified commands are simpler and install all features.
Preview what would be done without actually performing the installation
-p, --project
Install in the project directory instead of globally
--include TEXT
Include only directories matching these glob patterns (e.g., '**/microservice-*')
--exclude TEXT
Exclude directories matching these glob patterns
--all
Install for all supported IDEs, even if not currently installed
-h, --help
Show help message
By default, zenable install installs globally so the integration is available across all your projects.
Want project-level installation? Run zenable install --project from inside a git repository to install only for that project. When using --project outside a git repository, the installer will present an interactive TUI to select which repositories to install into.
# Install globally for all detected IDEs (recommended)zenable install# Install for a specific IDE using unified command (recommended)zenable install cursorzenable install claude-code# Install in the current project onlyzenable install --project# Preview what would be done without installingzenable install --dry-run# Advanced: Install only MCP (without hooks) for all detected IDEszenable install mcp# Advanced: Install only MCP for a specific IDEzenable install mcp cursor# Advanced: Install only hookszenable install hookzenable install hook claude-codezenable install hook cursor
Check the provided files against your conformance tests.
zenable check [OPTIONS] [PATTERNS]...
Automatically detects files from IDE context when no patterns are provided.
Supports glob patterns like **/*.py to check all Python files recursively.
Accepts piped input via stdin from git status --short or plain file lists.
Files are processed in batches of 5 for optimal performance.
The check command supports configuration via environment variables:
Environment Variable
Description
Default
ZENABLE_CHECK_BASE_BRANCH
Default base branch to compare against when using --branch
main
Example
# Set default base branch to developexport ZENABLE_CHECK_BASE_BRANCH=develop# Now --branch uses develop instead of mainzenable check --branch# CLI option still overrides env varzenable check --branch --base-branch feature/base
# Check a single filezenable check example.py# Check all Python files recursivelyzenable check '**/*.py'# Check multiple patternszenable check 'src/**/*.js' 'tests/**/*.js'# Pipe git status to check modified/untracked filesgit status --short | zenable check# Pipe a file list from any commandfind src -name '*.py' | zenable check# Exclude test files from checkingzenable check '**/*.py' --exclude '**/test_*.py'# Specify base directory for pattern matchingzenable check '*.py' --base-path ./src# Check all files changed on current branch compared to mainzenable check --branch# Check all files changed on current branch compared to developzenable check --branch --base-branch develop# Check only Python src files changed on current branchzenable check --branch '**/*.py' --exclude '**/test_*.py'# Dry run to see which files would be checkedzenable check '**/*.py' --dry-run# Output results in SARIF format to a file (e.g. for CI integration)zenable check '**/*.py' --format sarif=results.sarif# Output results in JSON format to a filezenable check '**/*.py' --format json=results.json# Output text to terminal and write SARIF + JSON to fileszenable check '**/*.py' --format text,sarif=results.sarif,json=results.json# Output HTML report to a filezenable check '**/*.py' --format html=report.html# Output multiple formats to stdoutzenable check '**/*.py' --format sarif,json# Skip AI review and only run semgrep guardrailszenable check '**/*.py' --skip-ai-review
This command is specifically designed for IDE integrations like Claude Code and Cursor.
It reads hook input from stdin, processes the files, and returns appropriate
exit codes and formatted responses for the IDE to handle.To manually run a scan, use the check command instead.
Reverted files are not reviewed. When an agent modifies a file and then reverts it back to match the base branch (e.g., via git checkout), the hook will report “No files to process” because there is no net change compared to the base branch. This is expected behavior — Zenable reviews the diff, not individual edits, so if the final state matches what’s already on the base branch, there’s nothing new to review.
Fetch and address unresolved review comments on a pull request or merge request.
zenable triage [OPTIONS]
Auto-detects the PR (GitHub) or MR (GitLab) for the current branch and fetches every commentable surface — line-level review threads, PR-level issue comments, and submitted-review summary bodies — in a single XML payload aimed at AI coding agents. By default only comments from the Zenable AI guardrails bot are returned; flags loosen that filter.The default output embeds an <instructions> block telling the agent how to process each thread (commit per thread, push, then reply). Use --reply to post a response to a single thread, or --report-only to emit a read-only research-report prompt that produces no commits, pushes, or replies.
GitHub PR number (auto-detected from current branch if omitted). Mutually exclusive with --mr.
--mr INTEGER
GitLab MR number (auto-detected from current branch if omitted). Mutually exclusive with --pr.
--all-bots
Include comments from all bots, not just the Zenable AI guardrails bot.
--all-authors
Include comments from all authors (humans and bots).
--include-resolved
Include resolved review threads. Only applies to line-level threads; issue comments and review summaries have no resolve concept.
--format TEXT
Output format: xml (default), json, or text.
--push-strategy TEXT
How commits and replies are sequenced in default-mode instructions: batch (default — commit per thread, push once, then reply) or each (commit, push, reply per thread). Ignored when --report-only is set.
--reply
Reply to a single thread. Requires --thread-id and one of --commit/--comment. Mutually exclusive with --report-only.
--thread-id TEXT
Thread ID to reply to (used with --reply).
--commit TEXT
Commit hash that addresses the thread (used with --reply). Mutually exclusive with --comment.
--comment TEXT
Custom reply body (used with --reply). Mutually exclusive with --commit.
--report-only
Emit a read-only research-report prompt; no commits, pushes, or replies. Mutually exclusive with --reply.
# List unresolved bot review comments (auto-detect PR/MR)zenable triage# List comments for a specific GitHub PRzenable triage --pr 123# List comments for a specific GitLab MRzenable triage --mr 456# Include comments from all authors, not just the botzenable triage --all-authors# Include resolved threads as wellzenable triage --include-resolved# Switch to per-thread commit + push + reply cycleszenable triage --push-strategy each# Reply to a thread by referencing a commitzenable triage --reply --thread-id PRRT_abc123 --commit abc123f# Reply to a thread with a custom commentzenable triage --reply --thread-id PRRT_abc123 --comment "Intentional, see docs"# Emit a read-only research-report prompt — no commits, no replieszenable triage --report-only# Same, but as JSON for downstream toolingzenable triage --report-only --format json
Resolve state only applies to line-level review comments. Issue comments (PR-level conversation) and review summaries (the body of a submitted review) have no resolve/unresolve concept, so --include-resolved is a no-op for them.
Opens a browser to complete the OAuth authentication flow. Credentials are cached locally for future commands. If already authenticated, skips re-authentication.
Diagnose and troubleshoot installation and client issues.
zenable doctor
Displays diagnostic information including OS details, terminal environment, Zenable environment variables (sensitive values redacted), dependency status, authentication state, custom guardrail validation status, and recent log entries.The Custom Guardrails section reports each configured custom guardrail file by absolute path with one of the following statuses:
✓ — passed both upstream syntax and Zenable schema checks
✗ — failed Zenable schema validation
? — partially or not yet validated; run zenable guardrail validate <engine> <file> for more details
Inspect and validate custom guardrail rules. The first positional argument selects the engine (opengrep or semgrep) — the server never infers it from the rule body. Subsequent arguments are file paths or glob patterns.
Validate one or more custom guardrail rule files. Runs the engine’s native validate command (catches YAML / pattern syntax errors) and the Zenable schema check (catches the field-level rules that protect the findings API). Validation results are cached locally by SHA-256 of the rule body, so re-running is free for unchanged files.
<engine> — required; one of opengrep or semgrep. Explicit by design; the server never infers it from the rule body.
<file-or-glob>... — one or more file paths or glob patterns. Globs expand relative to the current working directory. Excludes and config-driven skip-filenames do NOT apply: this command validates exactly what you point it at.
Options
--format <format> — text (default) or json
Examples
# Validate one filezenable guardrail validate opengrep ~/.zenable/custom_guardrails/semgrep/custom-no-eval.yaml# Validate every YAML rule in a directoryzenable guardrail validate semgrep '~/.zenable/custom_guardrails/semgrep/*.yaml'# Machine-readable output for CIzenable guardrail validate opengrep '**/*.yaml' --format json | jq
Exit Codes
0 — all files passed (or were partial-pass)
1 — at least one file failed validation
2 — bad arguments (unknown engine, no files matched)
# All Python files recursively'**/*.py'# Multiple extensions'**/*.{js,ts,jsx,tsx}'# Specific directory'src/**/*.py'# All files in current directory'*'# All files recursively'**/*'# Specific depth'*/*.py' # One level deep'*/*/*.py' # Two levels deep
# Maximum verbosityzenable -vv install# Run a check with verbose outputzenable -v check '**/*.py'# View debug logszenable logs --lines 100# Run diagnosticszenable doctor