Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -540,13 +540,13 @@ mm describe-screen

### Lifecycle

| Command | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mm launch [--context e2e\|prod] [--state default\|onboarding\|custom] [--extension-path <path>] [--goal <text>] [--force] [--flow-tags <tags>]` | Auto-starts the daemon if needed, then launches a headed Chrome session with the configured extension. Use `--context` to set the environment context before launching. Use `--state` to control wallet initialization. Use `--extension-path` to override the extension directory. Use `--goal` and `--flow-tags` for knowledge tagging. Use `--force` to replace an existing session. |
| `mm cleanup [--shutdown]` | Stops the browser, tears down test services (fixture server, Anvil, mock server), and releases session resources. Add `--shutdown` to also terminate the daemon process. |
| `mm stop [--force]` | Stops the daemon process (symmetric to `mm serve`). Sends a best-effort cleanup before shutdown. Use `--force` to remove stale `.mm-server` state from crashed daemons. |
| `mm status` | Displays the daemon's current status: PID, port, uptime, allocated sub-ports, and whether a browser session is active. |
| `mm serve [--background]` | Manually starts the HTTP daemon without launching a browser session. Use `--background` to detach the process. Fails if a daemon is already running for this worktree. |
| Command | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mm launch [--context e2e\|prod] [--state default\|onboarding\|custom] [--extension-path <path>] [--goal <text>] [--force] [--flow-tags <tags>] [--tags <tags>]` | Auto-starts the daemon if needed, then launches a headed Chrome session with the configured extension. Use `--context` to set the environment context before launching. Use `--state` to control wallet initialization. Use `--extension-path` to override the extension directory. Use `--goal`, `--flow-tags`, and `--tags` for knowledge tagging. Use `--force` to replace an existing session. |
| `mm cleanup [--shutdown]` | Stops the browser, tears down test services (fixture server, Anvil, mock server), and releases session resources. Add `--shutdown` to also terminate the daemon process. |
| `mm stop [--force]` | Stops the daemon process (symmetric to `mm serve`). Sends a best-effort cleanup before shutdown. Use `--force` to remove stale `.mm-server` state from crashed daemons. |
| `mm status` | Displays the daemon's current status: PID, port, uptime, allocated sub-ports, and whether a browser session is active. |
| `mm serve [--background]` | Manually starts the HTTP daemon without launching a browser session. Use `--background` to detach the process. Fails if a daemon is already running for this worktree. |

### Interaction

Expand Down
51 changes: 34 additions & 17 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,22 @@ The `run_steps` tool collects observations once after all steps complete. Contro
Starts the daemon (if not running) and launches a headed Chrome session with the extension.

```
mm launch [--context e2e|prod] [--state default|onboarding|custom] [--extension-path <path>] [--goal <text>] [--force] [--flow-tags <tags>]
mm launch [--context e2e|prod] [--state default|onboarding|custom] [--extension-path <path>] [--goal <text>] [--force] [--flow-tags <tags>] [--tags <tags>]
```

| Flag | Description |
| ------------------------- | --------------------------------------------------------------- |
| `--context e2e\|prod` | Set the environment context before launching |
| `--state default` | Pre-onboarded wallet with 25 ETH on local Anvil chain (default) |
| `--state onboarding` | Fresh wallet requiring manual onboarding setup |
| `--state custom` | Use a custom fixture for wallet state |
| `--extension-path <path>` | Override the extension build directory |
| `--goal <text>` | Tag the session with a goal for knowledge store |
| `--force` | Replace an existing active session |
| `--flow-tags <tags>` | Comma-separated flow tags for cross-session knowledge |
| Flag | Description |
| ------------------------- | ------------------------------------------------------------------------------ |
| `--context e2e\|prod` | Set the environment context before launching |
| `--state default` | Pre-onboarded wallet with 25 ETH on local Anvil chain (default) |
| `--state onboarding` | Fresh wallet requiring manual onboarding setup |
| `--state custom` | Use a custom fixture for wallet state |
| `--extension-path <path>` | Override the extension build directory |
| `--goal <text>` | **Required for knowledge.** Describe what this session is doing |
| `--force` | Replace an existing active session |
| `--flow-tags <tags>` | **Required for knowledge.** Comma-separated flow tags (see table below) |
| `--tags <tags>` | Comma-separated free-form tags for ad-hoc filtering (e.g., `smoke,regression`) |

**⚠ Always provide `--goal` and `--flow-tags` on every launch.** Without them, the knowledge store cannot index the session for cross-session learning, prior knowledge, or search. Sessions launched without tags are invisible to future sessions.

Returns: `sessionId`, `extensionId`, `state` (current extension state).

