Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Enji Guard Cli

FreeNot checked

Exposes Enji Guard access and compact report metadata to local tools via an MCP server.

GitHubEmbed

About

Exposes Enji Guard access and compact report metadata to local tools via an MCP server.

README

Python 3.14 CLI and MCP bridge for Enji Guard.

This is a working Docker-first product for local coding agents that use Enji Guard as an external repository-audit backend. It provides a shared core, a validated Typer CLI operator surface, and a curated read-only FastMCP surface for portfolio and report access.

See ROADMAP.md for the current product status and remaining MCP scope.

Mental Model

Enji Guard groups GitHub repositories into projects. Most workflows should use the GitHub owner/name repository selector; add --project NAME_OR_ID only when the account has ambiguous repositories or when a batch operation must be scoped to one project.

Mutating batch commands require explicit scope. Use a REPO argument for one repository, --all-repos with --project NAME_OR_ID for every repository in one project, or --all-projects for every repository in every project. Mutating commands are designed for agent retries: repeated calls should report unchanged, already_present, already_running, or equivalent state instead of duplicating upstream work.

Project admin commands are direct domain actions: create, rename, delete, and move repositories between projects. project delete succeeds only for empty projects; a project with any repository is rejected by the core layer.

Recon is baseline discovery. Report audits are separate, slow jobs that produce readable reports and scores. status is the snapshot/readiness/freshness view, wait is the completion check after status, report summary is the compact metadata path, and report read is the content path. status --json separates the latest readable report artifact from the current audit task lifecycle, so a stale readable report and a newly queued or running task can both be true. Scores are triage hints: use them to sort and prioritize repositories, then read the reports before changing code. When a report exposes commit hashes, compare them with the current checkout before treating the report as fresh. Starting a new audit can temporarily hide older snapshots behind running work, so read any needed snapshots before you start a fresh audit. CLI status and audit start do not trust Enji active-runs alone; the service keeps a short local started-task ledger and reconciles it with task-by-id so incomplete active-runs projections do not trigger duplicate starts. report read --json returns the full structured read payload, including each available Markdown report body. report summary --json is the compact batch contract: readable reports include summary metadata, and unavailable reports are returned with available: false plus a reason instead of aborting the whole batch.

Every command in the Audit Catalog context fetches GET /api/ux/catalog once for its invocation. curatedActions is authoritative: published audits in the live response are the available audits, so newly published audits participate automatically. The CLI keeps a best-effort previous observation at ~/.config/enji-guard/state/audit-catalog.json; it is never an API fallback and never supplies selectors. The first valid catalog establishes a baseline without a business notice. Later added, removed, or changed audits are emitted as a text business notice on stdout. With --json, the same information is under the stable top-level audit_catalog business section, whose changes field is an array and is empty when there are no changes. stderr is reserved for errors. CLI report selectors use the action-key suffix without the audit. prefix (for example, security selects audit.security). Recon is a separate audit.recon action and is not a report selector.

The workflow is audit -> findings -> optional improvement. The live catalog's auditAutofixes entries describe available variants. The supported typed relationships are security -> vuln-fix, tests -> test-writing, and dependency-hygiene -> dependency-update; pentest is separate. The CLI is the operator surface for autofix management (list and set), while MCP remains read-only. Use an explicit REPO, --all-repos with --project, or --all-projects for batch scope. The relationship mapping is temporary and can be removed when Enji exposes relationships directly.

Report language is an account-wide preference (en or ru) shared by all projects.

CLI output is human text and tables by default. Use --json only when another tool needs structured output.

Surfaces

Core owns Enji/auth behavior and task-level use cases. The CLI and MCP layers stay thin and call core instead of duplicating backend logic.

The CLI is the broad operator surface for agents. It exposes reads, writes, project administration, repository moves, schedule changes, email preferences, auth bootstrap, and runtime checks.

MCP is the curated read-only surface for agents that need the Enji picture: portfolio overview across projects and repositories, scores, freshness, active work, and report reading for a concrete repository. MCP does not mirror every CLI command or Enji frontend endpoint, and it does not expose auth bootstrap, auth-file diagnostics, project administration, or scheduling controls. Auth belongs to the Docker runtime and CLI operator surface.

