Customising the Gemini CLI with Extensions: A gas-fakes Case Study

The Gemini CLI is a powerful tool for developers, but its true potential lies in its extensibility. I’m excited to share a project that showcases this flexibility: the gas-fakes Gemini CLI Extension. This extension is a case study in tailoring the Gemini CLI to your specific needs, particularly when it comes to secure software development in Google Apps Script.

At its core, this project addresses a critical security concern in the age of AI-driven development: how can you safely test and execute AI-generated code that requires broad access to your Google Workspace data? The answer lies in the pioneering work of Bruce Mcpherson on his gas-fakes library, which this extension integrates into a seamless and secure workflow, thanks to the invaluable contributions of Kanshi Tanaike. I’m looking forward to discussing this project in more detail with Bruce at the upcoming Google Workspace Developer Summit in Paris.

The Power of Gemini CLI Extensions

The ability to create extensions for the Gemini CLI opens up a world of possibilities for developers. By packaging together a collection of tools and resources, you can create a customised experience that is perfectly suited to your workflow. An extension can include three key components:

  • System Prompts (GEMINI.md): A GEMINI.md file allows you to provide the model with custom instructions and context, guiding its behaviour to ensure it generates code that aligns with your specific requirements.
  • Custom Commands: You can create custom commands to automate common tasks and streamline your development process.
  • MCP Tools: The Model Context Protocol (MCP) allows you to integrate external tools and services with the Gemini CLI, enabling powerful, interactive experiences.

The gas-fakes Extension: A Case Study in Secure Development

The gas-fakes Gemini CLI Extension is a practical example of how these components can be combined to create a powerful and secure development environment for Google Apps Script.

The extension tackles the challenge of safely executing AI-generated code by creating a sandboxed environment where scripts can be tested without granting them access to your Google account. Here’s how it works:

  • GEMINI.md: The GEMINI.md file provides the model with detailed instructions on how to use the gas-fakes library, ensuring that the generated code is compatible with the sandboxed environment.
  • Custom Commands: The extension includes custom commands like /gas:init and /gas:new that automate the process of setting up a new project and generating code.
  • MCP Tool: The packaged MCP tool allows the Gemini CLI to interact with the gas-fakes sandbox, enabling it to execute code and receive feedback in a secure environment. This extension also includes the new official Model Context Protocol (MCP) for Google Workspace Development to interact directly with Google Workspace APIs.

Getting Started

To get started with the gas-fakes extension, you’ll first need to have the Google Gemini CLI installed. Once that’s set up, you can install the extension with the following command:

gemini extensions install https://github.com/mhawksey/gas-fakes-ext

For more information on managing extensions, including uninstallation and updates, please see the official documentation.

Usage

Once the extension is installed, you can start a new sandboxed Apps Script project directly from your terminal.

First, create a new directory for your project, navigate into it, and start the Gemini CLI. From there, you can use the /gas:init command to scaffold a complete project structure, which includes all the necessary files for local development and testing.

With the project initialised, you can then use the /gas:new command to generate code from a natural language prompt. For example:

/gas:new "create a new Google Doc and write 'Hello, World!' to it"

This command generates the Apps Script code in src/Code.js and a corresponding runner script in run.js. From here, you can continue the conversation with the Gemini CLI to refine and build upon your code, testing each iteration locally in the secure, sandboxed environment.

This project structure is deliberate: the run.js file is your sandbox for testing, while the src folder contains the clean, production-ready Apps Script code. This separation makes it easy to use other command-line tools like clasp to push only the code in the /src directory to your online Apps Script project when you are ready to deploy.

Fine-Grained Security with Conversational Controls

Beyond creating new files, a common requirement is to have a script interact with existing documents in a user’s Google Drive. The gas-fakes extension provides a robust solution for this, and because it’s integrated into the Gemini CLI, you can configure these advanced security settings using natural language.

This conversational control is powered by the extension’s MCP tool, run-gas-fakes-test. When you ask Gemini to “whitelist this Google Doc for read access”, the model doesn’t write the configuration code itself. Instead, it calls this tool, translating your request into a set of structured parameters that the tool understands. The MCP tool then dynamically assembles and executes the run.js script with the precise security settings you requested. This abstraction is what makes the natural language interface so powerful.

For example, instead of requesting broad access to all of a user’s files, you can create a specific whitelist of file IDs that your script is allowed to interact with, specifying read-only or write access on a per-file basis. This granular approach ensures your script only ever touches the files it is supposed to.

