# Miucr

> Review code/diffs/PRs with the owned `miucr` CLI (miu-cr, a pure-Go AI code reviewer). Use when asked to review staged changes, a commit, a ref range, or a GitHub PR; to run/parse a gated review; compare reviewer quality with eval; to drive reviews over MCP; or to run the serve webhook/poll daemon or GitHub Action. Output is the stable `miucr.cli/v1` JSON envelope; parse it, don't grep prose.

- **Type:** Skill
- **Install:** `agentstack add skill-vanducng-skills-miucr`
- **Verified:** Pending review
- **Seller:** [vanducng](https://agentstack.voostack.com/s/vanducng)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [vanducng](https://github.com/vanducng)
- **Source:** https://github.com/vanducng/skills/tree/main/skills/miucr
- **Website:** https://skills.vanducng.dev

## Install

```sh
agentstack add skill-vanducng-skills-miucr
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# miucr: owned AI code-review CLI (v0.65.0)

`miucr` (the **miu-cr** project) is a fast, **pure-Go** (`CGO_ENABLED=0`) AI code reviewer.
It keeps the correctness-critical parts **deterministic** (file selection, context assembly,
line-anchoring, severity gating, dedupe) and uses the LLM only for judgment (finding bugs,
proposing fixes). It runs five review ways:

- **Local review**: `miucr review` over a staged diff, a commit, or a ref range.
- **GitHub PR review**: `miucr review --pr` (dry-run by default; `--post` reacts 👀, upserts ONE summary issue comment, and posts inline comments as a PR review).
- **serve daemon**: HMAC webhook (default) and/or opt-in poll trigger; optional REST API + GitHub App auth.
- **MCP server**: `miucr mcp` exposes `review_run` / `review_get` over stdio to any agent host.
- **Evaluation**: `miucr eval` compares miu-cr and other reviewer commands against JSON expected findings.

**Review behavior worth knowing (design choices that prevent noise):**
- **One upserted summary, posted first.** `--post` writes ONE summary *issue comment*, edited in place on re-runs (never stacked), and acknowledges the PR with 👀. If no summary exists yet, it also creates a short `Review running` placeholder before the LLM starts; on later commits it keeps the prior completed summary visible until the new result is ready. The final summary replaces that same comment and is posted BEFORE the inline review so it anchors on top (overview → details). Inline findings are a separate PR review. `review_id` is NOT shown in the comment (it only resolves on the local store; it stays in the JSON envelope). On a **fatal review failure** after miucr's internal retries, `--post` upserts that SAME summary comment with a visible GitHub alert instead of failing silently: operational/provider/infrastructure failures (`agent.unavailable`, `provider.rate_limited`, `quota.exceeded`, `review.timeout`, `github.unavailable`, etc.) render as `[!WARNING]`, while unknown `internal.error` failures render as `[!CAUTION]`; a later successful run replaces it with findings.
- **The summary is a per-finding lifecycle ledger, not just the latest run.** Below a concise ≤5-bullet "What changed" summary, it renders two always-visible tracking tables — **⚠️ Open (N)** and **✅ Resolved (N)** — each finding tracked by its line-independent fingerprint across commits: a **Priority** column (P0–P4), status (`open` / `resolved` / `reopened`), the **origin commit** it was first raised on and the **resolved commit** it disappeared on (both linked), priority before→after for escalations, and first-seen / resolved timestamps. A clean review uses natural all-clear prose like `Review passed! No findings on the first review pass.` or `Review passed! 3 findings resolved. Good cleanup.` The deterministic note gets stronger as more findings are cleared and adapts to focused vs broad diffs. The footer is `Last reviewed commit` + review attempts + the miu-cr release. Lifecycle state is **storeless**: it lives in a hidden `` marker inside the comment (like the runs counter), so it survives ephemeral CI with no DB. A finding resolves only when it is absent AND its file is still in the diff (absence off-diff ≠ fix).
- **Inline comments persist; resolving the threads is left to you / your coding agent.** Each finding's inline comment is posted ONCE and deduped across re-runs via a hidden `` marker, so a re-review never re-posts or deletes it. miucr does NOT click "Resolve conversation": when a finding is fixed, GitHub auto-marks the thread *Outdated* and the summary ledger moves it to **✅ Resolved**, but the inline thread itself stays open for the developer/coding agent to resolve. A host config may opt into `thread_resolution_sync.mode: poll` to mirror manual GitHub "Resolve conversation" state into the summary (the Resolved row shows a clean `💬 conversation` marker linked to the discussion thread, distinct from a commit-resolved row's `open → resolved` SHA arrow); this never starts an LLM review and never feeds approval. So an agent acting on a review should read the inline threads, apply the fixes, reply on each handled inline thread with what changed and why, then resolve the thread.
- **Repeat-run stability is deterministic inputs + low-variance generation.** For the same repo/ref/config, file selection, context assembly, rules, anchoring, gating, fingerprints, and comment dedupe are deterministic. SDK-backed Anthropic/OpenAI calls use `temperature: 0`; exact model output can still vary, so PR posting is idempotent rather than duplicate-prone.
- **One-click suggestions and approvals are explicit write actions.** `--suggest` emits a native GitHub ` ```suggestion ` block ONLY for findings at or above the suggestion floor (`medium`) when the patch *deterministically* replaces the exact anchored line(s) and the model is certain of a grounded mechanical fix (a cited rule or an obvious best practice). It NEVER guesses an unverifiable value (a URL, path, route, ID, version, config key, API signature); such concerns become a verification-question in the rationale instead. `--patch-repair` (requires `--suggest`) runs one focused 2nd LLM pass to recover a repairable near-miss patch. `--approval clean|threshold` submits APPROVE only when the policy and safety gates pass; the first approval body is short (`LGTM`) and links to the code review summary unless `--approval-note none` is set. Approval is head-SHA scoped: a later clean push can be approved again bodyless, threshold re-approvals carry the threshold note, and the same commit is not approved twice. Permission/self-approval failures warn and degrade rather than failing the review.
- **`-o pretty`** is the human-readable local format; **`-o json`** is for agents; `-o sarif` for editors/CI.
- **Multi-provider profiles.** Add a named provider (e.g. z.ai/glm) with `kind`, `base_url`, `model`, `auth`, and either `auth_env` or `auth_command`; select with `--provider `. Built-in kinds: `anthropic`, `openai` (ChatGPT-plan OAuth via `miucr login`). Transient GitHub/network errors auto-retry with backoff. Optionally cap a provider instance's usage with `[providers..quota]` (`dimension = tokens|requests`, `limit`, `window = |monthly`); **uncapped by default**, fail-closed, over-quota → typed `quota.exceeded`.
- **Thinking on by default; deterministic fallback.** Capable models (Claude, gpt-5/o-series, codex, **z.ai GLM 4.5+**) review with **extended thinking/reasoning** (deeper analysis; temperature is omitted because thinking forces temp 1). Models without thinking (gpt-4o, plain glm-4 chat) sample at **temperature 0** for stable, reproducible findings. Both are config-exposed: `[review].thinking` (`auto|off|low|medium|high`, default auto) and `[review].temperature` (0–2, default 0). Set `MIUCR_TRACE_REASONING=true` to capture that reasoning into the review trace (`miucr trace `).

## Output contract: `miucr.cli/v1` envelope (parse this)

Every command prints **one JSON object** on stdout (default `-o json`). Field order:

```json
{
  "ok": true,
  "api_version": "miucr.cli/v1",
  "kind": "review.result",
  "command": "review",
  "request_id": "req_...",
  "summary": { "findings": 2, "gate": "high" },
  "data": { "...": "command-specific" },
  "artifacts": [],
  "warnings": []
}
```

- `ok` (bool) is the branch point. `artifacts` and `warnings` are **always present** (`[]` when empty).
- `summary`, `data`, `page`, `stats` are present only when relevant (`omitempty`).
- Errors use the **same envelope** with `ok:false`, `kind:"error"`, and an `error` object:

```json
{ "ok": false, "api_version": "miucr.cli/v1", "kind": "error", "command": "review",
  "error": { "code": "review.gate_failed", "message": "", "hint": "...",
             "retryable": false, "safe_to_retry": false } }
```

`kind` per command: `version`, `review.result`, `config.show`, `rules.check`, `rules.init`, `init.result`, `login.result`,
`whoami`, `logout`, `history.list`, `history.record`, `history.prune`, `eval.result`, `trace.show`, `error`
(REST: `review.accepted` / `review.result`). **Secrets never appear** in the envelope, logs, or on disk
(credential-named fields are scrubbed; finding `rationale`/`suggested_patch` prose is exempt).
The `--instruction`/`--conversation` flags and the `/miucr review ` comment trigger only add
**input** (a USER-turn context block); they never change the envelope or the finding JSON (still
`miucr.cli/v1`); parse the same shape.

### Exit codes (gate → exit mapping)

| Exit | Meaning |
| ---- | ------- |
| `0`  | Success: no finding reached `--gate`. |
| `1`  | Operational error: missing credentials, internal failure, store unavailable. |
| `2`  | **Gate failed** (a finding's severity ≥ `--gate`) **or** invalid invocation (bad gate, conflicting/zero modes, bad `--output`). |

Severities low to high: `info` .quota]` is exhausted for the current window; exit `2`. On the serve host the PR is skipped+logged, not failed (a later push re-checks). A quota counter that can't be read/opened fails closed as the retryable `store.unavailable` instead (serve retries, not skips) | `false` | raise the provider quota `limit` or wait for the window to reset |
| `github.auth` | PR fetch hit `401`/`403` (bad/missing `GITHUB_TOKEN` or insufficient scope) | `false` | check `GITHUB_TOKEN` / its repo scope |
| `github.pr_not_found` | PR fetch hit `404` (no such PR, or the token can't see it) | `false` | check the PR exists and the token has access |
| `github.rate_limited` | PR fetch hit `429` (REST rate limit or abuse-detection) | `true` | GitHub rate limit: wait for the reset and retry |
| `github.unavailable` | PR fetch hit `5xx` / a network error (DNS / refused / timeout) | `true` | GitHub unavailable / unreachable, retry shortly |
| `github.pr_fetch_failed` | any other unclassified PR-fetch failure | `false` | - |
| `internal.error` | any unclassified failure (default; bare-wrapped) | `false` | - |

Unknown failures stay `internal.error` (never mislabeled as retryable). Classified messages are redacted: **no token fragment ever appears**.

The **codex** backend retries `429`/`502`/`503`/`504` (and a `response.failed` stream event) with bounded, jittered exponential backoff (≤3 attempts) like the SDK backends, honoring `Retry-After`/`resets_in_seconds` and aborting on cancel/timeout. A persistent rate limit returns `provider.rate_limited` with the usage-cap reset window in `error.details.resets_in_seconds` (or `retry_after_seconds`); branch on that to decide wait-vs-switch-provider.

## Install

```sh
curl -fsSL https://cr.miu.sh/install.sh | sh   # asset-aware latest
curl -fsSL https://cr.miu.sh/install.sh | sh -s -- v0.65.0   # pin
brew install vanducng/tap/miucr                                                     # Homebrew
go install github.com/vanducng/miu-cr/cmd/miucr@latest                              # Go 1.25+
```

Verify: `miucr version` → `{"ok":true,...,"data":{"version":"v0.65.0"}}`.
Config (optional) at `~/.config/miu/cr/config.toml`; state DB at `~/.config/miu/cr/state.db`.
Repo rules at `.miu/cr/rules/*.md` (**never a flat `.miucr/`**).

## Onboarding (`miucr init`)

`miucr init` is the fastest path to a working config. It walks a clean, sectioned
wizard (**provider → provider-aware auth → project rules**), then writes
`~/.config/miu/cr/config.toml` (dir `0700`, file `0600`, **deltas only**: the
chosen provider block, never the full built-in defaults) and ends on the literal
`miucr review --staged`.

```sh
miucr init                                  # interactive wizard (idempotent: Overwrite? y/N)
miucr init --non-interactive --provider anthropic --auth-env ANTHROPIC_API_KEY --yes
```

- **Provider-aware auth menu**: `openai` offers **browser login (OAuth, default)**
  (review on your ChatGPT/Codex plan, no API key) plus env-var or paste; it runs
  the same PKCE loopback flow as `miucr login` and caches the token in `oauth.json`
  (config records just `default_provider = "openai"`, no secret). `anthropic` offers
  env-var (default) or paste, **no OAuth** (Anthropic ToS). `custom` asks kind +
  base URL, then env-var or paste.
- **Default writes no secret**: only the env-var **name** (`auth_env`). A literal
  `auth_token` lands only on explicit paste + confirm (after a plaintext-on-disk warning).
- Flags: `--provider anthropic|openai|custom`, `--auth oauth|env|paste` (non-interactive
  selector), `--auth-env `, `--base-url `, `--no-rules`, `--force`,
  `--yes`, `--non-interactive`. `--auth oauth` is interactive-only (needs a browser);
  non-interactive errors `init.aborted` toward `miucr login`. Envelope `kind: init.result`
  (`data.auth_method` = `oauth|env|paste`, `data.next` = `miucr review --staged`); errors
  `init.aborted` / `config.write_failed`.
- `init` is **optional**: zero-config still works when a provider key is on the env.
  With no config **and** no key, `review` prints a soft one-line nudge to run `init`.

## Examples (copy-paste starters)

The repo ships an [`examples/`](https://github.com/vanducng/miu-cr/tree/main/examples)
tree: `rules/{go-api,typescript-node,python-data}.md`,
`github-action/code-review.yml` (fork-safe `pull_request_target`),
`workflows/miucr-review.yml` (the **dual-trigger** default: `pull_request` + a
`/miucr review ` comment trigger),
`mcp-setup/{claude-code,cursor,codex}` + `README-mcp.md`,
`review-local/{pre-commit,Makefile,agent-review.sh}` (review-your-own-changes
recipes), and `review-host/{Dockerfile,docker-compose.yml,config.example.yaml}`
(pure-Go `CGO_ENABLED=0` Alpine image + Postgres host stack for `miucr serve`).
Onboarding walkthrough lives at the docs
[Getting started](https://cr.miu.sh/onboarding/) page.

**Comment-triggered review (`/miucr review `).** With the dual-trigger workflow
installed, a **write or admin collaborator** posts `/miucr review ` as a top-level PR
comment (e.g. `/miucr review focus on the auth changes`) to steer a re-review with free text.
The `issue_comment` event runs the trusted base-branch workflow with full secrets even on
fork PRs, so the workflow self-gates: the commenter must have **write|admin** (an
`actions/github-script` `repos.getCollaboratorPermissionLevel` check; `author_association`
alone is insufficient), the comment body is read via an env var (never inline-interpolated
into `run:`), the released binary is used (fork head code is never built with secrets), and
miucr adds a 👀 reaction to acknowledge an accepted command. Known limits (v1): only
top-level `issue_comment` is caught (not inline review comments or review summaries), and an
unchanged head SHA short-circuits (there is no `--force` on the comment path yet).

## Commands & exact flags

Global flags (all commands): `-o, --output json|pretty|sarif` (default `json`), `--timeout `
(default `30s`; `review` auto-bumps to `900s` and `eval` to `30m` unless `--timeout` is set explicitly).
`sarif` is **review-only**: it emits a SARIF 2.1.0 document (NOT the envelope) for
code-scanning/IDEs (`ruleId`=category, `level` from severity, repo-relative paths);
upload it with `github/codeql-action/upload-sarif`. `pretty` is a local reporter
(jumpable `file:line`, excerpt, patch; color on a TTY). `review --pr` also takes
`--filter-mode added|diff_context|file|nofilter` (default `diff_context`) controlling
which findings are inline-eligible; `file`/`nofilter` route off-diff findings to the
summary/SARIF/local output, never inline.

### `review`: needs **exactly one** mode

```sh
miucr review --staged                     # staged changes vs the index
miucr review --from main --to HEAD        # ref range (--from and --to required together)
miucr review --commit HEAD~1              # one commit vs its parent
miucr review --pr owner/repo#123          # a GitHub PR (dry-run by default)
miucr review --staged --instruction "focus on the auth changes"   # steer this one review
miucr review --pr owner/repo#123 --conversation                   # also read the prior PR thread
```

| Fla

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [vanducng](https://github.com/vanducng)
- **Source:** [vanducng/skills](https://github.com/vanducng/skills)
- **License:** MIT
- **Homepage:** https://skills.vanducng.dev

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** yes
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-vanducng-skills-miucr
- Seller: https://agentstack.voostack.com/s/vanducng
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
