# mm-harness

One CLI for operating MetaMask Extension, Mobile, and Core and producing
reviewable recipe evidence. Run it inside a checkout; the product, slot, ports,
and runtime paths are detected automatically.

- **Action:** one typed operation.
- **Recipe:** a reusable, parameterized graph of actions and called recipes.

The generic graph engine and evidence schemas live in Farmslot packages.
`mm-harness` owns MetaMask runtime control and domain capabilities.

## Getting started from zero

No checkouts yet? `mm-harness setup-base` clones the MetaMask product repos into one
standard layout and runs each repo's own dependency install — no install of this
package required to start:

```bash
npx -p @deeeed/metamask-harness mm-harness setup-base
```

It produces, under `~/dev/metamask` by default:

```text
metamask-extension-1..N   metamask-mobile-1..N   core-1..N
```

Run without flags in a terminal, it asks which projects you want and how many
copies of each. Pass flags to skip the prompt entirely — which is how scripts,
CI, and parent tools should invoke it:

```bash
mm-harness setup-base --only core --counts core=1
mm-harness setup-base --dir ~/work/metamask --counts extension=3,mobile=1,core=2
mm-harness setup-base --only mobile --dry-run        # plan only, changes nothing
```

The base directory resolves by precedence: `--dir`, then `$MM_HARNESS_BASE_DIR`,
then saved preferences, then `~/dev/metamask`. A successful run saves the base
directory and counts it used, so later runs adopt them — inspect with
`--show-config`, clear with `--reset-config`. Re-running is safe: existing
clones are fetched, never reset and never deleted.

**Scope fence.** It clones and installs dependencies. Nothing else — no platform
toolchains, no simulators, no `.env` files, no builds. Workflow onboarding is a
prompt; environment readiness is `mm-harness doctor`, which is exactly where it
points you next.

`setup-base` is a normal command on the single `mm-harness` entrypoint. Its work
stays in one readable shell leaf, and `npx -p` makes that same command available
before a global install.

## Install

```bash
npm install -g @deeeed/metamask-harness@latest
mm-harness --version
mm-harness doctor
```

`doctor` is read-only. `doctor --fix` repairs harness-owned runtime state but
does not launch an app, invent credentials, or choose a wallet fixture.

```bash
mm-harness doctor --fix
mm-harness fixtures init --from /secure/path/wallet-fixture.json
# Disposable public testing only; never fund this wallet:
mm-harness fixtures init --dev
```

Use `mm-harness update` to update a published installation.

## Operate

```bash
# Extension
mm-harness launch
mm-harness launch --sidepanel

# Mobile
mm-harness launch ios
mm-harness launch android

# Any checkout
mm-harness status
mm-harness stop
mm-harness logs
mm-harness debug
mm-harness reload                 # Mobile Metro reload / Extension CDP refresh
mm-harness fixtures set

# Delete the current wallet, then reapply the canonical fixture from clean state.
mm-harness fixtures reset
```

Extension `launch` keeps its incremental watcher running. Refresh the active
page after a successful rebuild; use `launch --build` only for an explicit
production-like LavaMoat rebuild.

Log sources stay separate:

```bash
mm-harness logs --source extension  # Extension page
mm-harness logs --source dapp       # active dapp
mm-harness logs --source webpack    # compiler
mm-harness logs --source watcher    # watcher lifecycle
mm-harness logs --source rebuild    # incremental rebuilds
mm-harness logs --source app        # Mobile app
mm-harness logs --source metro      # Mobile bundler
```

Live Mobile and Extension recipes automatically index a bounded, redacted
`network/run-summary.json` with request timing and recipe-node boundaries. Use
explicit `app.network_capture` and `app.network_assert` nodes for filtered
windows and machine-checked request expectations. See
[Recipe-scoped network capture](docs/NETWORK-CAPTURE.md).

Mobile and Extension recipes can bracket explicit UI-smoothness windows with
`app.performance_capture` and verify their evidence with
`app.performance_assert`. Capture is never automatic. See
[UI smoothness capture](docs/PERFORMANCE-CAPTURE.md).

## Discover and prove

```bash
mm-harness actions positions
mm-harness actions --action metamask.wallet.ensure_unlocked
mm-harness call metamask.wallet.ensure_unlocked

mm-harness run --list
mm-harness run perps.clean-market-testnet --describe
mm-harness run wallet.smoke --describe
mm-harness run wallet.import method=auto

# Use visible client UI to delete and import the wallet again.
mm-harness run wallet.reset-import
mm-harness run path/to/recipe.json market=ETH --plan
mm-harness run path/to/recipe.json
```

`run` selects a checkout-local artifact directory unless
`--artifacts-dir <dir>` overrides it. Human output prints diagnostics and
absolute paths to the report, trace, executed recipe, and artifact manifest.
Use `mm-harness last --json` to resume without repeating the last operation.

For automation, `--json` emits one stable document. `run --json-stream` emits
line-buffered JSONL progress and a terminal event.

## Team libraries

```bash
export RECIPE_LIBRARY_PATH="team=$HOME/shared-library/team-recipes"
mm-harness run --list
```

Shared libraries hold durable actions and composable recipes. Task acceptance
criteria remain task-local. See [Recipes](docs/RECIPES.md).

## Recover

```bash
mm-harness doctor
mm-harness doctor --fix
mm-harness verify
mm-harness cleanup
```

Failures name one exact next action. Core is headless; browser, device, logs,
and debugger capabilities are reported as unavailable instead of fabricated.
Stable exit codes are `1` runtime/action failure, `2` invalid CLI usage, `3`
infrastructure failure, `4` bounded recovery refusal, and `5` validation/trust
failure.

## Reference

- [Recipes](docs/RECIPES.md) — discover, compose, author, and share proof.
- [Security](docs/SECURITY.md) — trust, approval, fixtures, and evidence safety.
- [QA](docs/QA.md) — clean-machine and human release checks.
- [Contributing](docs/CONTRIBUTING.md) — ownership, layout, and change gates.

For development, point the installed command at a source checkout:

```bash
export MM_HARNESS_BIN=/path/to/metamask-harness/bin/mm-harness
mm-harness --version
```

Unset `MM_HARNESS_BIN` to return to the published installation.
