---
name: recording
description: Read a Groove bundle (a private recording of someone's browser work) and turn what they repeat into a Groove automation they can import and run. Use when given a groove-*.zip or a folder with manifest.json whose format is "groove-recording", or when asked to automate something from a Groove recording. Also use for a groove pack (a *.groove.zip, or a folder whose manifest.json format is "groove-pack"): one existing groove to explain or change.
---

# Using a Groove bundle

A **recording** is a recording of real browser work, exported by the Groove extension. A **groove** is an automation
Groove can run in the user's own browser. Your job is usually: read the recording, find the work worth automating,
and write a groove file.

## Files
| file | what it is |
|---|---|
| `README.md` | Start here: when, which sites, and every step in plain words. |
| `steps.jsonl` | One step per line: `action`, `tab`, `frame`, `url`, `target`, `value`, `text`. |
| `context.json` | The sites used, their pages, the form fields filled, and the busiest network endpoints. |
| `network.jsonl` | Network metadata (method, URL, status, timing). No bodies. |
| `events/*.json` | Full page recordings (rrweb format), one per tab and frame. Use only when steps are not enough, e.g. to see what was on screen. They can be large. |
| `groove.schema.json` | The exact format for the groove you write. |

Values shown as `[REDACTED]` or `•••` were hidden on the user's device. **Never guess or invent them.** If a groove
needs one (a password, an account number), make it a variable with `"secret": true` and the user supplies it.

## Finding what to automate
1. Read `README.md` top to bottom.
2. Look for runs of steps that repeat with different values (the same clicks on the same sites, with different
   names, dates or numbers typed). Each repeat is a candidate groove, and the changing values are its variables.
3. Look across tabs: a common pattern is "copy from site A, paste into site B". Steps carry `tab` numbers.
4. Prefer the smallest groove that removes the most repetition. Tell the user what you found and how often it happened.

## Writing a groove
- Follow `groove.schema.json` exactly. `format` is `"groove"`, `version` is `1`.
- Copy `target` objects from `steps.jsonl` rather than writing selectors yourself; keep `role` + `name` and add
  `text` when the element shows text. Groove tries testid, role+name, text, css and xpath in that order.
- Replace values that change between runs with `{{variables}}` and declare them in `variables` as inputs. Values
  that stay fixed for this person (their account id, a folder, a default region) are `"kind": "setting"` with a `value`.
- The person's notes (`comment` on steps, `comment` in manifest.json) say what they meant. Follow them, put the
  groove-level one in `description`, and copy each step's note into that groove step's `comment`.
- After each important action, add a `waitFor` or `assert` with text that proves it worked (e.g. "Saved").
  Groove stops a run when a check fails instead of carrying on silently.
- Mark anything that submits, sends, pays or deletes with `"confirm": true`. The user approves it during the run.
- Use `extract` with `saveAs` to read a value from one page and `type` it on another. Every `saveAs` value is also an
  output: Groove shows it to the person when the run ends, and `run_groove` returns it to you.
- Lists: `extractAll` reads every element matching `item` into rows of `fields` (text, or `attr: "href"` for links).
  Add `next` (the next-page control) and `maxPages` to page through, and `onlyNew: true` with a `key` to keep only
  rows not seen before (watching for new articles, listings or tickets). Groove masks private values in rows.
- Sending results: `webhook` POSTs JSON to a `url` the person gives you (Zapier, Make, Slack, their server); `email` sends
  them `to` an address (the person confirms it once in Groove); `download` saves a list or the results as a CSV, JSON or
  text file (`filename` can use `{{date}}` and `{{time}}`). By default each sends the inputs and every `saveAs` value;
  name others in `send` (or `from` for a download). Never invent a webhook URL or an email address: ask the person.
- Alerts: `notify` sends the person a notification, optionally only `if` the page shows some `text` or a list `var`
  has rows ("tickets available", "price dropped"). Use it at the end of a scheduled groove.
- Schedules: set `schedule` (`every`: minutes | hour | day | weekdays, `n`, `at`) for checks that should repeat.
  Scheduled runs use the inputs' last values or defaults, so give every input a `default`.
- Shopping or anything that pays: put `"confirm": true` on the final buy/pay/submit step. Never remove it.
- Frames: set `frame` to the iframe's CSS selector (from the step's `frame` field). Tabs: use `newTab` /
  `switchTab` with tab numbers.
- Keep `note` on each step in plain language; the user sees it.

## Example
```json
{
  "format": "groove", "version": 1,
  "name": "Add a customer note",
  "variables": [{ "name": "customer", "label": "Customer name" }, { "name": "note", "label": "Note" }],
  "steps": [
    { "action": "goto", "url": "https://crm.example.com/customers", "note": "Open customers" },
    { "action": "type", "target": { "role": "textbox", "name": "Search" }, "value": "{{customer}}" },
    { "action": "press", "key": "Enter" },
    { "action": "click", "target": { "role": "link", "name": "{{customer}}" } },
    { "action": "type", "target": { "role": "textbox", "name": "Note" }, "value": "{{note}}" },
    { "action": "click", "target": { "role": "button", "name": "Save" }, "confirm": true },
    { "action": "waitFor", "text": "Note saved" }
  ]
}
```

## Giving it back
Save the groove as `<name>.groove.json` and tell the user to import it in Groove (Grooves → Import), or, if Groove is
connected to you over MCP, call `propose_groove`. Grooves from agents always arrive as drafts the user approves, and
the first run goes step by step.

## Changing a groove you were given
A groove pack (`README.md`, `groove.json`, this file, the schema) is one existing groove. To change it:
- Edit `groove.json` and change only what the person asked for. Keep every step's `comment` unless it is now wrong.
- Leave `lineage` exactly as it is. Groove matches it to the original and shows the person each added, removed
  and changed step, and any site the groove did not visit before.
- Never write a credential into a groove. Use a variable with `"secret": true`.
- Give back `groove.json`, or the pack zipped. Over MCP: `get_groove` reads a groove, `propose_groove` sends the change.
  The edit arrives as a draft beside the original, which stays as it was.