For even tighter security, you can ask Gemini to:

  • Disable entire services: If your script only needs to work with Sheets, you can completely disable DriveApp and DocumentApp.
  • Whitelist specific methods: Lock down a service to only allow certain actions, for example, permitting DriveApp.getFiles() but blocking DriveApp.createFile().
  • Manage test artefacts: For debugging, you can disable the automatic cleanup feature to inspect any files created during a test run.

These advanced features provide developers with the confidence to build and test powerful automations, knowing that the execution is contained within a secure, predictable environment.

Conclusion

The Gemini CLI is more than just a command-line interface; it’s a powerful platform for creating customised and intelligent experiences. The gas-fakes Gemini CLI Extension is just one example of what is possible. I encourage you to explore the world of Gemini CLI Extensions and see what you can create.

Acknowledgements

This extension stands on the shoulders of giants. It directly builds upon the pioneering work of Bruce Mcpherson and his gas-fakes library. I’d also like to express my sincere gratitude to Kanshi Tanaike, whose work on the gas-fakes sandbox and MCP server has been instrumental in the development of this extension.

Source: GitHub – mhawksey/gas-fakes-ext

The Eject Button: How to Write Portable Apps Script Code for the Google Cloud

As Google Apps Script developers, we live in a world of incredible convenience. Services like DriveApp, SpreadsheetApp, and GmailApp are powerful, intuitive, and deeply integrated into Google Workspace. They allow us to build solutions with remarkable speed.

But this convenience comes with a trade-off: our code becomes tightly coupled to the Apps Script runtime. When you write DriveApp.getFiles(), you’re writing code that can only ever run inside Apps Script.

What happens when you hit a wall? Your script might need more than the 30-minute execution limit, require more memory than the shared environment provides, or need to handle a level of concurrency that Apps Script isn’t designed for. In these moments, you need an “eject button”—a way to lift your code out of Apps Script and into a more scalable environment like Google Cloud Run, without starting from scratch.

This article is a guide to a professional workflow that makes this possible. It’s about writing portable Apps Script code from day one, so you’re always ready for the cloud.

The Portability Problem: Built-in Services vs. Raw APIs

The core of the issue lies in how we interact with Google’s services.

  • Built-in Services (DriveApp, etc.): These are high-level abstractions. They provide incredibly useful helper functions (like getBlob()) that handle complex operations behind the scenes. However, they are a “black box” and exist only in Apps Script. For a fascinating look at the work involved in unpacking what these services do, check out Bruce Mcpherson’s gas-fakes project, which emulates these services for local testing.
  • Direct API Calls: The alternative is to interact directly with the underlying Google Drive API (or Sheets API, etc.). This gives you granular control but requires you to handle raw HTTP requests with UrlFetchApp, manage authentication tokens, and implement your own error handling like exponential backoff.

Let’s be clear: this isn’t a call to abandon the built-in services. Far from it. The built-in services are indispensable for anything that interacts directly with the user’s live session. Examples include creating custom menus, displaying dialogs with HtmlService, acting on an onEdit(e) event object, or manipulating the user’s cursor position. For these tasks, the built-in services are not just the best choice; they are often the only choice. The “portable philosophy” is about being strategic. It’s about identifying the core, data-processing engine of your script—the part you suspect might one day need more power or time—and deliberately building that piece for portability.

Writing portable code means finding a middle ground: the convenience of a high-level interface with the cross-platform nature of direct API calls.

The Solution: An Abstraction Layer with Client Libraries

The secret to portability is to abstract away the platform-specific parts of your code. Instead of using the built-in services, you can use client libraries that work in both Apps Script and a standard Node.js environment.

  1. In Apps Script: You can use the Google API Client Library Generator for Apps Script libraries. This repository includes over 400 Apps Script client libraries for Google APIs that provide a familiar, object-oriented interface (e.g., drive.files.list()) but handle the UrlFetchApp and token logic for you.
  2. In Node.js (for Cloud Run): You use the official Google API Node.js Client Libraries (e.g., googleapis). These libraries are the industry standard and provide the exact same structural interface (e.g., drive.files.list()).

A Real-World Example: Bulk PDF Generation

Let’s imagine a common business need: a script that takes data from a Google Sheet to generate hundreds of personalized offer letters as PDFs from a Google Doc template. Doing this one-by-one in Apps Script would be slow and might time out. This is a perfect candidate for the “eject button.”

Here is how we can write a single, portable function for the core logic.

The Portable Core Logic

This function contains the business logic. It’s agnostic to its environment; it only needs an initialized driveClient and docsClient to do its work. To ‘see’ what this looks like view this Apps Script project which has already had the Drive and Docs client libraries from the client library generator build directory.

