Enji Guard Cli
FreeNot checkedExposes Enji Guard access and compact report metadata to local tools via an MCP server.
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
- ROADMAP.md: product status, remaining MCP scope, and modular install notes.
- CONTRIBUTING.md: change intake, acceptance, and handoff rules.
- AGENTS.md: concise development, QA, and ops rules for coding agents.
- docs/decisions.md: current architectural decision index and invariants.
- SECURITY.md: credential handling, supported versions, and MCP exposure notes.
- CHANGELOG.md: release history.
- docs/deployment.md: GHCR image and production-style Docker deployment.
- docs/enji-api-field-guide.md: sanitized reverse-engineering notes, endpoint behavior, and known contract gaps.
License
PolyForm Noncommercial License 1.0.0. Commercial use requires separate permission.
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-cliFAQ
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
GitHub
PRs, issues, code search, CI status
by GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
by mcpdotdirectCompare 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
