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

CommandWhat it does
mainark startCreate/link Linear issue; rename branch to feat/ful-<n>-<slug> (before push)
mainark publishPR title FUL-n: …, Linear comment with PR URL, optional In Review
mainarkFull loop: validate → Claude review → fix → commit/push (default mode: local)
mainark validatepnpm mainark:validate in target repo
mainark reviewDefault — full loop in chosen mode
mainark review --mode cloudClaude review + Codex fix (Cursor fallback)
mainark review --mode localClaude review + local Cursor fix (+ Codex SDK fallback)
mainark review --executor <name>Override fix backend: auto, codex, cursor, or local
mainark review --review-onlyClaude review + checklist only (no fix)
mainark review-claudeSame as review --review-only
mainark review --postAlso post full review as PR comment
mainark fixFix only from existing .reviews/ (retry after failure)
mainark fix --re-reviewRefresh Claude review, then run fix
mainark status 529Terminal checklist (like your paste)
mainark status-post 529Upsert PR checklist comment
mainark devStart Linear orchestrator (watch mode)
mainark serveOrchestrator 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:

  1. mainark -C /path/to/repo …
  2. MAINARK_TARGET=/path/to/repo
  3. Current directory (if it has .git and .ai/reviewer.md or mainark:validate)
  4. REPO_PATH in 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.

ModeReviewFix (default --executor auto)
local (--mode local, default)Claude CLILocal Cursor agent → Codex SDK fallback on failure
cloud (--mode cloud)Claude CLICodex 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

ModeCommandUse when
Local PR loopmainarkYou have a branch + PR; want review/fix on your machine
Linear orchestratormainark devTickets 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).

HookPurpose
validateWithLogCustom validate runner (default: pnpm mainark:validate + log)
validateFailureArtifactsBuild .reviews from validate failures
postFixPR description / SaaS template after fix
resolveWorkspaceOverride PR worktree resolution
consensusCheckImplement 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--resume verifies PRs merged via gh
  • checkpoint: approve — human sign-off; --resume without merge check
  • stack: true + base: stack — PR chains on previous issue branch (within-track only)
  • Parallel roots in a phase — multiple base: main lines, no stack: true
  • State: .reviews/epic-<EPIC>.state.json in 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).

StepPrimaryFallback
Pre-push reviewClaudeCodex review-local
Pre-push fixesCursor agentCodex fix-local
PR reviewClaudeCodex reviewer
Ticket implementCursor agentCodex developer
PR review fixesCursor agentCodex 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:

StageMeaning
implementingCursor implement agent
prepush · reviewingClaude local review
prepush · fixingCursor local review fixes
prepush · blockedvalidate failed, no review, or pending must_fix/missing_tests
prepush · local-cleanpassed local-is-clean (ready to push)
shippedPR 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:

  1. Local — validate → Claude review on git diff vs stackBase / main → Cursor fixes → loop until clean. Artifacts: .reviews/local-FUL-407.json|.md (no PR yet).
  2. Push + publish — stacked PRs open only after local pass.
  3. Promote — copies local review to .reviews/pr-N.* and posts the PR checklist comment.
  4. Optional PR loop — set MAINARK_PR_REVIEW_AFTER_PUSH=1 to run the full until-clean on 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_requestdraft — skip CI on drafts; run when marked ready for review.
  • Label gate — e.g. only run full CI when label ready-for-ci is present (mainark can add it in publish later).
  • Do not rely on push to main for feature work; stacked PRs still use pull_request per 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/mainarkscripts/mainark.sh. To use this package as the source of truth:

  1. bun link from Mainark (or add Mainark as a devDependency).
  2. In Fulreach package.json, set "mainark": "mainark" in bin or scripts to delegate to the linked CLI.
  3. Keep Fulreach-specific .ai/fulreach-standards.md etc.; the reviewer reads any .ai/*-patterns.md and *-standards.md automatically.

Legacy pnpm review scripts can stay as thin wrappers calling mainark.