Skip to main content

An AI-native dev harness. Solemnly swear you're up to no good.

Project description

marauders-mischief

An AI-native dev harness. Solemnly swear you're up to no good.

A workflow for Claude Code that makes a coding agent behave like an engineering team instead of a single overcaffeinated junior.

Why

If you've used a coding agent for more than half an hour, you've watched it do at least one of these:

  • Delete the failing test to make the suite green.
  • Confidently report "feature shipped" when the feature doesn't work.
  • Refactor while you asked it to fix a bug, breaking three other things on the way.
  • Lose its mind around the second hour of a long task and forget what you asked for.
  • Run overnight in autonomous mode and commit garbage to main while you slept.

Agents are very good at writing code. They are very bad at the parts of engineering that aren't writing code: planning, peer review, knowing when to stop, knowing when to ask. Most setups paper over that gap by just letting it happen and hoping for the best.

mar is the setup that doesn't. It splits each task into the stages a real team uses (research, plan, build, test, review, integrate), runs each stage in a fresh-context sub-agent that hasn't been defending its own previous choices, and enforces the boundaries mechanically. Not by asking nicely.

What it does

For every task you give it:

  1. Research — pulls together what you need to know about the problem (the codebase, the libraries, the prior art). Surfaces options; doesn't decide.
  2. Plan — an author writes the plan. A skeptic in a fresh context tries to break it. They reconcile, or you do.
  3. Execute — small steps, fresh agent per step, no accumulated context drift.
  4. Test — multiple test kinds in parallel: unit, eval, agent-flow, browser, perf. The orchestrator picks which apply to what changed.
  5. Refine — when something fails, the fix goes in the code. Not in the test. A PreToolUse hook physically blocks the agent from writing to tests/, fixtures, snapshots, or eval data.
  6. Simplify — a cleanup pass. Same author/skeptic pattern. Reverts itself if cleanup regresses anything.
  7. Verify — a structured pre-PR adherence check. Classifies failures by who should fix them (refine / replan / user) instead of bouncing everything back to refine.
  8. Review + Tester — fresh-context PR review (inline comments on the actual PR) and functional validation (does the feature work for a user?), in parallel. Optionally a second reviewer from a different model entirely (Codex/GPT) — the surest way to catch what a reviewer trained like your builder would wave straight through.
  9. Integrate — squash merge with the commit story you approved in step 2.

Every stage runs as a fresh sub-agent. None of them inherit the running history. The only thing that persists between stages is files: plan.md, test-report.md, verification.md. Context-as-files, not context-as-tokens. The plan, not the chat log, is the source of truth.

What it stops

Failure mode What stops it
Agent weakens a failing test instead of fixing the code tests/, fixtures, snapshots, eval data are write-blocked during refine via the scope hook
A refine cycle introduces new failures while patching old ones Each round is checkpointed; new failures auto-revert and escalate via the refine-regression-wall safeguard
Plan and shipped reality drift apart Verify runs 5 mechanical pre-checks (diff vs scope, unresolved questions, unchecked manual steps, deviations triage, plan-quality) before reasoning, with structured evidence required for every adherence claim
Long agents lose track of state Each build step is a fresh sub-agent reading the previous step's handoff file
Autonomous mode ships broken work silently 15+ always-on safeguards pause autonomous sessions on every known silent-failure mode
Agent self-grades and rubber-stamps its own work Author/skeptic split at design-time stages (research, plan, simplify); fresh-context review at Stage 5
Long-lived branches diverge and produce merge nightmares One phase, one branch, one PR. Squash-merged at integrate. Phases run sequentially

Autonomy modes

Pick how much you want to be in the loop:

  • interactive — every gate pauses for your approval.
  • normal — gates pause for important things; routine stuff auto-passes.
  • streamlined — auto-passes if no issues; gates only when something needs you.
  • autonomous — runs end-to-end. You provide no input after /mar:session-start until the session finishes or a safeguard pauses it.

All four modes use the same safeguards. Autonomous is allowed to be unattended because the safeguards make it safe to be unattended, not because nobody's looking.

Programs — when the build is bigger than one session

One session, one task. Fine for a bug or a feature. But a whole app is dozens of sessions over weeks, and every session starts amnesiac — session 12 has no idea what contract session 2 agreed to. That's how greenfield builds rot: each session quietly re-decides settled things, and three weeks in, nothing agrees with anything.

