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 oldkind: 'script') andtemplates/were removed. Keep reusable procedures/boilerplate in Skills, and run ad-hoc code with the Bash tool. Passingkind: '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.
YAML frontmatter (recommended)
---
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
WriteUserScriptis a META_TOOL — available in every movement without listing it inallowed_tools.- After writing, use
RunUserScriptto immediately execute and verify the macro. - Use
ListUserAssetsto see all macros currently in the folder.