/**
 * PORTABLE CORE LOGIC
 * This function is almost perfectly portable between Apps Script and Node.js.
 * @param {object} job The job details (templateId, replacements, etc.).
 * @param {object} driveClient An initialized Drive API client.
 * @param {object} docsClient An initialized Docs API client.
 * @param {object} logger A logger object (like `console`).
 */
async function _portablePdfGeneratorLogic(job, driveClient, docsClient, logger) {
  const { templateId, destinationFolderId, replacements, newFileName } = job;
  let newFileId = null;

  try {
    // 1. Copy the template document
    logger.log(`Copying template: ${templateId}`);
    // NOTE for Node.js: The response is often nested, e.g., `response.data.id`
    const copyResponse = await driveClient.files.copy({
      fileId: templateId,
      requestBody: { name: newFileName },
    });
    newFileId = copyResponse.id || copyResponse.data.id;

    // 2. Perform the text replacements in the new document
    logger.log(`Replacing text in new file: ${newFileId}`);
    await docsClient.documents.batchUpdate({
      documentId: newFileId,
      requestBody: { requests: replacements },
    });

    // 3. Export the document as a PDF
    logger.log(`Exporting file as PDF...`);
    // NOTE for Node.js: The response is a stream, not a blob.
    const pdfResponse = await driveClient.files.export({
      fileId: newFileId,
      mimeType: 'application/pdf',
    }, { responseType: 'stream' });

    // 4. Create the final PDF file in the destination folder
    logger.log(`Creating PDF file in folder: ${destinationFolderId}`);
    await driveClient.files.create({
      requestBody: {
        name: `${newFileName}.pdf`,
        parents: [destinationFolderId],
      },
      media: {
        mimeType: 'application/pdf',
        body: pdfResponse.body || pdfResponse.data, // Accommodate both runtimes
      },
      fields: 'id',
    });

    logger.log(`Successfully created PDF for ${newFileName}`);
    return { status: 'success' };

  } catch (error) {
    const errorMessage = error.response ? JSON.stringify(error.response.data) : error.message;
    logger.error(`[Core Logic] Failed: ${errorMessage}`);
    return { status: 'error', reason: errorMessage };
  } finally {
    // 5. Clean up the temporary Google Doc
    if (newFileId) {
      logger.log(`Cleaning up temporary file: ${newFileId}`);
      await driveClient.files.delete({ fileId: newFileId });
    }
  }
}

The Platform-Specific “Bootstrap” Code

The only part that needs to change is the code that initializes the clients and calls the core logic.

In Apps Script (Code.gs for testing and delegation):

/**
 * This function is for testing the portable logic *within* Apps Script.
 */
function runPdfJobInAppsScript(job) {
  // 1. Initialize the Apps Script community client libraries
  // These libraries automatically use the user's token via ScriptApp.getOAuthToken()
  const driveClient = new Drive(); // Assumes Drive.gs is in the project
  const docsClient = new Docs();   // Assumes Docs.gs is in the project

  // 2. Call the portable logic
  _portablePdfGeneratorLogic(job, driveClient, docsClient, Logger);
}
/**
 * This function delegates a job to a Cloud Run service, passing the user's
 * OAuth token to extend the "run as user" paradigm.
 */
function delegateJobToCloudRun(job) {
  const CLOUD_RUN_URL = 'https://your-service-url.a.run.app';
  
  const options = {
    method: 'post',
    contentType: 'application/json',
    // Get the user's OAuth token and pass it in the Authorization header.
    headers: {
      Authorization: 'Bearer ' + ScriptApp.getOAuthToken(),
    },
    payload: JSON.stringify(job),
    muteHttpExceptions: true,
  };
  
  const response = UrlFetchApp.fetch(CLOUD_RUN_URL, options);
  Logger.log(response.getContentText());
}

In Node.js (index.js for Cloud Run):

In our Node.js server, we’ll use the OAuth2Client from the google-auth-library. While many Cloud Run examples use GoogleAuth for service accounts, OAuth2Client is specifically designed to work with user-provided OAuth tokens, allowing us to seamlessly continue acting on behalf of the original user.

// Import OAuth2Client instead of GoogleAuth for this purpose
const { google } = require('googleapis');
const { OAuth2Client } = require('google-auth-library'); // 👈 Change this line
const express = require('express');

const app = express();
app.use(express.json());
const PORT = process.env.PORT || 8080;

