Mainark local CLI
Terminal workflow for the PR loop you run today in Fulreach: validate → Claude review → GitHub checklist comment → Cursor fixes.
This lives in the Mainark repo; it runs in your target app repo (Fulreach, etc.) via MAINARK_TARGET, -C, REPO_PATH in Mainark .env, or your current directory.
Install
From the Mainark repo:
bun install
bun link # puts `mainark` on your PATH
Or without linking:
/path/to/mainark/bin/mainark --help
Target repo setup
In the app repo (once):
cd ~/fulreach
mainark init # copies default .ai/reviewer*.md if missing
Ensure package.json has a validation script the loop can call:
"scripts": {
"mainark:validate": "nx affected -t typecheck,lint,test,build --base=origin/main --head=HEAD --parallel=3"
}
Requires: gh (authenticated), claude (claude login), cursor agent (cursor agent login or CURSOR_API_KEY), pnpm.
Commands
| Command | What it does |
|---|---|
mainark start | Create/link Linear issue; rename branch to feat/ful-<n>-<slug> (before push) |
mainark publish | PR title FUL-n: …, Linear comment with PR URL, optional In Review |
mainark | Full loop: validate → Claude review → fix → commit/push (default mode: local) |
mainark validate | pnpm mainark:validate in target repo |
mainark review | Default — full loop in chosen mode |
mainark review --mode cloud | Claude review + Codex fix (Cursor fallback) |
mainark review --mode local | Claude review + local Cursor fix (+ Codex SDK fallback) |
mainark review --executor <name> | Override fix backend: auto, codex, cursor, or local |
mainark review --review-only | Claude review + checklist only (no fix) |
mainark review-claude | Same as review --review-only |
mainark review --post | Also post full review as PR comment |
mainark fix | Fix only from existing .reviews/ (retry after failure) |
mainark fix --re-review | Refresh Claude review, then run fix |
mainark status 529 | Terminal checklist (like your paste) |
mainark status-post 529 | Upsert PR checklist comment |
mainark dev | Start Linear orchestrator (watch mode) |
mainark serve | Orchestrator one-shot |
Examples:
cd ~/fulreach
mainark start --title "Unified voices library" # before first push
git push -u origin HEAD
mainark publish # PR + Linear link
mainark review --pr 606 # full loop (local Cursor fix)
MAINARK_MODE=cloud mainark review --pr 606 # Codex-primary fix (hands off laptop)
mainark review --review-only # Claude verdict only (no fix)
mainark fix 529 # retry fix from .reviews
Requires in Mainark .env: LINEAR_API_KEY, and optionally LINEAR_TEAM_NAME=fulreach, MAINARK_BRANCH_PREFIX=feat/ful-.
Pointing Mainark at a repo
Priority:
mainark -C /path/to/repo …MAINARK_TARGET=/path/to/repo- Current directory (if it has
.gitand.ai/reviewer.mdormainark:validate) REPO_PATHin Mainark's.env(same path the orchestrator clones)
Shell alias (optional):
alias mainark='MAINARK_TARGET=~/fulreach mainark'
Outputs (in target repo)
.reviews/pr-<N>.json— structured verdict.reviews/pr-<N>.md— human review.reviews/pr-<N>.cursor-fix.log— Cursor agent log.reviews/pr-<N>.status-comment.md— checklist body posted to GitHub
PR comments use <!-- mainark-review-status --> (also updates legacy Fulreach markers).
Note: mainark review --review-only exits with code 1 when the verdict is FAIL (for scripts/CI). The full loop passes --continue-on-fail-verdict internally so fixes still run when there are MUST FIX items.
ReviewPipeline modes
One command runs all phases internally (validate → review → fix). Use flags or env to pick the fix backend; Claude review stays on the local CLI for now.
| Mode | Review | Fix (default --executor auto) |
|---|---|---|
local (--mode local, default) | Claude CLI | Local Cursor agent → Codex SDK fallback on failure |
cloud (--mode cloud) | Claude CLI | Codex SDK primary → Cursor fallback |
mainark review --pr 606 # local mode (default)
mainark review --pr 606 --mode cloud # cloud fix chain
mainark review --pr 606 --executor codex # force Codex fix only
MAINARK_MODE=cloud mainark review --pr 606 # env override
Escape hatches: mainark review-claude (review only), mainark fix (fix only / retry).
PR3: The fix phase routes through src/cli/reviewPipeline.ts and typed executors, but still delegates to the same bash scripts (cursor-fix-pr-review.sh, codexFallback.ts) so local behavior is unchanged. Set MAINARK_FIX_TS=0 to use the pre-PR3 inline bash router.
Orchestrator vs local loop
| Mode | Command | Use when |
|---|---|---|
| Local PR loop | mainark | You have a branch + PR; want review/fix on your machine |
| Linear orchestrator | mainark dev | Tickets labeled orchestrator-managed → agents → PRs in REPO_PATH |
Both can share the same REPO_PATH / Fulreach clone.
Note: When the target repo has scripts/mainark-hooks/manifest.json (e.g. Fulreach), Mainark loads optional hooks for validate-with-log, post-fix PR description, and workspace resolution. Mainark owns review/fix; the target repo owns pnpm mainark:validate and hooks only.
Set MAINARK_LEGACY_REVIEW=1 to restore delegation to $MAINARK_ROOT/scripts/mainark.sh (deprecated).
Target repo hooks (Fulreach)
Optional manifest: $MAINARK_ROOT/scripts/mainark-hooks/manifest.json (see cli/lib/hooks/manifest.schema.json).
| Hook | Purpose |
|---|---|
validateWithLog | Custom validate runner (default: pnpm mainark:validate + log) |
validateFailureArtifacts | Build .reviews from validate failures |
postFix | PR description / SaaS template after fix |
resolveWorkspace | Override PR worktree resolution |
consensusCheck | Implement consensus gate |
Repo-only scripts (via manifest repoScripts): mainark-update-pr-description.mjs, etc.
Phased epic implement (Linear plan)
Epics with ## Mainark plan in the Linear description run phase-by-phase with human checkpoints (checkpoint: merge or checkpoint: approve). See Human checkpoints and merge vs stack.
mainark plan FUL-515 # parse plan, no side effects
mainark implement FUL-515 --dry-run # same
mainark implement FUL-515 # run current phase (sequential default)
mainark implement FUL-515 --resume # after merges, advance phase
mainark status FUL-515 # phase progress + PR stack
mainark status 626 # PR checklist — unchanged
mainark implement FUL-521 # leaf issue (no plan) — unchanged
Plan format (in epic Linear description)
## Mainark plan
### Phase 1 — Foundation
checkpoint: merge
- FUL-516 base: main
- FUL-517 base: main
### Phase 2 — Gated module
checkpoint: approve
- FUL-518 base: main
### Phase 3 — Setup
checkpoint: merge
stack: true
- FUL-521 base: main
- FUL-522 base: stack
checkpoint: merge—--resumeverifies PRs merged viaghcheckpoint: approve— human sign-off;--resumewithout merge checkstack: true+base: stack— PR chains on previous issue branch (within-track only)- Parallel roots in a phase — multiple
base: mainlines, nostack: true - State:
.reviews/epic-<EPIC>.state.jsonin target repo --parallel(opt-in): run current phase via worktree stack bootstrap
Coexists with .mainark/epics.json queue (mainark queue / mainark next).
Parallel features (worktrees)
Run several spec’d features at once without branch mix-ups. Stay in the Fulreach repo — Mainark CLI resolves via bun link + LINEAR_API_KEY in Mainark .env.
After creating issues in Cursor (Linear MCP)
cd ~/fulreach
# Full pipeline: worktrees → agents → local review → push → stacked PRs → promote to PR
# No ids: every issue in Linear state Todo (optional MAINARK_IMPLEMENT_LABEL to filter)
mainark implement
mainark implement FUL-407 FUL-409 FUL-410 FUL-411 FUL-408
# Preview queue without running agents
mainark implement --no-ship --plan
# Skip push/review (inspect diffs first)
mainark implement --no-ship FUL-407 …
# Optional plan preview
mainark parallel --plan FUL-407 FUL-411 FUL-408
# Partial steps
mainark parallel FUL-407 … # setup only
mainark parallel agents
mainark parallel ship --yes-push
Set Linear blocking relations (FUL-411 blocked by FUL-407, etc.) so stack order is correct. Legacy merge-first: mainark implement --no-stack ….
Codex fallback (safety layer)
If Claude review or Cursor implement/fix fails, the CLI retries with Codex SDK when OPENAI_API_KEY is in Mainark .env (on by default; MAINARK_CODEX_FALLBACK=0 to disable).
| Step | Primary | Fallback |
|---|---|---|
| Pre-push review | Claude | Codex review-local |
| Pre-push fixes | Cursor agent | Codex fix-local |
| PR review | Claude | Codex reviewer |
| Ticket implement | Cursor agent | Codex developer |
| PR review fixes | Cursor agent | Codex fix |
Cursor model: Local fix/implement defaults to --model Auto (MAINARK_CURSOR_MODEL, default Auto) so Pro premium quota is not burned. Set MAINARK_CURSOR_MODEL=default to omit --model (CLI default). Lowercase auto is normalized to Auto.
Usage limits: If Cursor logs a Pro usage/quota limit (“Switch to Auto”, etc.), soft --continue retries are skipped and Codex runs immediately (same as exhausting retries). Auth failures still do not fall through to Codex.
Extra logs: .reviews/local-FUL-N.codex-fix.log, .reviews/pr-N.codex-fix.log, .mainark/logs/implement-FUL-N.codex.log.
Manual / PR-based
# Register worktrees (existing PRs or Linear ids)
mainark parallel add 529 530
mainark parallel add FUL-123 FUL-124
mainark parallel add --new FUL-125 --title "Reconnect landing"
# 2) Open each tree in Cursor (or separate terminals)
mainark parallel paths
# 3) After you implement in each tree — push, open PRs, review until clean
mainark parallel push --yes
mainark parallel publish
mainark parallel until-clean --jobs 2
# Or one-shot tail (after implementation):
mainark parallel ship --yes-push
Registry: .mainark/parallel.json in the target repo. Worktrees default to ../wt-<repo-name>/ next to the clone (MAINARK_PARALLEL_BASE to override).
Implement progress (second terminal)
While mainark implement runs Cursor agents in parallel:
mainark parallel agents-status # one-shot snapshot
mainark parallel agents-status --watch # refresh every 3s until all done/failed
mainark parallel agents-status FUL-431 # filter slots
Per slot, shows pipeline stage:
| Stage | Meaning |
|---|---|
implementing | Cursor implement agent |
prepush · reviewing | Claude local review |
prepush · fixing | Cursor local review fixes |
prepush · blocked | validate failed, no review, or pending must_fix/missing_tests |
prepush · local-clean | passed local-is-clean (ready to push) |
shipped | PR exists on registry slot |
Also: orchestrator line (implement vs ship), commit, pending counts, browse/tail hints. Files: .mainark/implement-FUL-N.status.json, .mainark/logs/parallel-local-FUL-N.log, .reviews/local-FUL-N.json.
Pre-push review (hybrid)
mainark implement / mainark parallel ship now runs local review before the first push:
- Local — validate → Claude review on
git diffvsstackBase/main→ Cursor fixes → loop until clean. Artifacts:.reviews/local-FUL-407.json|.md(no PR yet). - Push + publish — stacked PRs open only after local pass.
- Promote — copies local review to
.reviews/pr-N.*and posts the PR checklist comment. - Optional PR loop — set
MAINARK_PR_REVIEW_AFTER_PUSH=1to run the fulluntil-cleanon GitHub after push (off by default).
Manual step: mainark parallel local-until-clean (same as ship step 1).
until-clean (PR-based) still applies when you already have PRs or want a second pass on CI.
Logs: .mainark/logs/parallel-local-<key>.log (pre-push), .mainark/logs/parallel-<key>.log (PR loop).
Cursor: ask the agent to run mainark parallel paths and implement each listed cd path, then mainark parallel ship --yes-push when done.
GitHub Actions (Fulreach)
Keep pull_request triggers for opened and synchronize. That is the right hook: CI runs when the PR exists and updates after push — which now happens after local review, not on raw agent output.
Avoid (or narrow) workflows that run on every push to feat/** before a PR exists, if those duplicate expensive checks on unreviewed commits.
Suggested pattern:
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
# Optional: drop bare push to feature branches, or gate with:
# push:
# branches: ['feat/**']
# paths-ignore: ...
Optional extras:
pull_request→draft— skip CI on drafts; run when marked ready for review.- Label gate — e.g. only run full CI when label
ready-for-ciis present (mainark can add it inpublishlater). - Do not rely on
pushtomainfor feature work; stacked PRs still usepull_requestper branch.
After ship, GitHub gets a checklist comment from the promoted local review; you do not need a separate “review bot” Action unless you want server-side re-review.
Fulreach migration
Fulreach already ships bin/mainark → scripts/mainark.sh. To use this package as the source of truth:
bun linkfrom Mainark (or add Mainark as a devDependency).- In Fulreach
package.json, set"mainark": "mainark"inbinor scripts to delegate to the linked CLI. - Keep Fulreach-specific
.ai/fulreach-standards.mdetc.; the reviewer reads any.ai/*-patterns.mdand*-standards.mdautomatically.
Legacy pnpm review scripts can stay as thin wrappers calling mainark.