Audit and govern locally installed agent CLIs and adjacent runtime tooling.
agent-cli-governor is a small local-ops repository for three related problems:
- detecting what agent CLIs are installed on a machine
- checking whether the current install channel still matches vendor guidance
- producing conservative upgrade and migration suggestions
agent_cli_audit.pyInspects installed tools, detects install channel, compares current versus latest version, summarizes release risk, and surfaces migration advice when the install method drifts from vendor guidance.agent_cli_upgrade.pyBuilds a conservative upgrade plan from the audit results and can optionally execute approved upgrades.agent_cli_catalog.jsonThe policy catalog that defines tracked tools, install channels, and source-specific latest-version lookups.gui.pyA thin NiceGUI prototype that visualizes the existing CLI and JSON outputs without replacing the CLI-first core.
The main focus is agent-cli tools such as:
- OpenAI Codex CLI
- Cursor Agent CLI
- Claude Code
- Gemini CLI
- xAI Grok CLI
- Nori CLI
- Vercel fx
- Kiro CLI
- Devin CLI
- Hermes CLI
- Google Antigravity CLI (
agy) - Google Jules CLI
- Copilot CLI
- OpenCode
- Amp
- Droid
- Kilo Code
- Cline
Agent-operations entries currently include Multica, Claude Code Router (ccr), 9Router, Nowledge Mem CLI (nmem), Orca, and CodexBar (codexbar).
The catalog has three intentionally narrow classes:
agent-cli: a CLI that directly accepts and runs a coding-agent task, such as Codex, Claude Code, Jules, or Gemini.tooling-runtime: protocol adapters and execution dependencies, such as ACPX, Codex ACP, Agent Browser, OpenSpec, anduv.agent-operations: a user-facing product that coordinates agents, routes model traffic, manages workspaces, knowledge, or usage, such as Multica, Claude Code Router, 9Router, Nowledge Mem CLI, Orca, and CodexBar.
The distinction prevents orchestration products from being mislabeled as either an Agent provider or a runtime dependency.
- macOS or another environment where the tracked CLIs are available in
PATH - Python 3
- Optional but commonly expected on the target machine:
brewnpm- network access for latest-version and release-note checks
The npm upgrade guard supports mise, nvm, fnm, and asdf. It validates the active Node/npm topology before an npm plan becomes executable. An unrecognized Node manager remains usable for auditing and dry-run planning, but its npm upgrades are intentionally not executable.
No Python package installation is currently required for the CLI tools.
python3 agent_cli_audit.py
python3 agent_cli_audit.py --offline
python3 agent_cli_audit.py --json
python3 agent_cli_audit.py --all
python3 agent_cli_audit.py --only-outdated
python3 agent_cli_audit.py --only-nonstandard
python3 agent_cli_audit.py --only-class agent-cli
python3 agent_cli_audit.py --only-class tooling-runtime
python3 agent_cli_audit.py --only-class agent-operations
python3 agent_cli_audit.py --with-release-notes
python3 agent_cli_audit.py --check-node-runtime
python3 agent_cli_audit.py --inventory-private-harnesses
python3 agent_cli_audit.py --inventory-private-harnesses --private-harness-baseline ~/private-harness-inventory.jsonpython3 agent_cli_upgrade.py
python3 agent_cli_upgrade.py --offline
python3 agent_cli_upgrade.py --channel recommended
python3 agent_cli_upgrade.py --channel supported
python3 agent_cli_upgrade.py --tool codex --tool gemini
python3 agent_cli_upgrade.py --tool uv --applypython3 -m pip install -r requirements-gui.txt
python3 gui.pyEnable NiceGUI hot reload during local GUI development:
python3 gui.py --reloadThe GUI entrypoint is reload-safe for NiceGUI multiprocessing, so use the
command above instead of wrapping ui.run() behind a plain if __name__ == "__main__":
pattern in downstream forks.
Reload watches only this project directory's *.py and *.json files, even when
the launcher is invoked from another working directory.
The GUI is intentionally a thin shell over the existing CLI tools:
Overviewexplains the upgrade model and shows static example dataConsoleruns a local audit and generates a dry-run upgrade plan; it never executes upgradesLoad release notesis enabled by default for online GUI audits so the Release Risk column can show available changelog evidence. Disable it for a faster version/channel-only audit; offline mode never fetches notes.- The audit table shows a product logo, current/latest versions, and their upstream publication dates. Dates appear only when exact upstream evidence is available;
Unknownnever means the local installation time. A compact evidence banner distinguishes failed upstream lookups from non-failure source gaps, and hovering anUnknowndate, latest version, or release-risk value gives its field-specific reason. TheEvidence Gapscard lists source-coverage, version-namespace, and date-parsing limitations separately fromAudit Warnings. Generate Upgrade Planreuses the latest matching audit result when possible, avoiding a second full network audit- The selected CLI's
Detailspanel can load release notes on demand, so changelog retrieval does not block the main audit Plan scopecontrols generated upgrade plans;Installation statusandOnly outdatedare results-table filters, while the summary cards remain an unfiltered audit baselineRun Auditreuses a matching in-memory audit for up to 10 minutes; the adjacentForce refreshbutton always bypasses that cache. The cache is per GUI process and is never written to disk.- online audit probes up to four CLIs concurrently; individual HTTP and package-manager lookups are bounded and failures appear under
Audit Warnings - class selection happens before probes begin, so one class cannot create warnings or network work for another; JSON output includes a catalog revision and selected-entry count for diagnostics
- local version and package-manager probes run in isolated process groups, so a timed-out launcher cannot leave a native child process behind
- Python HTTP lookups use the default
urllibproxy resolution:HTTP_PROXY/HTTPS_PROXYtake precedence, with macOS system proxy settings used when those variables are absent; that resolved proxy is also passed tonpmand Homebrew lookups - long-running subprocesses have a bounded timeout and are stopped on timeout rather than left running in the background
- the GUI never executes upgrades; explicit CLI
--applyremains separately guarded and requires user authorization
Run it with python3 gui.py. If port 8080 is already in use, choose another port, for example python3 gui.py --port 8081.
The audit output distinguishes:
tooling_classagent-cli,tooling-runtime, oragent-operationsnormalized_channelFor examplescript,npm,brew-core,brew-cask,desktop-installbinary_containerThe resolved executable's physical form, currentlystandaloneorapp-bundle. This is distinct from install channel: an official script can install a shim in~/.local/binthat resolves to an app bundle.channel_statusrecommended,supported, ornonstandardupdate_commandThe one executable command selected as the safe default for--applyupgrade_guidanceStructured primary-action title, rationale, installation-channel effect, and optional informational alternatives. Alternatives are never executed by--apply.migration_commandA suggested migration path when the current install channel is no longer preferredrelease_riskA lightweight summary of upgrade-time change risk inferred from the latest release notes. It signals how risky or behavior-changing the newest upstream release may be to adopt, not the risk of staying on the current version.audit_metadataCatalog entry and selection counts plus a catalog revision, used to diagnose which policy catalog produced a GUI or JSON audit.logo_url,current_version_published_at,latest_version_published_atOptional presentation evidence for the product logo and exact upstream publication dates. Missing publication dates are intentionally represented as unavailable rather than as local installation times.
--offlineskips network-backed latest-version checks and is better for quick local scans.--check-node-runtimeis a read-only Node runtime topology check fornode,npm,npx, andpnpm. It recognizesmise,nvm,fnm, andasdf; it detects PATH, Node executable, and npm-prefix drift, and applies the stricter local-wrapper policy only tomise. It never repairs the environment. A terminal invocation checks only that terminal; for GUI context, use the GUI's Run Node Runtime Check action, which launches the probe from the GUI server process.--inventory-private-harnessesis a separate, read-only inventory for private Agent Harness copies. It reports the current shell entrypoints, fixed evidence paths for Zed, Devin Desktop, Multica, Codeg, and Conductor, and explicit safe bindings for Zed, Nori, ACPX, and Codex ACP. It never recursively scans app bundles, runs host-private executables, reads command arguments or secrets, or changes a host. A private copy is a governance risk only when a client binding is confirmed and a specific policy or known risk applies; host presence alone is reported asunconfirmed.--private-harness-baseline PATHcompares against an explicitly supplied JSON report without writing it. Use an external, private location if you choose to retain an inventory; the repository and weekly automation do not store machine inventory results. A changed baseline means manual review is warranted, not automatic repair.- To create that external baseline deliberately, redirect the JSON output yourself, for example
python3 agent_cli_audit.py --inventory-private-harnesses --json > ~/private-harness-inventory.json. - The weekly upgrade automation deliberately runs only
--check-node-runtime; it does not run the private Harness inventory or scan desktop application directories every week. --only-outdatedonly shows installed tools that are both outdated and upgradeable on the current channel.--only-nonstandardnarrows the report to tools whose install channel does not match the vendor's supported or recommended channels.--only-classseparates direct Agent CLIs, runtime dependencies, and agent-operations products.--with-release-notesfetches the latest release notes where possible and produces a simple risk summary. GitHub Releases are supported directly, and a few vendor-hosted changelog pages are summarized heuristically.- A native self-update command is not automatically preferred over npm or Homebrew. When a CLI can explicitly preserve its install method, such as Kilo Code and OpenCode with
--method, the plan uses that native command. When ownership effects are unverified, the plan preserves the current npm/Homebrew channel and presents native self-update only as an informational alternative. - Claude Code uses
claude update; its installer may migrate installation types, so it is not the default for Homebrew-managed installs. Codex script installs use the official standalone installer, while app-bundled Codex is updated with ChatGPT.app. - Antigravity CLI uses Google's native installer at
~/.local/bin/agyand runs its verified self-updater in the background during normal CLI use. The audit reports its official manifest version but does not treat interactiveagystartup as an automatic--applyaction. - The tool catalog lives in
agent_cli_catalog.json. - Most entries are
agent-cli.tooling-runtimecovers supporting adapters and dependencies;agent-operationscovers products that coordinate one or more Agent CLIs without being the Agent itself. - The audit output separates the selected
update_commandfrommigration_command.upgrade_guidanceexplains which action is selected, how it affects installation ownership, and when an alternative is only for review or troubleshooting. agent_cli_upgrade.pyonly upgrades entries that are both outdated and on a recognized supported or recommended channel.- npm-channel plans run through the validated Node runtime provider:
miseusesmise exec node -- npm, whilenvm,fnm, andasdfuse a path-bound npm command with the validated Node bin directory first inPATH. A failed or unsupported runtime check leaves dry runs visible but blocks--applyfor plans containing npm-channel upgrades. - Source-linked catalog entries, currently including 9Router and Claude Code Router, can read a compatible local launcher and report the existing local Git relation to their configured upstream ref. They never fetch, rebase, or modify the checkout; a stale upstream ref is explicitly reported.
- Missing catalog entries are omitted from the default audit and listed only with
--all. agent_cli_upgrade.py --offlinereuses offline audit mode for faster but less complete upgrade planning.agent_cli_upgrade.py --only-class agent-clilimits planning to the same class boundary used by the audit.agent_cli_upgrade.py --channel recommendednarrows the plan to vendor-recommended install channels only.agent_cli_upgrade.py --channel supportedis the default and includes both recommended and supported channels.--recommended-onlyis kept as a compatibility alias for--channel recommended.
topgrade is useful as a bulk execution engine, but this repository solves a different problem.
agent-cli-governor is opinionated about:
- whether a tool is installed through the vendor-recommended channel
- whether the current channel is merely supported or already drifted
- how to compare vendor-specific latest-version sources
- how to surface migration advice when the install method is no longer preferred
Those policy checks are the core value here. A generic upgrader can execute package-manager updates, but it usually does not answer:
- should this tool be upgraded from the current channel at all
- is the current install method still the one the vendor wants
- does this tool need an in-channel upgrade or a migration
So the project treats topgrade as optional execution infrastructure, not as the decision-making layer.
The distinction is intentional and operationally useful:
recommendedThe vendor's current preferred installation path. This is the safest default for routine upgrades.supportedA channel the vendor still supports, but does not currently present as the preferred path.
Without this distinction, local CLI governance becomes too coarse:
- some tools would be upgraded through channels the vendor is gradually de-emphasizing
- migration opportunities would be hidden inside normal upgrade advice
- automated checks could not separate "safe default upgrades" from "allowed but less preferred upgrades"
In practice:
--channel recommendedis the conservative weekly-upgrade path--channel supportedis the broader review pathnonstandardis where migration or manual review is usually needed
Basic health checks:
python3 -m py_compile agent_cli_audit.py agent_cli_upgrade.py gui.py
python3 agent_cli_audit.py --offline --only-class agent-cli
python3 agent_cli_upgrade.py --channel recommendedMIT. See LICENSE.