cora-cli is a Rust CLI tool for AI-powered code review. Bring Your Own Keys (BYOK) — no managed API, no cloud service. Runs locally against diffs, scans, or branches.
- License: MIT
- Edition: Rust 2024 (MSRV 1.85)
- Repo:
codecoradev/cora-cli - Default branch:
develop - Marketplace: https://github.com/marketplace/actions/cora-ai-code-review
- Website: https://codecora.dev
cargo build # Build (debug)
cargo build --release # Build (release)
cargo test # Run all 567 tests
cargo clippy --all-targets -- -D warnings # Lint (strict)
cargo fmt --all -- --check # Format checkAlways run cargo fmt --all before committing. CI runs all three checks.
src/
├── main.rs # Entry point, CLI argument parsing
├── commands/ # Subcommand handlers
│ ├── mod.rs
│ ├── review.rs # cora review (diff-based review)
│ ├── scan.rs # cora scan (full-file scan)
│ ├── debt.rs # cora debt (tech debt report)
│ ├── commit_cmd.rs # cora commit (review + commit message + commit)
├── index/ # Symbol index (v0.6 — Code Intelligence)
│ ├── mod.rs # Index engine (open, index_project, search)
│ ├── schema.rs # SQLite schema + FTS5
│ ├── symbols.rs # SymbolKind, SymbolQuery, SearchResult
│ ├── extract.rs # Per-language definition + call extraction
│ └── graph.rs # Call graph (callers, impact, affected)
│ ├── config_cmd.rs # cora config (show/set/validate)
│ ├── auth.rs # cora auth (API key management)
│ ├── hook_cmd.rs # cora hook (pre-commit hook install/uninstall)
│ ├── init.rs # cora init (project scaffolding)
│ ├── upload.rs # cora upload (review upload)
│ ├── completion.rs # Shell completion generation
│ ├── debt.rs # cora debt (tech debt report)
│ └── providers.rs # cora providers (list providers)
├── config/
│ ├── mod.rs
│ ├── schema.rs # Config structs & defaults
│ ├── loader.rs # Config loading & priority chain
│ └── providers.rs # LLM provider definitions
├── engine/
│ ├── mod.rs
│ ├── review.rs # Review orchestration logic
│ ├── scanner.rs # File scanning engine
│ ├── llm.rs # LLM API interaction
│ ├── types.rs # Severity, finding, and result types
│ ├── diff_parser.rs # Diff → FileChunk parsing
│ ├── chunker.rs # Auto-chunking large diffs
│ ├── profiles.rs # Quality profiles (strict/balanced/lax)
│ ├── quality_gate.rs # Quality gate thresholds + pass/fail
│ ├── debt_tracker.rs # Tech debt metrics + trend tracking
│ ├── security_scanner.rs # Static security pattern matching
│ ├── language_analyzer.rs # Language-specific review guidance
│ ├── secrets_scanner.rs # Secret/credential detection
│ ├── debt_tracker.rs # Tech debt metrics + history snapshots
│ ├── memory.rs # Uteke memory integration (recall + learn)
│ └── rules/ # Custom rule engine
│ ├── mod.rs
│ ├── builtin.rs # Built-in rules
│ ├── matching.rs # Rule matching logic
│ └── types.rs # Rule & finding types
├── mcp/ # MCP server (Model Context Protocol)
│ ├── mod.rs
│ ├── protocol.rs # JSON-RPC 2.0 types
│ ├── server.rs # Stdio transport + request dispatch
│ └── tools.rs # 5 tool handlers
├── formatters/ # Output format implementations
│ ├── mod.rs
│ ├── pretty.rs # Human-readable terminal output
│ ├── compact.rs # Compact single-line output
│ ├── json_fmt.rs # JSON output
│ └── sarif.rs # SARIF format (CI integration)
├── git/
│ ├── mod.rs
│ ├── diff.rs # Git diff parsing
│ └── files.rs # File listing & filtering
└── hook/
├── mod.rs
├── install.rs # Hook install/uninstall logic
└── template.rs # Hook script templates
| File | Purpose |
|---|---|
commands/config_cmd.rs |
Config subcommand — display, set, validate, path resolution |
config/loader.rs |
Config loading with full priority chain resolution |
config/schema.rs |
All config structs, defaults, serde annotations |
commands/init.rs |
Project scaffolding, .cora.yaml generation |
cargo test # 567 tests total
# 484 unit tests
# 16 CLI integration tests
# 6 config tests
cargo test --no-verify # Skip pre-commit hooks (avoids timeout in hooks)Use --no-verify when running tests through pre-commit hooks to prevent nested
hook execution and timeouts.
Three GitHub Actions workflows in .github/workflows/:
- ci.yml — PR checks: build, test, clippy, fmt on push to
developand PRs - release.yml — Triggered by
v*tags; builds for 4 platforms (Linux x86_64, macOS x86_64, macOS ARM64, Windows x86_64), publishes to crates.io - deploy-website.yml — Deploys project website/docs
- CLI flags (
--provider,--model, etc.) - Environment variables (
CORA_PROVIDER,CORA_MODEL, etc.) - Project config (
.cora.yamlin repo root) - Global config (
~/.cora/config.yaml) - Built-in defaults (defined in
config/schema.rs)
API keys live in a separate auth.toml file (~/.cora/auth.toml), not in
.cora.yaml. This prevents accidental key leakage via committed config files.
- Severity comparison uses
<=not>=: Severity filtering uses<=because the ordinal maps info=1, warning=2, error=3 — so--severity warningmeans "include warning and below (info)", not "warning and above (error)". This is intentional; the mapping is defined inengine/types.rs. - TOML → YAML migration: Config format migrated from TOML to YAML for better readability and broader tooling support. The loader only reads YAML now.
- Auth/config separation: API keys are deliberately stored in
auth.tomlrather than the main config to allow.cora.yamlto be safely committed to repositories without exposing secrets. - LLM JSON repair:
engine/llm.rsincludesrepair_invalid_escapes()— a state machine that fixes invalid JSON escape sequences produced by some LLMs (e.g.\s,\d→\\s,\\d). Applied beforeserde_json::from_strin all parse paths.review_diff()also retries once on parse failure. - Temperature 0 (deterministic): Default temperature is 0 (v0.1.7+). Same diff produces identical review output every run. Cache key includes model + temperature.
- Per-request HTTP timeout:
reqwest::Clientshared viaLazyLock(connection pooling). Timeout set per-request via.timeout()on RequestBuilder, not at client construction (client-level is misleading). - Diff-hash caching: Reviews cached in
~/.cache/cora/reviews/by SHA-256 of diff + model + temperature. TTL configurable viallm.cache_ttl. Bypass with--no-cache. Cache stores fully-filtered response (after anti-hallucination). - Anti-hallucination: File paths extracted from diff headers, injected into
prompt. Post-parse filtering removes issues referencing files not in diff.
system_prompt_filepath traversal guard (canonicalized root check). - Composite action resilience: Version resolution retries 3x with fallback.
curl -sfL(fail on HTTP errors).d.get('tag_name', '')(no KeyError). - Release workflow v-prefix:
release.ymlstripsvfrom git tag to match CHANGELOG[X.Y.Z]format.TAG(with v) for display/URLs,VERSION(without) for changelog sed matching and asset naming. - Infisical secrets: All workflows use
secrets.INFISICAL_IDENTITY_ID— never hardcode identity IDs. - Documentation update before release: README config/features/flags, website configuration docs page, and homepage feature bullets MUST be updated to reflect new features BEFORE version bump and tagging.
These are hard-won lessons from actual development sessions. Follow them.
- One issue = one branch = one PR = wait CI green = merge = next. Never stack multiple features on one branch. Serial workflow prevents merge conflicts and makes bisecting bugs trivial.
- Local green ≠ CI green. CI may use a different Rust version that is stricter (e.g. treats dead_code as error, not warning). Always wait for CI to pass.
- Delete stale branches immediately after merge.
git push origin --delete <branch>. A cleangit branch -aimproves developer experience.
pubvisibility = API contract. Everypubadded must have justification. When exposing internals (e.g.SecurityPatternfields for MCP), consider adding getter methods instead of making fields public.Result<(), CoraError>is infectious. Changing a return type from()toResultwill propagate to every callsite. Plan the blast radius before changing signatures.- Use
edit(exact text replacement), notsedfor refactoring.sedapplies globally and can mangle struct literal instances when you only meant to change the struct definition. #[allow(dead_code)]for structs used only in#[cfg(test)]. Clippy in CI with-D warningstreats dead_code as error. Functions called only from tests need this annotation.
- Code Scanning alerts: evaluate before dismissing. Some are false positives
(test fixtures like
AKIAIOSFODNN7EXAMPLE), but others catch real bugs (e.g. redundantparse_diff()calls, broken line-based stdio parsing). - Dismiss with reason. Always provide
dismissed_reason("won't fix" or "false positive") so future reviewers understand the decision.
- MCP is simpler than you think. JSON-RPC 2.0 over stdio. No HTTP server needed. The client (Claude Code, Cursor, etc.) manages the lifecycle.
- Don't use line-based stdin parsing for JSON-RPC. Pretty-printed JSON spans multiple lines. Use brace-depth tracking instead.
- Reuse parsed data. If
parse_diff()already ran, pass theVec<FileChunk>to downstream functions. Never parse the same diff twice.
- Every regex pattern needs exemption logic. Skip test files, example keys, fixtures. Without exemptions, noise drowns out real findings.
- Balance sensitivity. Too strict = wall of false positives. Too loose = miss real vulnerabilities. Start conservative, tune based on real findings.
Before any release (version bump + tag), verify ALL of these are done. Missing any = release blocker.
- All target issues merged to
develop -
cargo test— all 567+ tests pass -
cargo clippy --all-targets -- -D warnings— clean -
cargo fmt --all -- --check— clean -
cargo build --release— no errors -
./target/release/cora --version— prints correct version -
./target/release/cora mcp --help— new subcommands work -
./target/release/cora review --staged— no crash on clean tree
Documentation drift is the #1 source of user confusion. Each file must reflect reality BEFORE version bump.
| File | What to check |
|---|---|
README.md |
"Why Cora" bullets match all features. Commands table includes all subcommands. Config example shows latest features. All links point to codecora.dev |
CHANGELOG.md |
New version entry with ALL changes (Added, Changed, Fixed, Removed). Link references at bottom include new version |
docs/changelog.md |
Mirrors CHANGELOG.md exactly — same content, same links |
docs/roadmap.md |
Completed items marked ✓ Done (not ◎ Planned). Future items accurate |
docs/getting-started.md |
Quick start still works. Next steps links valid. New major features mentioned |
docs/configuration.md |
All config keys documented with examples. New sections (quality gate, security scanner, MCP, profiles, custom rules, language analyzers) present |
docs/cli-reference.md |
All commands listed. New subcommands (e.g. cora mcp) included. Flags accurate |
docs/usage.md |
Review modes, output formats, exit codes up to date. New sections present |
docs/examples.md |
CI examples work. Marketplace action reference correct. Multi-platform examples present |
docs/providers.md |
Provider list, default models, env vars accurate |
docs/installation.md |
Version pin example uses latest. Platforms list accurate |
AGENT.md |
Code structure tree current. Test count current. Key files table current |
.agent.md |
Pre-release checklist current. CI checks count current. Module dependencies current |
- Feature coverage: Every new feature appears in README + CHANGELOG + docs/configuration.md + docs/roadmap.md
- Consistent terminology: Same name for features across all files (e.g. "Quality Gate" not "quality gate" or "gate check")
- No broken links: All
codecora.devlinks resolve. All internal doc links work - Version numbers: README install example, docs/installation.md pin example, AGENT.md test count — all match current version
- Star History chart: Repository list includes all relevant repos (e.g.
cora-cli,uteke)
- CI: 10/10 checks green on develop branch
- Code Scanning: 0 open alerts (fix or dismiss each with reason)
- No open PRs blocking the release
After merging to main:
-
release.ymltriggers onv*tag - 4 platform binaries published to GitHub Releases
-
crates.iopublish succeeds - Website (
codecora.dev) reflects new docs - Marketplace action still works (test on a PR)
Release authority belongs to the project owner only. The agent NEVER triggers a release without explicit approval. This workflow was established during v0.5.0 development.
Complete ALL items in the Pre-Release Checklist above. Every single checkbox must be green.
Generate a comprehensive pre-release report covering:
╔══════════════════════════════════════════════════════════════╗
║ LAPORAN PRE-RELEASE vX.Y.Z — FINAL ║
╚══════════════════════════════════════════════════════════════╝
📦 REPOSITORY: codecoradev/cora-cli
🌿 BRANCH: develop (N commits ahead of main)
🏷️ TAG: Next → vX.Y.Z
📋 CARGO: version = "0.X.Y" (needs bump)
✅ TESTS: N pass (unit + CLI + config)
✅ CLIPPY: Clean
✅ FORMAT: Clean
✅ CI: 10/10 green
✅ CODE SCANNING: 0 open
✅ OPEN PRs: 0
✅ OPEN ISSUES: N (all post-release scope)
📋 vX.Y.Z FEATURES:
1. ...
2. ...
📄 DOCS VERIFICATION:
✅ README.md — ...
✅ CHANGELOG.md — ...
✅ docs/* — ...
✅ AGENT.md — ...
⚠️ REMAINING (post-release):
• ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
👍 SIAP RILIS — menunggu approval.
The owner reviews the report and either:
- APPROVES → "oke kerjakan" / "go ahead" / "rilis"
- REQUESTS CHANGES → specifies what to fix first
- POSTPONES → "belum, tunggu dulu"
The agent must NEVER proceed without explicit approval.
# 1. Bump version
sed -i '' 's/version = "0.X.Y"/version = "0.X.Z"/' Cargo.toml
# 2. Update version references in docs
# - docs/installation.md: CORA_VERSION pin example
# - AGENT.md: test count if changed
# - docs/.vitepress/config.ts: nav bar version
# 3. Commit and tag
git add -A && git commit -m "chore: bump version to X.Y.Z"
git tag vX.Y.Z
git push origin develop --tags
# 4. release.yml auto-triggers:
# → sync develop → main (force push)
# → build 4 platforms (Linux x86_64, Linux ARM64, macOS ARM64, Windows)
# → publish to crates.io
# → create GitHub Release with changelog excerpt
# 5. deploy-website.yml auto-triggers (on push to main):
# → build VitePress docs
# → deploy to codecora.devAfter release completes, verify:
- GitHub Release page shows vX.Y.Z with correct changelog
- 4 platform binaries attached to release
- SHA256 checksums file included
-
crates.ioshows new version:cargo search cora-cli -
codecora.devreflects new docs - Marketplace action still works (test on a test PR)
- Close the released milestone/issues
- Update roadmap: mark released items
If release fails or has critical bugs:
- Delete the tag:
git push origin --delete vX.Y.Z - Delete the GitHub Release
- Yank from crates.io:
cargo yank cora-cli@X.Y.Z - Fix on develop, re-tag when ready
- Patch (0.4.6 → 0.4.7): Bug fixes, docs updates, no new features
- Minor (0.4.x → 0.5.0): New features, backwards compatible
- Major (0.x → 1.0.0): Breaking changes
- Pre-release: Tag with suffix (v0.5.0-beta.1) —
release.ymlmarks as prerelease
- Documentation drift is the biggest risk. PRs from other agents may merge code without updating docs. Always audit docs coverage BEFORE release.
- Ghost versions in CHANGELOG are dangerous. If a version entry exists but has no tag, merge it into the next real version before release.
- Test count changes with every PR. Verify actual test count matches AGENT.md.
- Deploy-website trigger must be main-only. develop pushes should never deploy to production.
- Code Scanning alerts accumulate. Dismiss false positives with reason, fix real ones.
When submitting cora to directories, aggregators, or showcases (Trendshift, etc.):
Cora CLI — Open-source AI code review tool written in Rust. BYOK (Bring Your Own Key) — works with any OpenAI-compatible LLM. Runs locally via CLI, CI/CD, pre-commit hooks, or as an MCP server for AI coding agents (Claude Code, Cursor, Copilot).
Features: diff-based review, static security scanning (11 regex patterns), quality gate with configurable thresholds, language-specific analyzers (Dart/Flutter, Svelte, TypeScript, Go, Rust, Python), secret detection, custom rule engine, quality profiles, auto-chunking for large PRs, and SARIF output for CI integration.
- Test count (495+)
- Lines of Rust code (16,800+)
- CI checks (10)
- GitHub Marketplace action published
- MCP server with 5 tools
- MIT license
- Active development cadence
- README accurately describes ALL current features (not outdated)
- All docs synced (changelog, roadmap, configuration, CLI reference)
- No stale "Planned" items on roadmap that are actually done
- Star History chart includes all relevant repos