GAS Fakes for VS CodeRun, debug, and serve Google Apps Script projects locally — no This extension wires Built for the workflow described in Gas-fakes, GitHub Actions, and WIF. Features
Requirements
Quick startIf you already have
For a script that reads/writes a Google Sheet, jump to Authentication. Authentication: the real setup
Path A — Personal Google account (most users)This works for One-time GCP setup
Per-project setup
Adding more test users (if "App is being tested" error)If you see "Project Name has not completed the Google verification process":
You can add up to 100 test users. Personal dev never needs to "publish" the app for verification. Path B — Enterprise Workspace, locked-down GCP ConsoleIf your IT department blocks
Daily usageOnce auth is set up:
The editor title-bar buttons appear on any How
|
| Setting | Default | What it does |
|---|---|---|
gasFakes.nodeBinary |
"node" |
Path to the Node.js binary used to run the runner. |
gasFakes.entryFunctionPattern |
regex | Match for runnable zero-arg top-level functions. |
gasFakes.sandboxIframe |
true |
Serve web app inside a sandboxed iframe with postMessage bridging. Set false to serve the user HTML directly (less faithful to GAS but simpler). |
gasFakes.codeLens.enabled |
true |
Show ▶ Run / 🐞 Debug above functions. |
Troubleshooting
"no .clasp.json found in this workspace"
The extension looks for .clasp.json from the active editor up to the workspace root. If you opened a single file instead of a folder, open the project directory.
"cannot find @mcpher/gas-fakes in this project"
Run GAS Fakes: Init in This Project. The extension installs @mcpher/gas-fakes from a private cache (~/.cache/gas-fakes-npm) so a broken ~/.npm cache won't sink the install.
"Request had insufficient authentication scopes"
The ADC token doesn't have the scopes your code needs. Three things to check:
appsscript.jsonlists the scopes underoauthScopes..envhasEXTRA_SCOPESset to the same scopes.- You re-ran Sign In (ADC) after editing the manifest — the scopes only flow through at sign-in time.
"App has not completed Google verification"
The OAuth consent screen is in "Testing" mode (which it always is for personal projects). Add yourself as a test user: https://console.cloud.google.com/apis/credentials/consent → Test users → + ADD USERS.
"An iframe which has both allow-scripts and allow-same-origin can escape its sandboxing"
Harmless Chrome warning. We need both flags so user code runs and can use localStorage. Real GAS achieves the same effect by serving the inner iframe from a different domain (userContent.googleusercontent.com); locally we don't have that option.
"ScriptApp.getService is not a function"
Older bundle. The current runner stubs ScriptApp.getService().getUrl() to return the local server URL. Reload the Extension Development Host (Cmd+R) and rebuild.
EACCES errors on ~/.npm
Old npm bug — fix with sudo chown -R "$(id -u):$(id -g)" ~/.npm. The extension's Init command sidesteps this by using ~/.cache/gas-fakes-npm as the npm cache, but every other npm tool you run will keep failing until you chown.
Web app loads but data is empty
Most likely the spreadsheet isn't accessible to whichever account you authenticated with. Open the sheet and confirm your signed-in Gmail is in the share list.
Limitations
- Zero-argument entry points only for Run/Debug. The web-app
doGet(e)does receive a synthesized event, including query parameters. google.script.runargument types — JSON-serializable values, plusFile/Blob.Dateobjects round-trip via JSON so they arrive as strings (same as real GAS).- Scope inference — Apps Script's editor auto-infers scopes from your code at deploy time. We don't do that — list scopes explicitly in
appsscript.json. - Some
HtmlServicechain methods are no-ops —setXFrameOptionsMode,setSandboxMode,setWidth,setHeight. Real GAS uses these for security and dialog sizing; locally we serve the iframe full-viewport. - Stack traces point at real
.gsfiles (good), butvm.Scriptline numbers can drift a few lines from what you see in the editor when the file uses unusual whitespace.
Architecture
┌────────────── VS Code (extension host) ──────────────┐
│ src/ │
│ ├─ extension.ts Activation + wiring │
│ ├─ projectResolver.ts .clasp.json discovery │
│ ├─ functionIndexer.ts Top-level fn parser │
│ ├─ codeLens.ts ▶ Run / 🐞 Debug │
│ ├─ context.ts Title-bar visibility │
│ └─ commands/ │
│ ├─ init.ts │
│ ├─ signIn.ts │
│ ├─ runFunction.ts │
│ ├─ debugFunction.ts │
│ └─ serveWebApp.ts │
└──────────────────────────────────────────────────────┘
│ spawns Node child process
▼
┌────────────── runner (dist/runner-web.cjs) ──────────┐
│ • require('@mcpher/gas-fakes') │
│ • HtmlService shim (createHtmlOutputFromFile, …) │
│ • Scriptlet processor │
│ • HTTP server │
│ GET / → outer wrapper page │
│ GET /_inner/ → doGet(e) → rendered HTML │
│ POST /_gasfakes/run/:fn → server-side fn │
│ • postMessage bridge for google.script.run │
│ • busboy for multipart (File/Blob uploads) │
│ • ScriptApp.getService stub │
└──────────────────────────────────────────────────────┘
The function runner (dist/runner.cjs) is the same minus the HTTP server; it just calls global[targetFunction]() once and prints the result.
Roadmap
- Phase 3:
GAS Fakes: Generate Test— scaffold a Mocha/Vitest test from existing.gsfunctions.GAS Fakes: Setup GitHub Actions— drop in a WIF-based CI workflow.
- Phase 4:
- First-class debug type (no need to hit "Run with Debugging" twice for source maps).
doPostevent-shape parity with the real Apps Script payload.- Visual route map for multi-page web apps.
Contributing
PRs welcome. The dev loop:
npm install- F5 in the GAS_FAKES window to launch an Extension Development Host (the
.vscode/launch.jsonhas pre-configured launches for several test projects). - Edit, save, Cmd+R in the EDH to reload.
License
MIT — see LICENSE.
Credits
@mcpher/gas-fakes— the Apps Script emulator that does the real work.- Bruce McPherson's blog — for documenting the WIF + ADC flows that this extension automates.