// --- Main Express Route Handler ---
app.post('/', async (req, res) => {
  // 1. Extract the token from the Authorization header
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).send('Unauthorized: Missing or invalid Authorization header.');
  }
  const userToken = authHeader.split(' ')[1];

  const { job } = req.body;
  if (!job) {
    return res.status(400).send('Invalid payload. Expected JSON with a "job" object.');
  }

  try {
    // 2. Create an OAuth2Client instance
    const auth = new OAuth2Client();

    // 3. Set the credentials using the token from Apps Script (or swap out for a service account config)
    auth.setCredentials({
      access_token: userToken,
    });

    // 4. Initialize the Google clients with the user-authed client
    const driveClient = google.drive({ version: 'v3', auth });
    const docsClient = google.docs({ version: 'v1', auth });

    // Now, any calls made with driveClient or docsClient will act on
    // behalf of the user who ran the Apps Script. 🚀
    const result = await _portablePdfGeneratorLogic(job, driveClient, docsClient, console);

    if (result.status === 'success') {
      res.status(200).send('PDF generated successfully.');
    } else {
      res.status(500).send(`Failed to generate PDF: ${result.reason}`);
    }
  } catch (err) {
    console.error(err);
    // Check for authentication errors specifically
    if (err.code === 401 || err.code === 403) {
      res.status(401).send('Authentication error with Google APIs. The token may be expired or invalid.');
    } else {
      res.status(500).send('An unexpected error occurred.');
    }
  }
});

app.listen(PORT, () => {
  console.log(`PDF generator service listening on port ${PORT}`);
  console.log('Ready to receive a test request...');
});

// (Paste the _portablePdfGeneratorLogic function here)
}

Conclusion: Start Portable, Scale with Confidence

The “eject button” is your strategic advantage, transforming Apps Script from just a scripting environment into the first stage of a professional development lifecycle. By separating your core logic from the convenient but platform-specific built-in services, you give your applications a future-proof foundation.

The key takeaway is simple: write your business logic for the Google APIs, not for the Apps Script runtime.

Your Next Step:The next time you start a project in Apps Script, challenge yourself to write just one core function in this portable style. You’ll not only prepare your code for future scaling but also gain a deeper understanding of the Google APIs themselves.

Apps Script Engine v2.0 is Here! Your Workflow Just Got a TypeScript Power-Up 🚀

 

You heard it right. This is the update you’ve been waiting for. Apps Script Engine now has full-blown TypeScript support! 🤯

We’re talking server-side .gs files and client-side HtmlService code. The whole shebang. While clasp has been on-again, off-again with its TypeScript support, we decided to go all in and deliver the robust, seamless experience you deserve.

Getting started is ridiculously simple. Just tack on the --ts flag during installation:

npx apps-script-engine [directory] --ts

Why TypeScript is a Game-Changer for Apps Script

For larger or more complex Apps Script projects, the introduction of TypeScript offers substantial benefits that can improve code quality and developer productivity:

  • Static Typing: Helps catch common errors during development rather than at runtime, preventing entire classes of bugs related to data types.
  • Enhanced Autocompletion: Provides intelligent code suggestions and autocompletion in the IDE, speeding up the development process.
  • Improved Code Readability: Makes code easier to understand and maintain, as types explicitly define the data structures being used.

What’s New in Version 2.0?

This release is packed with features that modernise the Apps Script development experience:

  • Full TypeScript Support: Write modern, type-safe JavaScript for both frontend and backend code.
  • ES6+ Modules: Organise your code into clean, reusable modules.
  • Frontend Frameworks: Comes with out-of-the-box support for Alpine.js and Tailwind CSS (including Daisy UI).
  • NPM Modules: Leverage the vast ecosystem of NPM modules in your server-side and client-side code.
  • Robust Mocking: The mocking system for google.script.run has been re-engineered to allow for easy simulation of both success and failure handlers during local development.
  • Migration to Vitest: The testing framework has been switched from Jest to Vitest, offering faster performance and a simpler configuration.
  • Gemini CLI Integration: A new GEMINI.md file is included in the project template, providing the Gemini CLI with the necessary context to assist with coding and debugging tasks.
  • CI/CD and Environment Management: The engine includes built-in support for GitHub Actions workflows and managing multiple deployment environments (DEV, UAT, PROD).

This update positions Apps Script Engine as a powerful tool for developers who want to apply modern web development practices to the Google Workspace platform.

Source: Apps Script Engine v2.0 is Here! Your Workflow Just Got a TypeScript Power-Up 🚀

A Secure Sandbox for AI-Generated Apps Script: How to Experiment with Confidence


gas-fakes includes a sandbox feature in an emulation of Apps Script on Node that allows you to control file access and manage test artifacts