Expand Down Expand Up @@ -448,9 +451,13 @@ These contracts can be deployed to the local Anvil chain via `seed_contract` / `
| `simpleAccountFactory` | ERC-4337 account factory |
| `verifyingPaymaster` | ERC-4337 paymaster |

## Flow Tags
## Session Tagging (REQUIRED)

**Every `mm launch` must include `--goal` and `--flow-tags`.** This is what makes the knowledge store work — without tags, the session is invisible to search, prior knowledge, and cross-session learning.

### Flow Tags

When launching, tag your session with flow tags for cross-session knowledge:
Pick one or more flow tags that describe what the session is doing:

| Tag | Use for |
| ----------------- | ------------------------------ |
Expand All @@ -462,6 +469,16 @@ When launching, tag your session with flow tags for cross-session knowledge:
| `settings` | Settings configuration |
| `tx-confirmation` | Transaction confirmation flows |

### Free-Form Tags

Use `--tags` for ad-hoc categorization not covered by flow tags:

```bash
mm launch --goal "Regression test send USDC" --flow-tags send --tags regression,usdc
```

Tags enable filtering via `knowledge_sessions` and `knowledge_search`.

## Daemon Model

- Daemon runs per project, state tracked in `.mm-server` at the project root
Expand All @@ -476,7 +493,7 @@ When launching, tag your session with flow tags for cross-session knowledge:
### Basic Interaction

```bash
mm launch --state default
mm launch --state default --goal "Test send ETH flow" --flow-tags send
mm describe-screen
# Response includes a11y nodes: [{ ref: "e1", role: "button", name: "Send" }, ...]
mm click e1
Expand All @@ -490,7 +507,7 @@ mm cleanup --shutdown
### Transaction with Notification

```bash
mm launch --state default
mm launch --state default --goal "Test Uniswap swap via dApp" --flow-tags swap,connect
mm navigate https://app.uniswap.org
mm describe-screen
# Interact with dApp...
Expand All @@ -507,13 +524,13 @@ mm cleanup --shutdown
# Set once — all subsequent mm commands target this project
export MM_PROJECT=/path/to/metamask-extension

mm launch --state default
mm launch --state default --goal "Verify home screen" --flow-tags settings
mm describe-screen
mm click e1
mm cleanup --shutdown

# Or use --project per command
mm --project ../metamask-extension launch
mm --project ../metamask-extension launch --goal "Quick check" --flow-tags send
mm --project ../metamask-extension describe-screen
```

Expand Down
36 changes: 36 additions & 0 deletions src/cli/mm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,42 @@ describe('parseLaunchArgs', () => {
);
});

it('parses --tags as comma-separated array', () => {
expect(parseLaunchArgs(['--tags', 'smoke, regression'])).toStrictEqual({
tags: ['smoke', 'regression'],
});
});

it('exits for --tags without value', () => {
expect(() => parseLaunchArgs(['--tags'])).toThrowError('process.exit');
expect(stderrSpy).toHaveBeenCalledWith(
'Error: --tags requires a comma-separated value\n',
);
});

it('exits for --tags with flag as value', () => {
expect(() => parseLaunchArgs(['--tags', '--force'])).toThrowError(
'process.exit',
);
});

it('parses --tags and --flow-tags together', () => {
expect(
parseLaunchArgs([
'--flow-tags',
'send',
'--tags',
'smoke,e2e',
'--goal',
'test send',
]),
).toStrictEqual({
flowTags: ['send'],
tags: ['smoke', 'e2e'],
goal: 'test send',
});
});

it('parses --context value', () => {
expect(parseLaunchArgs(['--context', 'prod'])).toStrictEqual({
context: 'prod',
Expand Down
12 changes: 11 additions & 1 deletion src/cli/mm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,7 @@ export function parseLaunchArgs(args: string[]): Record<string, unknown> {
'--goal',
'--force',
'--flow-tags',
'--tags',
]);

for (let i = 0; i < args.length; i++) {
Expand Down Expand Up @@ -1135,6 +1136,15 @@ export function parseLaunchArgs(args: string[]): Record<string, unknown> {
process.exit(1);
}
result.flowTags = args[i].split(',').map((tag) => tag.trim());
} else if (arg === '--tags') {
i += 1;
if (!args[i] || args[i].startsWith('--')) {
process.stderr.write(
'Error: --tags requires a comma-separated value\n',
);
process.exit(1);
}
result.tags = args[i].split(',').map((tag) => tag.trim());
} else if (arg.startsWith('--') && !knownFlags.has(arg)) {
process.stderr.write(`Warning: unknown launch flag '${arg}'\n`);
}
Expand All @@ -1159,7 +1169,7 @@ Environment Variables:
Falls back to the current git worktree root.

Lifecycle:
mm launch [--context e2e|prod] [--state default|onboarding|custom] [--extension-path <path>] [--goal <text>] [--force] [--flow-tags <tags>]
mm launch [--context e2e|prod] [--state default|onboarding|custom] [--extension-path <path>] [--goal <text>] [--force] [--flow-tags <tags>] [--tags <tags>]
mm cleanup [--shutdown]
mm status
mm stop [--force]
Expand Down
Loading