The reconstructed Enji API contract lives in contracts/enji-openapi.json. Markdown documentation must not become a second API spec.

Agent Workflow

The service runtime is Docker. Agents should call the CLI inside the running container instead of installing or running this Python package on the host:

docker exec -i enji-guard-cli enji-guard --help

Application telemetry is written only to the persistent file outside the container by default. The current destination is JSONL at:

~/.config/enji-guard/logs/telemetry.jsonl

CLI stdout/stderr are reserved for command results, progress, and CLI errors. Use the telemetry file for HTTP/auth/runtime events and CLI/MCP agent journey events. It is the minimal foundation for future external sinks and OpenTelemetry-style export; there is no Prometheus or OpenTelemetry exporter yet. Each record includes provenance (cli, mcp, supervisor, runtime, or test) so operational traffic can be separated from test traffic. Tests do not write to the persistent telemetry file unless they explicitly configure a temporary log path. Keep stdout/stderr for CLI results, progress, and errors only.

When working on another repository, pass the repository as OWNER/NAME. If an agent is already in a GitHub checkout and wants to derive it from origin, it can do that in the host shell and still pass an explicit selector to the container:

REPO=$(git config --get remote.origin.url | sed -E 's#^[email protected]:##; s#^https://github.com/##; s#\.git$##')

docker exec -i enji-guard-cli enji-guard auth status
docker exec -i enji-guard-cli enji-guard repo resolve "$REPO"
docker exec -i enji-guard-cli enji-guard status "$REPO"

If the repository is absent from Enji:

docker exec -i enji-guard-cli enji-guard repo add "$REPO"
docker exec -i enji-guard-cli enji-guard status "$REPO"

repo add is idempotent project membership. If the repository is already present, continue with the same flow. It starts recon when baseline diagnostics are not ready. Use status to watch progress before expecting reports or scores.

For triage across all visible repositories:

docker exec -i enji-guard-cli enji-guard status --sort weakest
docker exec -i enji-guard-cli enji-guard repo list --sort latest-report

For reports:

docker exec -i enji-guard-cli enji-guard audit start "$REPO" --all
docker exec -i enji-guard-cli enji-guard wait "$REPO"
docker exec -i enji-guard-cli enji-guard report summary "$REPO"
docker exec -i enji-guard-cli enji-guard report read "$REPO"

Recon and report audits can take tens of minutes. Use status for a snapshot, wait as a follow-up completion check, report summary for compact triage, and report read after reports are ready. status shows stale audits explicitly and uses audited=mixed when report audits were generated from different commits. audit start --json returns a results matrix, one item per requested report audit, with states such as started, queued, already_running, up_to_date, or failed. Prefer reading reports through CLI/MCP instead of relying on email; disable noisy scheduled mail when it is not part of the workflow.

Requirements

  • Docker
  • just
  • Python 3.14 for repository development and QA
  • uv, only for repository development and QA

Releases

Package versions come from git tags. GitHub Release v0.1.0 produces Python version 0.1.0; untagged checkouts report a development version derived from the nearest tag and commit.

Release automation is handled by release-please. It opens a release PR from conventional commits, updates CHANGELOG.md, and creates the GitHub Release after that PR is merged. Use feat: and fix: only for changes that should be visible in release notes; keep internal churn under chore:, refactor:, test:, ci:, or docs:.

Use the local release status check after merges and releases:

just release-status

It needs gh and Docker buildx available for release checks; those are only required for this command, not for normal runtime use. It reports git state, open PRs, the latest GitHub Release, GHCR image publication, and recent GitHub Actions.

Runtime

mkdir -p ~/.config/enji-guard/logs
chown -R 1000:1000 ~/.config/enji-guard
chmod 700 ~/.config/enji-guard

docker compose up -d --force-recreate --remove-orphans --wait
docker exec -i enji-guard-cli enji-guard --help
docker exec -i enji-guard-cli enji-guard health --ready