The rise of generative AI tools like the Gemini CLI has unlocked incredible potential for automating Google Workspace, allowing developers to generate Google Apps Script code from simple, natural language prompts. However, this power comes with a significant security challenge: how can you safely execute code generated by an AI without granting it broad, potentially risky permissions to your Google Drive?

In a brilliant example of community collaboration, two distinguished developers, Bruce Mcpherson and Kanshi Tanaike, have provided a powerful solution to this very problem. Their combined work showcases an elegant architecture for creating a secure “Fake-Sandbox,” allowing developers to test and run AI-generated code with confidence.

The Problem: The All-or-Nothing Permission Model

At the heart of the issue is that Google Apps Script’s core services often require sweeping permissions. For example, a script designed to organise files often needs the https://www.googleapis.com/auth/drive scope, which grants it sweeping access to all of a user’s files and folders in Google Drive. This presents a clear risk when running code from a source you don’t fully control, as an unintended command could have far-reaching consequences.

Bruce Mcpherson’s Foundation: gas-fakes

The technical cornerstone of the solution is gas-fakes, a powerful Node.js library created by Bruce Mcpherson. This library ingeniously emulates a Google Apps Script environment locally. It works by translating familiar Apps Script calls (like SpreadsheetApp.create()) into their equivalent, direct Google API requests. The library already provides extensive support for the most-used services, including SpreadsheetApp, DocumentApp, DriveApp, and SlidesApp, along with their advanced service counterparts.

This abstraction is the key. By funnelling actions through the underlying APIs, gas-fakes makes it possible to work with more granular, file-specific permissions—a level of control not available with the standard Apps Script services.

Kanshi Tanaike’s Vision: The “Fake-Sandbox”

Seeing the potential of this library, Google Workspace Developer Kanshi Tanaike authored a detailed feasibility study proposing its use as a “Fake-Sandbox.” Tanaike demonstrated how gas-fakes could be integrated directly into the Gemini CLI workflow.

His approach is both simple and effective:

  1. Generate Code: A user provides a prompt to the Gemini CLI (e.g., “Create a new Google Sheet and add the value ‘Hello, World’ to cell A1”).
  2. Execute Locally: The generated Apps Script code is then executed locally on Node.js.
  3. Translate and Secure: The gas-fakes library intercepts the Apps Script commands, translates them into permission-controlled Google API calls, and executes them securely.

Crucially, any files created during this process are contained within the sandbox session. At the end of the run, a simple command (ScriptApp.__behavior.trash()) automatically cleans up by moving all created files to the Google Drive trash, leaving the user’s Drive pristine.

Taking it Further: Granular Controls

Building on this concept, the gas-fakes library now includes even more sophisticated sandbox controls, as detailed in a follow-up post. Developers can now implement:

  • Whitelists to grant read-only or write access to specific, pre-existing files.
  • Per-Service Rules to disable entire services (like DocumentApp) or restrict a service to a specific list of approved methods.

Ultimately, this work provides a vital safety net for innovation. It gives developers the confidence to experiment with AI-generated code, knowing that their core data is protected by a robust and highly configurable sandbox. This practical solution removes a major barrier to entry, establishing a clear blueprint for safely embracing the next wave of Google Workspace automation.

To dive deeper into this solution check out the source links below:

Source: A Fake-Sandbox for Google Apps Script: A Feasibility Study On Securely Executing Code Generated by Gemini CLI by Kanshi Tanaike
Source: Fake-Sandbox for Google Apps Script: Granular controls by Bruce Mcpherson
Code: gas-fakes on GitHub by Bruce Mcpherson

Unlocking Google’s Full API Universe and Authentication Flows in Google Apps Script

A Google Apps Script project that dynamically generates modern, feature-rich client libraries for any public Google API directly from the Google API Discovery Service.

For many developers, Google Apps Script is the go-to platform for rapidly automating and extending Google Workspace. Its simplicity and deep integration are powerful. But as projects grow in ambition, developers often encounter two significant walls: needing to connect to a Google API that isn’t built-in, or requiring an authentication flow, like a service account, that the standard services don’t support.

What if you could break through those walls? What if you could use a robust client library for almost any Google API—from Firebase to Cloud Billing—in seconds, right from Apps Script itself?

Today, I’m excited to introduce the Google API Client Library Generator for Apps Script, a project and code repository designed to solve these very challenges. It comes with a full suite of pre-built libraries, enabling you to significantly expand what’s possible on the platform.

Why This Matters: Beyond the Built-in Services

While Apps Script’s built-in and advanced services are excellent, they represent just a fraction of Google’s vast API ecosystem. This collection of generated libraries unlocks the rest, offering two critical advantages:

  1. Complete API Coverage: The generator uses the Google APIs Discovery Service to create clients for over 400 APIs. If it’s in the Google Discovery Service then there is a library for it in the repository.
  2. Flexible Authentication Flows: Generated libraries are not tied to the standard user-permission model. This means you can use service accounts for server-to-server authentication, or implement other OAuth2 flows as needed.

Getting Started

Getting started is as simple as finding the library you need in the build/ directory of the GitHub repository and copying the code into your Apps Script project. For detailed setup instructions and other authentication options, please refer to the main README.md in the repository.

Unlocking Professional Workflows with Service Accounts

The real power of this approach comes from flexible authentication. For Google Workspace developers, this also unlocks the ability to use service accounts with domain-wide delegation to make API calls on behalf of other users in your domain.

To handle the authentication flow, you’ll need an OAuth2 library. The following example uses the OAuth2 for Apps Script library, but other options are also available. Once you have your chosen library set up, you can use the following pattern:

// The email of the user to impersonate (for domain-wide delegation).
const USER_EMAIL = '[email protected]'; 

function getService_() {
  // Credentials from the service account's JSON key file.
  const serviceAccountCreds = {
    "private_key": "-----BEGIN PRIVATE KEY-----\n...",
    "client_email": "[email protected]",
  };

  // Use a unique name for the service, like 'Drive' or 'BigQuery', to avoid
  // token collisions between different services.
  return OAuth2.createService('Drive:' + USER_EMAIL)
      .setTokenUrl('https://oauth2.googleapis.com/token')
      .setPrivateKey(serviceAccountCreds.private_key)
      .setIssuer(serviceAccountCreds.client_email)
      .setSubject(USER_EMAIL)
      .setCache(CacheService.getUserCache())
      .setScope('https://www.googleapis.com/auth/drive');
}

/**
 * Lists files using the configured service account.
 */
function listFilesWithServiceAccount() {
  const service = getService_();
  if (!service.hasAccess()) {
    console.log('Service Account authentication failed: ' + service.getLastError());
    return;
  }
  
  const token = service.getAccessToken();

  // This is where the generated library is used with the custom token.
  const drive = new Drive({
    token: token 
  });

  const files = drive.files.list({
    supportsAllDrives: true,
    pageSize: 10
  });
  
  console.log('Files found via service account:', JSON.stringify(files, null, 2));
}

Under the Bonnet: The Generator

For those who want to tweak the generation logic or integrate it into their own workflows, the generator itself is included in the repository. It’s a self-contained Apps Script project that fetches API metadata and programmatically constructs modern, robust ES6 classes with features like automatic exponential backoff for handling API errors.

Join the Community and Contribute

This project was heavily inspired by the work of Spencer Easton and aims to build upon that foundation. It’s a community effort.

While libraries for all APIs are generated, not all have been extensively tested. If you use a library and find a bug, or have an idea for an improvement, please open a GitHub Issue. Pull requests are, of course, always welcome. Happy scripting!

Source: GitHub – mhawksey/Google-API-Client-Library-Generator-for-Apps-Script

Go Beyond the Gemini App: Building Custom AI Tools with Gemini CLI and Apps Script

This article explores the integration of the Gemini Command-Line Interface (CLI) with Google Sheets using the Model Context Protocol (MCP). It demonstrates how to leverage the open-source projects MCPApp and ToolsForMCPServer to create a bridge between the Gemini CLI and Google Workspace. This enables users to perform powerful data automation tasks, such as creating, reading, and modifying tables in Google Sheets directly from the command line, using natural language prompts. The article provides practical examples and sample prompts to illustrate the seamless workflow and potential for building sophisticated, AI-powered applications within the Google Cloud ecosystem.

For developers who work in the command line, the introduction of Google’s Gemini Command-Line Interface (CLI) has opened up new ways to interact with AI. The open-source tool allows you to bring the power of Gemini models directly into your terminal, making it a useful companion for coding assistance, content generation, and task automation. While the CLI can interact with your local file system and the internet, its standard capabilities don’t provide a direct path to your personal data within Google Workspace.

But what if you could extend it? What if you could create a secure connection, allowing the Gemini CLI to interact with your own files in Drive, events in Calendar, or emails in Gmail?

Over the past month, Google Workspace Developer Expert Kanshi Tanaike has published an insightful series of blog posts that provides a practical blueprint for achieving just that. In this series, he demonstrates how to use the flexibility of Google Apps Script to create a powerful, personalised bridge between the Gemini CLI and the entire suite of Google Workspace services.

