Comprehensive guide for Google Apps Script development covering all built-in services (SpreadsheetApp, DocumentApp, GmailApp, DriveApp, CalendarApp, FormApp, SlidesApp), triggers, authorization, error handling, and performance optimization. Use when automating Google Sheets operations, creating Google Docs, managing Gmail/email, working with Google Drive files, automating Calendar events, implementing triggers (time-based, event-based), building custom functions, creating add-ons, handling OAuth scopes, optimizing Apps Script performance, working with UrlFetchApp for API calls, using PropertiesService for persistent storage, or implementing CacheService for temporary data. Covers batch operations, error recovery, and JavaScript ES6+ runtime.
/plugin marketplace add henkisdabro/wookstar-claude-code-plugins/plugin install productivity@wookstar-claude-pluginsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
assets/spreadsheet-automation-template.jsassets/trigger-setup-template.jsreferences/apps-script-api-reference.mdscripts/validators.pyThis skill provides comprehensive guidance for developing Google Apps Script applications that automate Google Workspace services. Google Apps Script is a cloud-based JavaScript platform that enables automation across Google Sheets, Docs, Gmail, Drive, Calendar, and more, with server-side execution and automatic OAuth integration.
Invoke this skill when:
Automate all aspects of Google Sheets including reading, writing, formatting, and data manipulation.
Common operations:
Create and edit Google Docs programmatically including text, tables, images, and formatting.
Common operations:
Automate email operations including sending, searching, and managing Gmail messages.
Common operations:
Manage Google Drive files and folders programmatically.
Common operations:
Automate Google Calendar operations including events, reminders, and recurring appointments.
Common operations:
Implement time-based and event-driven automation.
Trigger types:
function generateWeeklyReport() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('Data');
// Batch read for performance
const data = sheet.getRange('A2:D').getValues();
// Process data
const report = data
.filter(row => row[0]) // Filter empty rows
.map(row => ({
name: row[0],
value: row[1],
status: row[2],
date: row[3]
}));
// Write summary
const summarySheet = ss.getSheetByName('Summary') || ss.insertSheet('Summary');
summarySheet.clear();
summarySheet.appendRow(['Name', 'Total Value', 'Status']);
report.forEach(item => {
summarySheet.appendRow([item.name, item.value, item.status]);
});
// Email notification
MailApp.sendEmail({
to: Session.getEffectiveUser().getEmail(),
subject: 'Weekly Report Generated',
body: `Report generated with ${report.length} records.`
});
}
function processUnreadEmails() {
const threads = GmailApp.search('is:unread from:specific@example.com');
threads.forEach(thread => {
const messages = thread.getMessages();
const latestMessage = messages[messages.length - 1];
const subject = latestMessage.getSubject();
const body = latestMessage.getPlainBody();
// Process and respond
thread.reply(`Thank you for your email regarding: ${subject}\n\nWe will respond within 24 hours.`);
// Mark as read and label
thread.markRead();
const label = GmailApp.getUserLabelByName('Auto-Responded');
thread.addLabel(label);
});
}
function generateDocumentFromTemplate() {
// Get template
const templateId = 'YOUR_TEMPLATE_ID';
const template = DriveApp.getFileById(templateId);
// Make copy
const newDoc = template.makeCopy('Generated Document - ' + new Date());
// Open and edit
const doc = DocumentApp.openById(newDoc.getId());
const body = doc.getBody();
// Replace placeholders
body.replaceText('{{NAME}}', 'John Doe');
body.replaceText('{{DATE}}', new Date().toDateString());
body.replaceText('{{AMOUNT}}', '$1,234.56');
// Save
doc.saveAndClose();
// Share with user
newDoc.addEditor('recipient@example.com');
Logger.log('Document created: ' + newDoc.getUrl());
}
function setupDailyTrigger() {
// Delete existing triggers to avoid duplicates
const triggers = ScriptApp.getProjectTriggers();
triggers.forEach(trigger => {
if (trigger.getHandlerFunction() === 'dailyReport') {
ScriptApp.deleteTrigger(trigger);
}
});
// Create new trigger for 9 AM daily
ScriptApp.newTrigger('dailyReport')
.timeBased()
.atHour(9)
.everyDays(1)
.create();
Logger.log('Daily trigger configured');
}
function dailyReport() {
// This function runs daily at 9 AM
generateWeeklyReport();
}
For comprehensive API documentation, code patterns, and detailed examples, see:
The reference file contains:
Minimize API calls by batching reads and writes:
// ✅ Good - Single batch read
const values = sheet.getRange('A1:Z1000').getValues();
// ❌ Bad - 1000 individual reads
for (let i = 1; i <= 1000; i++) {
const value = sheet.getRange(`A${i}`).getValue();
}
Use CacheService for temporary data (25 min TTL):
function getCachedData(key) {
const cache = CacheService.getScriptCache();
let data = cache.get(key);
if (!data) {
// Fetch from source
data = expensiveOperation();
cache.put(key, JSON.stringify(data), 600); // 10 minutes
}
return JSON.parse(data);
}
Implement comprehensive error handling:
function safeOperation() {
try {
// Operation code
const range = sheet.getRange('A1');
range.setValue('Value');
} catch (error) {
Logger.log('Error: ' + error.message);
Logger.log('Stack: ' + error.stack);
// Notify user
const ui = SpreadsheetApp.getUi();
ui.alert('Error: ' + error.message);
// Log to sheet for audit trail
const logSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Error Log');
if (logSheet) {
logSheet.appendRow([new Date(), error.message, error.stack]);
}
}
}
Scripts have a 6-minute timeout. For large operations:
Request only necessary permissions in appscript.json:
{
"oauthScopes": [
"https://www.googleapis.com/auth/spreadsheets.currentonly",
"https://www.googleapis.com/auth/script.send_mail"
]
}
Store configuration and state:
function saveConfig(key, value) {
const props = PropertiesService.getScriptProperties();
props.setProperty(key, value);
}
function getConfig(key) {
const props = PropertiesService.getScriptProperties();
return props.getProperty(key);
}
function setupDataValidation() {
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getRange('A2:A100');
// Create dropdown rule
const rule = SpreadsheetApp.newDataValidation()
.requireValueInList(['Option 1', 'Option 2', 'Option 3'])
.setAllowInvalid(false)
.build();
range.setDataValidation(rule);
}
function fetchWithRetry(url, maxRetries = 3) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
const response = UrlFetchApp.fetch(url);
return JSON.parse(response.getContentText());
} catch (error) {
if (attempt === maxRetries) {
throw error;
}
Utilities.sleep(Math.pow(2, attempt) * 1000); // Exponential backoff
}
}
}
function onFormSubmit(e) {
const response = e.values; // Form responses
const email = response[1]; // Assuming email is column B
const name = response[2]; // Name in column C
// Send confirmation email
MailApp.sendEmail({
to: email,
subject: 'Form Submission Received',
body: `Hi ${name},\n\nThank you for your submission.`
});
// Log to separate sheet
const ss = SpreadsheetApp.getActiveSpreadsheet();
const logSheet = ss.getSheetByName('Processed') || ss.insertSheet('Processed');
logSheet.appendRow([new Date(), name, email, 'Processed']);
}
Use the validation scripts in scripts/ for pre-deployment checks:
Common Issues:
Debug with Logger:
Logger.log('Debug info: ' + JSON.stringify(object));
// View: View > Logs (Cmd/Ctrl + Enter)
Use Breakpoints:
This skill provides production-ready patterns for Google Workspace automation. Consult the comprehensive API reference for detailed method signatures and advanced use cases.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.