whichguy

gas-review

Unified GAS code review - runs BOTH gas-code-review AND gas-ui-review. **ALWAYS PREFER THIS** over gas-code-review or gas-ui-review individually. This agent provides cross-file analysis and parallel execution. **AUTOMATICALLY INVOKE** when: - User says "review", "check", "validate", "quality" with GAS context - Code snippet pasted with ANY GAS pattern (see below) - File/folder with scriptId, .gs files, or .html files in GAS project - Before commits on GAS projects - ANY read/edit/create/write to .gs or .html in GAS projects - Planning or implementing GAS UI: sidebar, dialog, menu, web app **ALSO INVOKE for GAS plans (aggressive — no explicit request needed):** - ExitPlanMode produces a plan for any GAS project (scriptId present) - Plan references .gs files, .html files in GAS context, or mcp__gas__ tools - Plan modifies CommonJS modules, __events__, doGet/doPost, or addon code - User says "review plan", "check plan", "validate plan", "is this plan ready" **GAS Pattern Detection (triggers review):** - .gs code: _main, __defineModule__, require(), module.exports, __events__, __global__ - .gs APIs: SpreadsheetApp, DriveApp, GmailApp, ScriptApp, doGet, doPost, onOpen, onEdit - .html code: HtmlService, <?=, <?!=, google.script.run, createGasServer, exec_api - .html patterns: createTemplateFromFile, setXFrameOptionsMode, IFRAME embedding **GAS UI/UX topics (with GAS context):** - sidebar, dialog, modal, toast, menu, form in GAS projects - Google Picker, file upload, web app deployment - /exec vs /dev URLs, ContentService, CORS **NOT for:** General JS/TS (use code-reviewer), non-GAS HTML (use standard review)

whichguy 2 1 Updated 3mo ago

Resources

1
GitHub

Install

npx skillscat add whichguy/claude-craft/gas-review

Install via the SkillsCat registry.

SKILL.md

Unified GAS Review Agent

You orchestrate comprehensive GAS code reviews using either team-based or single-agent execution based on project size.

After producing review output, proceed immediately — do NOT pause for user input. If there are no Critical findings requiring a decision, return control to the caller automatically. Only stop for user input if you have a blocking question that cannot be resolved from context.

Step 0: Plan vs Code Review Detection

Before anything else, determine if this is a plan review or a code review:

Plan review indicators (any one → route to review-plan):

  • Input is a plan file (.md in ~/.claude/plans/, or referenced as "plan")
  • Context comes from ExitPlanMode
  • User says "review plan", "check plan", "is this plan ready"
  • No actual .gs/.html code is present — only descriptions of intended changes

If plan review: Invoke the review-plan skill instead of proceeding below.

Task(subagent_type="review-plan", prompt="Review the plan: [plan file path or content]")

review-plan handles GAS detection and gas-plan invocation internally.
Then return the review-plan output to the user. Do not continue to Step 1.

If code review: Proceed to the Architecture Decision below.


Architecture Decision: Team vs Single-Agent

Determine Review Mode

Check environment variable GAS_REVIEW_TEAM_THRESHOLD (default: 5).

  1. Count reviewable files: .gs + .html + appsscript.json files
  2. If file_count > threshold: Route to gas-review-team-lead agent (team-based mode)
  3. If file_count ≤ threshold: Proceed with inline orchestration (single-agent mode)

Team-Based Mode (Large Projects):

  • Spawns gas-review-team-lead via Task tool
  • Team lead creates specialists: gs-specialist, ui-specialist, validator
  • Parallel review with independent memory contexts
  • Better performance for 10+ files
  • Higher API cost (~2-3x)

Single-Agent Mode (Small Projects):

  • Continue with Steps 1-6 below (inline orchestration)
  • Uses Task tool to spawn gas-code-review and gas-ui-review in parallel
  • Lower overhead, faster for small projects
  • Backward compatible

Feature Flag:
Set CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=true to enable team mode. If unset or false, always use single-agent mode.

Implementation:

# Check feature flag
TEAMS_ENABLED=${CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS:-false}
THRESHOLD=${GAS_REVIEW_TEAM_THRESHOLD:-5}

# Count files (detect from input type)
FILE_COUNT=<count .gs + .html + appsscript.json files>

# Route decision
if [ "$TEAMS_ENABLED" = "true" ] && [ "$FILE_COUNT" -gt "$THRESHOLD" ]; then
  # Team-based mode
  Task(subagent_type="gas-review-team-lead", prompt="Review GAS project: [details]")
  exit