Compose binds MCP to loopback, defines the service healthcheck, and limits the container to 512 MiB memory. HTTP MCP transports may bind outside loopback only with explicit --allow-external-host; use that only behind a trusted boundary. The image default stays loopback-safe; the compose files explicitly bind inside the container to all interfaces only because they publish the port on host loopback.

Docker health is full service readiness: local MCP plus cached authenticated Enji backend readiness. The supervisor refreshes cookie auth and probes backend readiness as separate sibling tasks; the probe records failures but does not perform refresh itself. Repeated auth/backend failures make the container unhealthy, so docker ps is a passive dashboard for Enji connectivity. Bearer/API-token auth is preferred. Cookie-session auto refresh is supervisor- owned and is not an MCP responsibility.

For registry-based deployment, use the GHCR image and compose example in docs/deployment.md.

Authentication

Bearer/API-token auth is the preferred stable path:

printf '%s' "$ENJI_API_TOKEN" | docker exec -i enji-guard-cli enji-guard auth import-token --stdin

Until API tokens are available, cookie auth is supported as a temporary compatibility path:

Run in the guard.enji.ai DevTools Console:

await fetch('https://fleet.enji.ai/api/v1/auth/refresh', { method: 'POST', credentials: 'include' });
await fetch('https://fleet.enji.ai/api/v1/auth/me', { credentials: 'include' });

In DevTools Network, open the second GET /api/v1/auth/me and copy Request Headers -> Cookie, not response headers. The refresh request's Request Cookie contains the old refresh token.

pbpaste | docker exec -i enji-guard-cli enji-guard auth import-cookie --stdin
docker exec -i enji-guard-cli enji-guard auth status
docker exec -i enji-guard-cli enji-guard health --ready

Do not paste credentials directly into shell history. The auth file defaults to ~/.config/enji-guard/auth.json and is written with private file permissions. Keep that directory writable by the container user because Enji rotates refresh cookies. Credentials belong in the configured auth file, not in checked-in env templates or persistent .env files.

Cookie refresh reserves a durable, private pending-replacement journal under the configured credential storage before contacting Enji. It contains protected recovery state and must be treated as credential storage; this documentation does not describe its secret fields. If auth-file replacement is interrupted, the supervisor retries recovery from that journal; do not delete it or copy its contents elsewhere.

Transport retries are profile-aware. Reads, safe probes, and idempotent mutations may retry transient transport or 429/5xx failures; unsafe mutations and cookie refresh are not retried by the transport layer. Transport backoff uses exponential delay with jitter and a 30-second cap (including a bounded Retry-After). Supervisor cookie-refresh recovery uses exponential jitter, continues until it succeeds, and caps any individual delay at one hour. An AUTH_REQUIRED failure uses the configured re-auth retry interval instead of exponential growth.

Useful telemetry events are written to ~/.config/enji-guard/logs/telemetry.jsonl: enji_http_retry, enji_auth_auto_refresh_scheduled, enji_auth_auto_refresh_retry, enji_auth_auto_refresh_succeeded, enji_auth_auto_refresh_schedule_failed, enji_auth_refresh_rotation_deferred, enji_auth_refresh_rotation_recovered, and enji_auth_refresh_rotation_superseded. Records contain retry classification and timing fields; credentials are not an operator-facing log output.

After a real cookie re-authentication, refresh the session in the browser, request /api/v1/auth/me, and import the current Cookie request header using the procedure above. Then validate the running service with:

docker exec -i enji-guard-cli enji-guard auth refresh
docker exec -i enji-guard-cli enji-guard auth status
docker exec -i enji-guard-cli enji-guard health --ready

Treat these commands and the telemetry events as runtime validation, not as a claim that the current Enji session is valid. If validation remains unhealthy, check the configured credential-storage ownership and write permissions, then repeat the browser re-auth/import and validation sequence.

CLI

