# 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 ```ts { 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: ```js // 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. ## YAML frontmatter (recommended) ```yaml --- 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: ` 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 ```js 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.