maestro/docs/tools/writeuserscript.md
oss-sync 9f8958c4a2
Some checks failed
CI / build-and-test (push) Has been cancelled
sync: update from private repo (ce93095)
2026-06-10 03:52:37 +00:00

3.4 KiB

WriteUserScript

Creates or overwrites a Playwright browser-macro in the caller's browser-macros/ folder.

Retired (2026-06): plain-Node scripts/ (the old kind: 'script') and templates/ were removed. Keep reusable procedures/boilerplate in Skills, and run ad-hoc code with the Bash tool. Passing kind: 'script' now returns an error pointing at those replacements.

directory runtime signature
browser-macros/ Playwright — Chromium main({ context, params })

Input

{
  name: string,                        // slug — '.js' appended if absent
  content: string,                     // full file text (frontmatter + main())
  overwrite?: boolean                  // default: false — error if file exists
}

Required file structure

The content must define a main function. The following forms are all accepted:

// ES function declaration
async function main({ context, params }) {  }

// Arrow / assigned function
const main = async ({ context, params }) => {  };

// CommonJS export
module.exports = async function main({ context, params }) {  };
exports.main = async function({ context, params }) {  };

If none of these patterns is found the tool returns isError: true with a hint to add a main definition.

---
description: One-line human-readable description shown in ListUserAssets
params:
  - name: url
    type: string
  - name: limit
    type: number
    default: 10
---

Frontmatter is parsed by RunUserScript for param validation. Macros without frontmatter still run, but param validation is skipped.

Macros may additionally declare session_profile_id: <N> to auto-load a saved login session (see RunUserScript docs).

Size limit

256 KB (UTF-8 encoded). Exceeding the limit returns isError: true.

Overwrite semantics

By default (overwrite: false) writing to an existing file is an error. Pass overwrite: true to replace the existing file atomically.

When to use

  • You discovered a useful browser-automation pattern during a task — save it for next time.
  • The user asks you to create or update a macro they can run later via RunUserScript.
  • You want to prototype a browser automation without going through the UI.

Example

WriteUserScript({
  name: "screenshot-dashboard",
  content: `---
description: Take a screenshot of the dashboard
params:
  - name: url
    type: string
---
async function main({ context, params }) {
  const page = await context.newPage();
  await page.goto(params.url);
  const buf = await page.screenshot({ fullPage: true });
  return { screenshotBase64: buf.toString('base64') };
}
`
})

Error cases

Situation isError message contains
No authenticated user true "authenticated"
Retired kind: 'script' passed true "retired"
name missing / empty true "name"
name contains /, space, etc. true "alphanumeric"
content missing main true "main"
Content exceeds 256 KB true "bytes"
File exists, overwrite not set true "overwrite"

Notes

  • WriteUserScript is a META_TOOL — available in every movement without listing it in allowed_tools.
  • After writing, use RunUserScript to immediately execute and verify the macro.
  • Use ListUserAssets to see all macros currently in the folder.