A program is the memory that outlives the session. You birth one once with /mar:program-start — a visionary and a skeptic argue out the shape of the thing while you call the shots — and it lays down a spine: the charter, the invariants you won't trade away, the contracts between the pieces. After that, every session is a slice. It reads the spine before it plans, builds against it, and writes back what it learned at integrate. Decisions compound instead of evaporating.

The map stays yours to draw. Births and big pivots are human calls — the agents fill in the territory, they don't redraw it. When the thing stands on its own two feet, /mar:program-graduate rolls up the spine and sends it on its way.

Today it runs one slice at a time, in order. The spine is there to keep a long build honest, not fast — parallelism across a program comes later.

YOLO mode (/mar:program-yolo) — fully autonomous, from a PRD. Hand it one north-star spec and nothing else: it births the program from that seed, derives the build sequence, and grinds through the slices end-to-end with no further input. The structure is identical — same birth, slices, spine, graduation — the human just leaves the loop and a built-in driver turns the crank. The safety floor stays intact even here: a market/moat KILL halts birth, contract and charter changes are never auto-decided (they park to a queue the build flows around), and graduation stays human (it writes durable memory). "Done" means build-complete, ready to graduate — not graduated. Meant for throwaway greenfield/test programs in a dedicated tree, not the venture you can't roll back.

Run it through the launcher to put a hard cost cap on the night: bash ops/workflow/scripts/yolo-run.sh prd.md --budget-usd 100 --max-hours 8. On Claude Code the dollar cap is a real stop (--max-budget-usd); on Cursor there's no per-run dollar cap, so the launcher enforces the wall-clock and you set an account spend limit (or leave on-demand billing off) as the money backstop.

Going bigger — mar as a worker in a loop

Status: experimental, in testing. mar runs a task end-to-end today. Bolting an external driver agent on top — one that dispatches mar sessions on its own — is a thin connection, because mar already exposes the surface to drive. That connection is what we're testing now, not a big build.

mar finishes a task and stops. Right behavior for a task. But a lot of real work isn't one task — it's "keep going until this is done," where done is a moving target a human usually babysits. That's a goal loop, and it has five parts. Miss one and you don't have a loop, you have a runaway:

  • Goal — a definition of done you can check: tests pass, CI green, a judge agent's rubric satisfied.
  • Worker — one fresh-context attempt per turn. A bash agent, a ralph iteration, or a whole mar session.
  • Verifier — deterministic checks first (tests, types, CI), a fresh-context judge for the rest. Never the worker grading its own homework.
  • State — lives in files and git between turns. The repo is the memory; each turn starts clean.
  • Stop — goal met, max iterations, budget cap, or "ask the human." A loop without a stop condition is a bug, not a feature.

The trick is dumb driver, smart iterations: the thing running the loop is a while-loop or a stop-hook — cheap, boring plumbing. The intelligence lives in the worker and the verifier. (Huntley's ralph is literally bash. mar's own refine stage is this exact shape one level down: tests are the verifier, and the hook that blocks edits to tests/ is what stops the worker from cheating the reward.)

mar is the premium worker. Where a bash loop throws a raw agent at the problem, you hand a turn to a full mar session — research, plan, build, review, the works — and get an engineered attempt instead of a vibe. And mar is made of goal loops: refine, verification, the program tier itself. Loops all the way down.

Driving it — four rungs of ambition:

  • ralph — minimal. A bash loop re-running an agent against PROMPT.md until it writes .ralph-done. Dumb on purpose. Lives in a worktree; skips permission prompts.
  • /loop (Claude Code) — a standing watchman. Wake on a cadence, walk a checklist, fix the small stuff, spawn a goal loop when there's real work.
  • YOLO mode (/mar:program-yolo) — the one driver mar ships itself, scoped to a single program: feed it a PRD and it births and builds the whole thing end-to-end (see "Programs" above). The driver is built-in because the loop is the program tier's own — but it stays scoped to one program; mar still doesn't grow a general orchestrator.
  • A driver agent — the endgame for everything wider than one program. An external orchestrator — Hermes, OpenClaw, or anything that can drive a CLI — connects to mar from outside: it dispatches sessions across programs and repos, reads the spine for state, and escalates to you only for the calls that are actually yours. mar just has to be drivable, and it is.

One rule survives every rung: contract and charter changes are never auto-decided. A driver earns more rope by explicit promotion, never by drift. Even YOLO mode — which automates gating, birth included, from a PRD seed — holds this floor: a kill verdict halts, contract changes park for a human instead of being absorbed, and graduation stays human. The decisions that silently corrupt a build if they're wrong are the ones that never go auto — by design, possibly forever.