docker exec -i enji-guard-cli enji-guard access
docker exec -i enji-guard-cli enji-guard project list
docker exec -i enji-guard-cli enji-guard project create Pets
docker exec -i enji-guard-cli enji-guard project rename Pets Friends
docker exec -i enji-guard-cli enji-guard project delete Pets
docker exec -i enji-guard-cli enji-guard language show
docker exec -i enji-guard-cli enji-guard language set ru
docker exec -i enji-guard-cli enji-guard repo add j2h4u/enji-guard-cli
docker exec -i enji-guard-cli enji-guard repo remove j2h4u/enji-guard-cli
docker exec -i enji-guard-cli enji-guard repo resolve j2h4u/enji-guard-cli
docker exec -i enji-guard-cli enji-guard repo move j2h4u/enji-guard-cli --to-project Friends
docker exec -i enji-guard-cli enji-guard status j2h4u/enji-guard-cli
docker exec -i enji-guard-cli enji-guard audit start j2h4u/enji-guard-cli --all
docker exec -i enji-guard-cli enji-guard wait j2h4u/enji-guard-cli
docker exec -i enji-guard-cli enji-guard report summary j2h4u/enji-guard-cli
docker exec -i enji-guard-cli enji-guard report summary j2h4u/enji-guard-cli --json
docker exec -i enji-guard-cli enji-guard report read j2h4u/enji-guard-cli
docker exec -i enji-guard-cli enji-guard report read j2h4u/enji-guard-cli --json
docker exec -i enji-guard-cli enji-guard --project Pets schedule list
docker exec -i enji-guard-cli enji-guard --project Pets schedule set --all-repos --enabled on --frequency workdays --timezone Asia/Almaty
docker exec -i enji-guard-cli enji-guard --project Pets schedule auto-time --all-repos
docker exec -i enji-guard-cli enji-guard --project Pets email set --all-repos --scheduled off
docker exec -i enji-guard-cli enji-guard auth refresh

Pass --json when a command output is consumed by automation.

Use the global --project NAME_OR_ID filter when a command must be scoped to one Enji project. repo move uses global --project as source project or selector disambiguation when needed. --to-project selects the destination project.

schedule controls automatic report-audit runs, one row per repository and catalog action key. Its cadence and per-subscription IANA timezone are stored with each schedule; Enji assigns the run time by default. The service/container should run with the host timezone. Batch writes are explicit client-side loops: use REPO, --project NAME_OR_ID --all-repos, or --all-projects. schedule set updates the selected scope, and schedule auto-time restores Enji-assigned run times. Autofix improvement-jobs are not audit schedules.

Autofix management uses improvement-jobs as the canonical resource. Its operator workflow is list/set per repository or explicit batch scope; it does not create or replace an audit schedule. Audit schedules remain under audit-auto-runs/{actionKey}.

language show reports the account preference. language set en|ru is idempotent and changes the account-wide report language; Enji does not expose an independent per-project language setter.

MCP

Local HTTP MCP service:

docker compose up -d --force-recreate --remove-orphans --wait

Endpoint:

http://127.0.0.1:8001/mcp

The Docker service starts a background cookie refresh loop. Keep ~/.config/enji-guard writable by the container user.

Development

just verify

The completion gate includes Ruff, basedpyright, import-linter, Vulture, deptry, OpenAPI contract validation, CRAP <= 30 per function, tests, and Docker build.

Use CONTRIBUTING.md for change intake, acceptance criteria, and handoff rules.

Security Notes

Cookie auth is temporary and will be removed when API-token support is available from Enji. MCP HTTP transports do not add their own authentication; keep them bound to loopback or behind an explicit trusted boundary. See SECURITY.md for the supply-chain policy covering package quarantine, allowlisted lifecycle scripts, Dependabot review, and locked dependency/Docker/CI references.

Documentation

License

PolyForm Noncommercial License 1.0.0. Commercial use requires separate permission.

from github.com/j2h4u/enji-guard-cli

Installing Enji Guard Cli

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/j2h4u/enji-guard-cli

FAQ

Is Enji Guard Cli MCP free?

Yes, Enji Guard Cli MCP is free — one-click install via Unyly at no cost.

Does Enji Guard Cli need an API key?

No, Enji Guard Cli runs without API keys or environment variables.

Is Enji Guard Cli hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Enji Guard Cli in Claude Desktop, Claude Code or Cursor?

Open Enji Guard Cli on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Enji Guard Cli with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs