google-apps-script

Installation
SKILL.md

Google Apps Script

Server-side JavaScript that runs on Google's infrastructure with built-in, auto-authorised services for Workspace. V8 is the only runtime: Rhino was shut down on 31 January 2026, so write modern JavaScript (const/let, arrow functions, classes, template literals, destructuring) and set "runtimeVersion": "V8" in appsscript.json if a legacy manifest still says DEPRECATED_ES5.

Steps

  1. Pick the binding and entry point. Container-bound scripts (opened from a Sheet, Doc or Form) can use getActiveSpreadsheet() / getActiveDocument() and simple triggers (onOpen, onEdit). Standalone scripts and anything run from a time trigger must open files by ID or URL. Done when every file access in the plan uses a call that works in the chosen binding.

  2. Write against the service, batching I/O. Read a whole range with getValues(), transform in memory, write back once with setValues(). Cache expensive lookups with CacheService and persist config or cursors with PropertiesService. Done when no getValue/setValue/appendRow sits inside a loop over rows.

  3. Fit the 6-minute limit. Each execution stops at 6 minutes (custom functions at 30 seconds). For larger jobs, process a slice, save a cursor in PropertiesService, and let a time trigger pick up the next slice. Done when the worst-case run is bounded by a batch size, not the data size.

  4. Set triggers idempotently. Before ScriptApp.newTrigger(...), delete existing triggers for the same handler so re-running setup never duplicates them. Done when running the setup function twice leaves one trigger per handler.

  5. Narrow the scopes. List oauthScopes explicitly in appsscript.json, preferring spreadsheets.currentonly, drive.file and script.send_mail over their broad counterparts. Done when every scope in the manifest maps to a call the script makes.

  6. Handle failure visibly. Wrap trigger handlers in try/catch, log with console.error (it reaches Cloud Logging with severity), and notify by email or an error sheet - a failed time trigger is otherwise silent. Done when every trigger handler has a catch that records the error somewhere a human will see it.

Quick start

Installs
140
GitHub Stars
93
First Seen
Jan 21, 2026