At the centre of Kanshi’s solution is a simple and effective architecture. He shows readers how to build a Model Context Protocol (MCP) server using a Google Apps Script project deployed as a Web App. This server acts as the secure intermediary between the Gemini CLI and your Google account.

The key advantage of this approach lies in its security and simplicity. By using Apps Script, the complex and critical OAuth2 authorisation is handled natively within the Google ecosystem. This means developers can create a robust tool without the overhead of managing credentials or setting up separate cloud infrastructure.

Throughout the series, Kanshi doesn’t just provide the theory; he delivers the tools to make it happen. He has developed and shared two key open-source Apps Script libraries, MCPApp and ToolsForMCPServer, which significantly simplify the process. These libraries provide a ready-to-use framework and a rich set of functions for interacting with Workspace services.

The result is a system capable of executing complex, multi-step automations from a single, natural-language prompt. The examples in his posts speak for themselves:

  • Automated Data Entry: Fetching a multi-day weather forecast and populating it directly into a Google Sheet.
  • Content Creation: Uploading a local PDF to Drive, generating a summary, creating a new Google Slides presentation from that summary, and emailing it to a colleague.
  • Interactive Tasks: Generating a custom survey in Google Forms and sending out the link via Gmail.

This extensibility is what sets the approach apart. While a standard tool like the Gemini App (gemini.google.com) provides a familiar conversational interface, it offers a fixed set of features. This CLI-based method allows developers to keep that same intuitive, conversational style of interaction but makes it completely extensible. With the CLI and a custom MCP server, developers are no longer limited—they can build bespoke tools to solve their specific challenges.

For example, a common request from Workspace users is the ability to generate an entire presentation from source material. Using this framework, a developer could easily build a custom tool to do just that, triggered by a single command.

This series is a great example of the innovation happening within the Google Workspace developer community. While this command-line approach is naturally suited for developers and power users comfortable with scripting, it offers a level of control and automation that is difficult to achieve through graphical interfaces. It provides a clear, powerful, and extensible pattern for anyone in this group looking to explore their own sophisticated AI-powered automations.

We highly recommend diving into the series to see what’s possible. You can start with the most recent post, which links back to the previous articles in the series:

Source: Next-Level Data Automation: Gemini CLI, Google Sheets, and MCP

Bridging the Gap: A Framework for Securely Embedding Apps Script Web Apps on Custom Domains

This framework integrates Google Apps Script web apps into a standard website

Integrating a Google Apps Script web app into a public website offers powerful possibilities, but developers can often hit a wall of limitations. Serving from a custom domain, managing multiple Google account logins, preventing security vulnerabilities like clickjacking, and providing a smooth user experience are significant hurdles.

A new open-source framework from developer Zig Mandel provides a comprehensive solution, offering a flexible framework for embedding Apps Script web apps securely and professionally. At its core, the framework uses a parent website to host the Apps Script in an iframe, using a secure postMessage protocol for communication between the parent website and your web app. A key innovation is its ability to dynamically and securely load different script deployments using a cryptographic signature (org/sig) system, preventing unauthorised use while enabling advanced features like centralised logging and analytics integration.

What This Framework Solves

This solution is more than just an iframe wrapper; it’s a complete integration kit designed to enhance your Apps Script web app to a professional standard. It addresses several key pain points:

  • Custom Domain Serving: Serve your app from your own domain, not the standard script.google.com URL.
  • Secure Embedding: A communication protocol and domain validation prevent your app from being embedded on unauthorized sites.
  • Multi-Account & Workspace Compatibility: The framework is built to handle complexities that arise when users are logged into multiple Google accounts or are using a Google Workspace account.
  • Seamless User Experience: The architecture eliminates the jarring “flash” of a new page loading within the iframe, creating a smooth transition for single-page application (MPA) style web apps.
  • Analytics & Logging Integration: Send events from your Apps Script directly to the parent website’s Google Tag Manager instance and forward client-side logs to a centralized location like Google Cloud Logging.

Summary

In short, this framework hopefully unlocks a better way to implement public-facing Google Apps Script for web applications. For developers it provides the tools to overcome common embedding hurdles, moving beyond simple scripts to create secure, professional, and seamlessly integrated user experiences. To explore the code and get started on your own integration, check out the repository on GitHub.

Source: GitHub – zmandel/demosite_appscript

Agent2Agent (A2A) Communication in Google Workspace with Apps Script

 

