Skip to content
Skill · Cursor.cursor/rules/*.mdcCoding

Utility Script Standards

Rules for one-off and operational scripts requiring idempotency, a default dry-run mode, structured output, and meaningful exit codes.

Use when: Attach to the scripts directory of any Node/TypeScript repo so data fixes, backfills, and ops scripts are safe to rerun and easy to audit.

@libraryNewcomer
0 upvotes0 forks0 comments

The skill file

Cursor · .cursor/rules/*.mdc
.cursor/rules/*.mdc3348 chars
--- description: Safety and output conventions for files under scripts/ globs: "scripts/**" alwaysApply: false --- # Script rules Scripts here touch real data and run unattended in CI or by tired humans at 2am. Every script follows these rules — no exceptions for "quick one-offs", because one-offs get rerun. ## Idempotency - Running a script twice must produce the same end state as running it once. Design for it explicitly: - inserts use upserts or existence checks, never blind `INSERT`; - file generation writes to a temp path then renames atomically; - external calls (emails, webhooks, charges) check a recorded marker before sending and record completion after. - Process records in stable order with a resumable cursor (last processed id), so a crash mid-run can resume instead of restarting. Print the cursor on exit. - Batch mutations: chunks of ≤ 500 with progress output per chunk. Never one transaction around the whole run. ## Dry-run by default - Mutating scripts run in dry-run mode unless `--apply` (or `--no-dry-run`) is passed. Dry-run executes the full read path and prints exactly what WOULD change: counts, sample ids, before→after values. - The first line of output always states the mode: `mode=dry-run` or `mode=APPLY`. In apply mode against a production `DATABASE_URL`, require `--yes` or an interactive confirmation naming the target (`Type "production" to continue`). - Parse flags with `node:util` `parseArgs` (or the repo's CLI lib) — no hand-rolled `process.argv[2]` positional guessing. Every script supports `--help` listing flags, env vars read, and an example invocation. ## Structured output - Progress and results go to stdout as one JSON object per line: `{"level":"info","event":"chunk_done","processed":500,"failed":0}`. Human-only decoration goes to stderr. - Always end with a single summary line: `{"event":"summary","mode":"dry-run","scanned":12000,"changed":340,"failed":2,"duration_ms":8120}` — this is what CI greps and what gets pasted into the incident channel. - Collect per-record failures (id + reason) and report them in the summary; do not abort the whole run on the first bad record unless `--fail-fast` is passed. - No bare `console.log("done")`, no `console.table` in scripts meant for CI. ## Exit codes - `0` — completed, zero failures. `1` — completed with per-record failures (summary still printed). `2` — bad usage: unknown flag, missing env var, failed precondition (exit before touching anything). `3+` — fatal runtime error mid-run. - Validate every required env var and connectivity precondition up front; fail with exit 2 and a message naming the missing variable before any mutation starts. - Handle `SIGINT`/`SIGTERM`: stop taking new chunks, print the summary with current cursor, exit `130`. A Ctrl-C must never leave a half-applied chunk uncommitted-but-unknown. - Top-level code is wrapped in `main().catch(err => { print error event; process.exit(3); })` — an unhandled rejection that exits 0 is the worst possible outcome. ## Misc - Scripts are TypeScript, run via the repo's runner (`tsx`/`bun`), and import shared db/env modules from `src/` — never duplicate a connection string or schema definition inside a script. - Each script starts with a comment header: purpose, example invocation, owner, and date — delete the script when its purpose is done.

Install

drop into your repo

Save this to your project or home directory so Cursor can load it.

path./.cursor/rules/node-scripts-rules.mdc
Discussion

What people are saying

Forks

0 forks of this skill
Loading forks…