Parallelism comes from lanes, not from inside a build: each concurrent task is its own git worktree, running beside the others. The loop above them stays single-minded; the fan-out is structural.

Requirements

  • Python 3.12+ — the mar CLI and the harness scripts require it. (mar init will resolve-fail on 3.11 or older.)
  • uv on your machine — the harness's memory pipeline and hooks run via uv run, so uv is needed at session time no matter how you install mar itself. (curl -LsSf https://astral.sh/uv/install.sh | sh)
  • A coding-agent CLI: Claude Code and/or Cursor CLI (cursor-agent).
  • gh authenticated for your repo (gh auth login).

Install

mar is a one-shot scaffolder — you run it to set a repo up, then rarely again (mar update). Install it per-project, not globally. Pick one:

uv venv (recommended):

cd my-project
uv venv --python 3.12              # 3.12+ required; uv fetches it if missing
uv pip install marauders-mischief
uv run mar --version               # → mar 0.16.0  (only inside this project)

Ephemeral — nothing installed (uv's tool runner):

uvx --from marauders-mischief mar --version

Standard venv + pip:

python3.12 -m venv .venv && source .venv/bin/activate
pip install marauders-mischief
mar --version

Installing mar globally (pipx install / uv tool install) works but isn't recommended — it's a scaffolder, not a daemon. To undo a global install: uv tool uninstall marauders-mischief (or pipx uninstall marauders-mischief).

In the commands below, mar means the binary on your activated venv's PATH; on the uv-venv route prefix it with uv run (e.g. uv run mar init).

Quickstart

mkdir my-project && cd my-project
git init
gh repo create --private --source=. --remote=origin  # or use an existing repo

mar init                 # Claude Code (default)
# mar init --target both # Claude Code AND Cursor CLI (shared spine, both front doors)
# mar init --target cursor

# Set up the memory pipeline (its own uv project):
cd ops/memory && uv sync && cd -

# Fill in the two files mar wants you to fill in:
#   .brain/CONTEXT.md  — what you're building, in plain language
#   .brain/STATE.md    — where you are right now

git add -A && git commit -m "chore: scaffold mar harness"

mar installs once and is committed to the repo; git worktrees inherit it (no re-init per worktree). With --target both, choose the harness when you open the lane — claude or cursor-agent. See docs/cursor-adapter-design.md for the Cursor adapter (incl. the per-agent model map and --models profiles).

Then open Claude Code (or Cursor CLI) and run a session. Commands below use Claude Code's /mar: namespace; under Cursor the same commands are flat /mar- (e.g. /mar-session-start, /mar-program-yolo) — Cursor names commands by filename and has no :-namespace.

/mar:session-start "fix the auth token refresh bug"
# picker: size (S/M/L/XL), kind, guidance, autonomy

/mar:plan
# → research, plan, plan-skeptic review

/mar:approve plan

/mar:ship
# → branch, execute, test, refine, simplify, verify, review + tester, draft PR

/mar:approve integrate
# → gh pr ready + gh pr merge --squash

For a tiny task (typo, isolated bug) the loop fits in 5-15 minutes. For a multi-day feature you'll plan it as L or XL and run multiple phases sequentially, each one its own PR.

Slash commands

Command What it does
/mar:session-start Start a session (size / kind / guidance / autonomy picker)
/mar:plan Run the current planning sub-stage
/mar:ship The build loop: branch → execute → test → refine → simplify → verify → review + tester → draft PR
/mar:integrate Compose the commit story; pause for approval
/mar:approve <gate> Pass a gate (research / meta-plan / plan / integrate / …)
/mar:iterate <gate> "<note>" Refine the gate's output without losing position
/mar:revise <target> "<note>" Back up to a prior stage with a note
/mar:redirect "<direction>" Pivot the session entirely
/mar:reject <gate> Discard the gate's artifact and back up
/mar:status Where am I?
/mar:session-list All active and archived sessions
/mar:retrospect <id> Post-archive audit; surfaces framework feedback for the maintainer
/mar:program-start Birth a program: visionary + skeptic spar over the spine, you arbitrate
/mar:program-yolo Birth + build a program end-to-end, fully autonomously, from a single PRD seed
/mar:program-graduate Retire a program once the app stands on its own

There are more (idea capture, session resume, the rest of the program tier, between-session machinery). See .claude/commands/mar/ after install, or the full spec at ops/workflow/README.md.

One session per working tree — the harness won't let two run loose in the same checkout and trample each other's git. Want two going at once? Give each its own git worktree; they share the spine, not the working directory.

What mar init writes

your-project/
├── CLAUDE.md                   Project-level context. You own it.
├── .brain/                     Curated context. You own it.
│   ├── CONTEXT.md              What you're building.
│   ├── STATE.md                Current state of play.
│   ├── STACK.md                Stack decisions.
│   ├── DECISIONS.md            Why you made the calls you made.
│   └── RISKS.md                What could go wrong.
├── .claude/
│   ├── agents/                 ~30 sub-agents (research, plan, execute, review, …)
│   ├── commands/mar/           26 slash commands (/mar:*)
│   └── settings.json           Hooks + permissions. mar manages its own keys.
├── .cursor/                    Only with --target both / cursor:
│   ├── hooks.json              Cursor hooks (mar-owned). Reads the same ops/ scripts.
│   ├── cli.json                Starter CLI permissions (scaffolded — yours after).
│   └── commands/mar-*.md        The same commands, plain-markdown for Cursor (/mar-*).
├── ops/workflow/               Spec, scripts, templates
└── .mm/lockfile.json           SHA256 of every framework file. `mar update` reads this.

With --target both, Cursor reads CLAUDE.md and .claude/agents/ natively, so those aren't duplicated under .cursor/ — both harnesses share one spine.

Every shipped file falls into one of three classes:

  • framework — owned by mar. Overwritten on mar update. Drift is detected if you edit.
  • scaffolded — created once at init. Yours forever after. mar never touches.
  • merged — mar owns specific keys; you own everything else in the same file (.claude/settings.json, .gitignore).

This split is what lets mar update upgrade the framework without clobbering your project.

Development

git clone git@github.com:sindreespeland/marauders-mischief.git
cd marauders-mischief
uv sync --dev

uv run pytest
uv run ruff check src tests

# Try mar init against a throwaway directory
mkdir /tmp/test-install && cd /tmp/test-install
uv run --project ~/repos/marauders-mischief mar init

Status

Pre-release (v0.20.0). The build loop is hardened end-to-end and the PR-native flow is live. The last few releases added the program tier (v0.14), an opt-in second reviewer from a rival model (v0.15), a Cursor CLI adapter plus one-session-per-worktree parallelism (v0.16; see docs/cursor-adapter-design.md), YOLO mode (v0.17): fully autonomous, PRD-seeded program runs via /mar:program-yolo, and — newest — a YOLO launcher with a hard cost cap (v0.18; yolo-run.sh --budget-usd). Smoke-test against a throwaway repo before you trust it on anything you'd miss.

Each minor release hardens one stage. See the roadmap below or the GitHub Releases page for what landed when.

Roadmap

Shipped:

  • v0.5 — phase research: hypothesis-driven, 5-section structured output, optional skeptic
  • v0.6 — phase plan: author + skeptic at per-phase grain, AI-aware checks
  • v0.7 — execute step-decomposition: bounded context per build step
  • v0.8 — multi-kind testing: strategist + parallel runners (unit/eval/agent-flow/browser/perf), target-aware refine
  • v0.9 — simplify hardened: dynamic conventions, targeted re-test, revert on regression
  • v0.10 — refine hardened: protected surfaces (tests/fixtures/snapshots/evals), checkpoint + revert across all four refine loops
  • v0.11 — verify hardened: route-based dispatch (refine/replan/user), mechanical pre-checks, structured evidence
  • v0.12 — PR-native flow: draft PR at Stage 2.2, review/tester in PR mode, squash-merge at /mar:approve integrate
  • v0.13 — retrospect redesigned: per-session output, maintainer feedback via chat, no framework-shared file in user repos
  • v0.13.1 — first-run fix: /mar:ship auto-creates the phase branch
  • v0.13.2CLAUDE.md template brought up to date (session awareness, files-as-source-of-truth table, safeguards list, post-v12 repo map)
  • v0.13.3 — critical fix: .claude/settings.json hook shape corrected (was being rejected by Claude Code, silently disabling the scope hook)
  • v0.14 — program tier: a 4th level above session, a persistent spine for multi-session greenfield builds; all sub-agents baselined to Opus 4.8
  • v0.15 — opt-in cross-model review: a second reviewer (Codex / GPT-5.5) at Stage 5, advisory, never gating — a different model catches what yours won't
  • v0.16 — Cursor CLI adapter (dual-install, one shared spine, both front doors); one active session per working tree (parallel sessions live in separate worktrees)
  • v0.17 — YOLO mode (/mar:program-yolo): fully autonomous, PRD-seeded program runs — birth + slice-chaining driver, contract changes park instead of halting; safety floor (KILL, contract-decisions, graduation) stays human
  • v0.18 — YOLO launcher with a hard cost cap (yolo-run.sh --budget-usd N): real per-run dollar stop on Claude Code (--max-budget-usd); wall-clock + account-limit guidance on Cursor (no native per-run $ cap); in-band --budget hours=/slices= graceful halts
  • v0.18.1 — fix: shipped .cursor/cli.json carried an invalid top-level version key that made cursor-agent refuse to start ("Unrecognized key"); removed it (hooks.json correctly keeps version)
  • v0.18.2 — yolo credential safety: a missing credential / un-created external resource (e.g. a Telegram bot) now fires the external-setup-required safeguard — autonomous/yolo pauses and waits (resumable) instead of an interactive prompt, and the build is explicitly forbidden from mocking/stubbing/faking/skipping a credentialed integration to dodge a missing key
  • v0.19.0 — Cursor CLI lane actually works: verified against cursor-agent 2026.06 and fixed four silent breakages — slash commands install flat as /mar-* (Cursor has no :-namespace), scope enforcement now matches Cursor's real preToolUse payload (was inert), memory injection emits Cursor's additional_context envelope, and memory flush moved to sessionEnd (stop never fires in the CLI). Per-harness I/O isolated in ops/workflow/scripts/harness.py; Claude path unchanged
  • v0.19.1 — credential capability catalog: CLAUDE.md now points the build at ~/.config/mar/credentials.catalog.yaml (names + purpose, no values) as a nudge toward provisioned services — not a fence (greenfield work can still reach for other tools); the one firm line stays "pause on a missing credential, never fake it"
  • v0.20.0clean updates: re-running mar init on an existing repo now prunes framework files a prior version shipped but the current one dropped (e.g. the old .cursor/commands/mar/* layout after the flat /mar-* switch). Only mar-owned framework files are removed — scaffolded and merged/user files are never touched. Until the full drift-aware mar update lands, re-init for your chosen target is the supported in-place upgrade

Next:

  • mar update (drift-aware, with conflict resolution), plus the mar status / mar doctor stubs filled in
  • Cursor v2 — the best-of-breed cross-vendor model profile (.cursor/agents/) shipped in v0.21 (mar init --models best-of-breed); live-hook verification still pending
  • Codex CLI adapter

Contributing

Issues and PRs welcome at github.com/sindreespeland/marauders-mischief. Run /mar:retrospect after a session if you find friction; the chat output formats framework findings as paste-ready issue bodies.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

marauders_mischief-0.21.0.tar.gz (288.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

marauders_mischief-0.21.0-py3-none-any.whl (372.8 kB view details)

Uploaded Python 3

File details

Details for the file marauders_mischief-0.21.0.tar.gz.

File metadata

  • Download URL: marauders_mischief-0.21.0.tar.gz
  • Upload date:
  • Size: 288.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for marauders_mischief-0.21.0.tar.gz
Algorithm Hash digest
SHA256 ff58d2256c04419810c5f2df83db02b3dc4382232bac71a6fa77de35c52890a5
MD5 4c308f5036c9b50ea8a75305fbc5f569
BLAKE2b-256 2f4e9df11478d105729de11707bce38cd3bc200b3ba01587d95748b23cdbbbba

See more details on using hashes here.

Provenance

The following attestation bundles were made for marauders_mischief-0.21.0.tar.gz:

Publisher: release.yml on sindreespeland/marauders-mischief

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file marauders_mischief-0.21.0-py3-none-any.whl.

File metadata

File hashes

Hashes for marauders_mischief-0.21.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4109ca686cb7cec4613d2ba17939f5c060cb1eec6f8fe119bf4032b3e972be1d
MD5 3b56585a7c0ce3e1dcd186c87e6f3167
BLAKE2b-256 20dfa6cdfe3ef2dd534742fe4811841c04e322273edc1901c711735b386748c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for marauders_mischief-0.21.0-py3-none-any.whl:

Publisher: release.yml on sindreespeland/marauders-mischief

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page