Exploring Agent2Agent (A2A) protocol implementation in Google Apps Script seamlessly allows AI agents to access Google Workspace data and functions. This could enable complex workflows and automation, overcoming platform silos for integrated AI applications.

The buzz around AI and collaborative agent systems is growing, and with it, the need for standardized communication. The recently introduced Agent2Agent (A2A) protocol aims to enable exactly that – allowing different AI agents, regardless of their underlying framework, to discover each other’s capabilities and work together. But how can the Google Workspace developer community tap into this exciting new frontier?

Enter prolific Apps Script contributor Kanshi Tanaike, who has once again provided a valuable resource for the community. Kanshi has published a detailed guide and a Google Apps Script library demonstrating how to build an Agent2Agent (A2A) server using Google Apps Script.

Why is this significant?

Kanshi’s work explores the feasibility of implementing a core A2A server component directly within the Google Workspace ecosystem. As Kanshi notes, “Such an implementation could seamlessly allow AI agents to securely access and utilize data and functionalities across Google services like Docs, Sheets, and Gmail via a standardized protocol.”. This opens up possibilities for:

  • Integrating AI agents with your Google Workspace data: Imagine AI agents that can directly interact with your Sheets, Docs, Drive files, or Gmail.
  • Building sophisticated AI-powered workflows: Automate complex tasks that span across different services, orchestrated by communicating AI agents.

Kanshi’s guide walks through the setup and implementing functions that allow AI agents to interact with Google Workspace services like Drive or external APIs via UrlFetchApp. This work significantly lowers the barrier to entry for Google Workspace developers looking to experiment with and implement A2A-compatible agents and as such I highly encourage you to check out the linked source post for the complete guide, code, and library details.

Source: Building Agent2Agent (A2A) Server with Google Apps Script

Unlock Your Productivity Potential with Gemini and Google Calendar (and other Workspace APIs)


As a Google Workspace Developer Advocate, I’m always exploring innovative ways to leverage technology. I’m thrilled to share my new Jupyter Notebook that showcases the power of Gemini and the Google Calendar API for productivity coaching. 🚀✨

This notebook dives into:
– Using Gemini’s multimodal capabilities to analyze calendar data. 📅
– Leveraging function calling to connect Gemini with Google Workspace APIs. 🔗
– Developing a personalized AI productivity coach. 🧑‍🏫

It’s amazing to see how generative AI can transform the way we work and optimize our time. ⏳

Explore the notebook on GitHub and discover how to build your own AI-powered productivity tools! 🛠️

👉 Link: https://lnkd.in/gpTxMMAy

Are you struggling to manage your time effectively? Mohammad Al-Ansari, Google Developer Advocate, has recently shared how the Gemini API can act as a personal productivity coach. The solution uses a Google Colab notebook, which is connected to the Google Calendar API. The Gemini API is used to provide personalized insights and recommendations to boost your productivity and improve your work/life balance. For those who don’t know, Google Colab is a free cloud-based platform for running Jupyter Notebooks, which are interactive coding environments that allow users to write and execute code and can be a useful tool to have in the toolbox when exploring data.

Some of the key features in Mohammad’s ‘Productivity Coach’ are:

  • Function Calling: This notebook uses Gemini’s ‘function calling’ capabilities, allowing it to dynamically interact with the Google Calendar API and retrieve real-time data. This ensures that the analysis and recommendations are always up-to-date and relevant to your current schedule.
  • Google Workspace Integration: By integrating with the Google Calendar API, this notebook shows how the Gemini API can be seamlessly integrated with other Google Workspace services. This opens up exciting possibilities for quickly experimenting with other Workspace data sources, such as Google Docs, Sheets or Drive.
  • Personalized Coaching: As a bonus you can see how Gemini can act as your personal productivity coach, so if nothing else you can get some tailored guidance and support about your own calendar

Check out the notebook to explore!

Source: generative-ai/gemini/use-cases/productivity/productivity_coaching_with_google_calendar.ipynb at main · GoogleCloudPlatform/generative-ai

How Apps Script Became the Ultimate LLM Fine-Tuning Tool

If you have domain-specific knowledge that you want an LLM to leverage, you probably have a use case for fine-tuning. Fine-tuning can significantly improve how well the model understands and responds to your queries, whether it’s legal documents, medical texts, financial reports, or niche industry data.

The most crucial step in this process is structuring your data correctly. If your dataset is well-organized and formatted properly, the rest of the workflow becomes much more manageable. From there, it’s just a matter of setting up a few configurations and automating parts of the process with Apps Script. That’s where things get interesting and surprisingly efficient.

Source: How Apps Script Became the Ultimate LLM Fine-Tuning Tool