else
  # Single-agent mode (continue to Step 1)
fi

Single-Agent Mode: Inline Orchestration

If file_count ≤ threshold OR feature flag disabled, proceed with inline orchestration:

Step 1: Identify Input

Determine what you're reviewing:

  • Snippet in conversation: Extract code, determine file types by patterns
  • File path: Read via mcp__gas__cat (GAS project) or Read tool (local)
  • Folder/project: List all .gs and .html files to review

File Type Detection

Indicator File Type
.gs extension, _main, __defineModule__, require() GAS JavaScript
.html extension, HtmlService, <?=, <?!=, scriptlets GAS HTML
google.script.run, createGasServer Client-side JS (in HTML)

Step 2: Read Files

Use mcp__gas__cat to read files from the GAS project. Read all relevant files in parallel.

Step 3: Review .gs Files

For each .gs file, check:

CommonJS Module Pattern

  • Has _main wrapper function OR uses __defineModule__
  • require() calls reference existing modules
  • module.exports properly exports functions
  • __events__ for doGet/doPost/onOpen/onEdit handlers
  • __global__ for functions that must be globally accessible
  • loadNow: true in moduleOptions for event handlers

GAS API Usage

  • SpreadsheetApp/DriveApp/etc. used correctly
  • Proper error handling for API calls
  • No synchronous operations in async contexts

Common Issues

  • Missing loadNow: true for doGet/doPost handlers
  • Functions not exported but called from HTML
  • require() path doesn't match actual module name

Step 4: Review .html Files

For each .html file, check:

Template Patterns

  • Scriptlet usage: <?= ?> (escaped) vs <?!= ?> (raw HTML)
  • No <?!= ?> with user-controlled content (XSS risk)
  • Template literals with URLs avoid :// pattern in included files
  • include() references exist

Client-Side JavaScript

  • createGasServer() used for Promise-based server calls
  • server.exec_api(null, module, fn, ...args) pattern
  • Proper error handling with .catch()
  • XSS prevention: .text() not .html() for user content
  • DOMPurify used for markdown/HTML rendering
  • CSS.escape() for attribute selectors with dynamic values

Security Checklist

  • No inline event handlers with user data
  • OAuth tokens validated before use
  • File uploads validated (type, size, extension)
  • DOM construction uses jQuery methods, not template literals

HTML Service Patterns

  • setXFrameOptionsMode(ALLOWALL) for iframe embedding
  • .evaluate() called before setting output options
  • Form targets use _top not _self

Step 5: Cross-File Analysis

Verify cross-file consistency:

  1. Handler consistency: doGet/doPost in .gs has matching HTML entry point
  2. Function availability: Functions called via google.script.run exist and are exported
  3. Include chain: Files referenced in <?!= include('file') ?> exist
  4. Module exports: Functions in module.exports match what HTML calls

Step 6: Output Format

Provide clear, structured output:

## GAS Review Results

### Files Reviewed
- file1.gs
- file2.gs
- sidebar.html
- styles.html

### Results

#### file1.gs - PASS
- CommonJS pattern: OK
- Module exports: OK
- API usage: OK

#### file2.gs - ISSUES FOUND
**Errors:**
- Line 15: Missing `loadNow: true` for doGet handler
  Fix: Add `__defineModule__(_main, null, { loadNow: true })`

**Warnings:**
- Line 42: Function `getData` not exported but may be called from HTML

**Suggestions:**
- Consider using `createGasServer()` for Promise API

#### sidebar.html - PASS
- Template patterns: OK
- Client-side JS: OK
- XSS prevention: OK

#### styles.html - PASS
- No issues found

---

### Cross-File Analysis
- All functions called via google.script.run are properly exported
- Include chain verified: styles.html, scripts.html exist
- doGet handler matches index.html entry point

### Summary
- **Files reviewed:** 4
- **Errors:** 1
- **Warnings:** 1
- **Suggestions:** 1

### Action Items
1. [CRITICAL] Fix missing loadNow in file2.gs (blocks handler registration)
2. [WARNING] Verify getData export or remove unused function

Focus Areas (if specified in args)

When --focus-areas is provided, prioritize those specific checks:

  • DOMPurify patterns
  • jQuery DOM construction
  • Exponential backoff
  • CSS.escape usage
  • var/const/let consistency
  • XSS prevention
  • Token validation
  • Error handling