mcpField
A
appscript

appscript

github.com/smkeramati開発185 回インストール12 週間前に更新
リポジトリ

appscript について

appscript は、clasp を使ってターミナルから Google Apps Script プロジェクトを開発・管理するスキルです。ローカル編集からテスト、デプロイまでを扱い、プロジェクト構成やデバッグも案内します。

主な機能

  1. 01スクリプトのローカル編集とプッシュ
  2. 02バインド型・スタンドアロン型の複製と管理
  3. 03関数のリモート実行とログ確認
  4. 04デプロイバージョンの作成と管理
  5. 05TypeScript をコンパイルしてからプッシュ

活用シーン

  1. 01ターミナルから Google Apps Script プロジェクトを保守
  2. 02関数をテストして実行ログを調査
  3. 03Web App、API Executable、Add-on のデプロイ

MCP 対応

ドキュメントでは、clasp を MCP サーバーとして使い、Claude Code から Google Apps Script プロジェクトを直接管理する方法を説明しています。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/smkeramati/appscript --skill appscript

インストール後、Claude Code で/appscriptを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

README.md
LICENSE
.gitignore
TODO.md
appscript-workspace/iteration-1/
benchmark.json
appscript-workspace/iteration-1/eval-1-weekly-email/
eval_metadata.json
appscript-workspace/iteration-1/eval-1-weekly-email/with_skill/
timing.json
grading.json
appscript-workspace/iteration-1/eval-1-weekly-email/with_skill/outputs/
response.md
metrics.json
appscript-workspace/iteration-1/eval-1-weekly-email/without_skill/
grading.json
timing.json
appscript-workspace/iteration-1/eval-1-weekly-email/without_skill/outputs/
metrics.json
response.md
appscript-workspace/iteration-1/eval-2-webhook-app/
eval_metadata.json
appscript-workspace/iteration-1/eval-2-webhook-app/with_skill/
timing.json
grading.json
appscript-workspace/iteration-1/eval-2-webhook-app/with_skill/outputs/
metrics.json
response.md
appscript-workspace/iteration-1/eval-2-webhook-app/without_skill/
grading.json
timing.json
appscript-workspace/iteration-1/eval-2-webhook-app/without_skill/outputs/
metrics.json
response.md
appscript-workspace/iteration-1/eval-3-timeout-fix/
eval_metadata.json
appscript-workspace/iteration-1/eval-3-timeout-fix/with_skill/
timing.json
grading.json
appscript-workspace/iteration-1/eval-3-timeout-fix/with_skill/outputs/
response.md
appscript-workspace/iteration-1/eval-3-timeout-fix/without_skill/
timing.json
appscript-workspace/iteration-1/eval-3-timeout-fix/without_skill/outputs/
metrics.json
response.md

詳細

appscript — clasp による Google Apps Script

ターミナルから Google Apps Script プロジェクトを開発、編集、デプロイできます。作成/クローン → ローカルで編集 → プッシュ → テスト → デプロイという、ライフサイクル全体をカバーします。ブラウザーでのコピー&ペーストは不要です。

クイックスタート

# Verify clasp is installed (needs Node 22+)
clasp --version
npm install -g @google/clasp   # install if missing

# One-time: enable Apps Script API in your Google account
# https://script.google.com/home/usersettings → toggle ON
# Without this, every clasp command fails with an authorization error.

clasp login                                    # authenticate (opens browser)
clasp create-script --title "My Script"        # start a new standalone project
# — or —
clasp clone-script <scriptId>                  # clone existing project
# scriptId: script.google.com → gear icon → Script ID

.gs ファイルをローカルで編集してから、clasp push を実行します。これが基本の作業サイクルです。


スクリプトの種類:バインド型とスタンドアロン型

この違いは、作成、クローン、データへのアクセス方法に関わるため重要です。

スタンドアロンスクリプト — script.google.com または clasp create-script を使って作成します。Drive 内で独立して動作します。明示的な ID を指定して Google サービスにアクセスします(例:SpreadsheetApp.openById('...'))。

コンテナバインド型スクリプト — シート、ドキュメント、フォーム、スライドの内部から「拡張機能 → Apps Script」を選択して作成します。親ファイルと密接に連携します。GAS はスクリプトがどのファイルに属するかを認識しているため、引数なしで SpreadsheetApp.getActiveSpreadsheet() を呼び出せます。onEdit(e) などのトリガーが機能するのはバインド型スクリプトのみです。

バインド型スクリプトをローカルで使用する方法:

  1. シート/ドキュメントを開く → 拡張機能 → Apps Script
  2. 歯車アイコン(プロジェクトの設定)→ スクリプト ID をコピー
  3. clasp clone-script <scriptId> — これでローカルファイルを取得できます

主な動作上の違い:

// Bound script — works without an ID
const ss = SpreadsheetApp.getActiveSpreadsheet();

// Standalone script — must supply the ID
const ss = SpreadsheetApp.openById('1BxSheet...');

プロジェクト構成

my-project/
├── .clasp.json           ← project config (scriptId, rootDir)
├── .claspignore          ← gitignore-style exclusions from push
├── appsscript.json       ← manifest (must exist and be pushed)
├── Code.gs               ← main logic
├── Utils.gs              ← helpers
└── ui.html               ← HTML for web apps / sidebars

すべての .gs ファイルはグローバルスコープを共有します。モジュールや import/export はありません。Utils.gs で定義した関数は、Code.gs から自動的に利用できます。トップレベルの宣言ではファイルの読み込み順序が重要です。必要に応じて .clasp.json の filePushOrder で制御してください。

appsscript.json では、必ず V8 ランタイムを使用してください。V8 では ES6 以降の機能(アロー関数、async/await 構文、分割代入)が使えます。使用しない場合は、ES5 の Rhino で動作します。

{
  "timeZone": "America/New_York",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

日常のワークフロー

clasp show-file-status          # preview what will push/pull (dry run)
clasp push                      # upload local → Google
clasp push --watch              # auto-push on every file save
clasp push --force              # skip confirmation prompts

clasp pull                      # download Google → local
clasp pull --versionNumber 3    # pull a specific version

実行とデバッグ

# Execute a function remotely
clasp run-function myFunction
clasp run-function processData --params '["arg1", 42]'

# Stream Cloud Logging
clasp tail-logs
clasp tail-logs --watch         # continuous
clasp tail-logs --json          # machine-readable

# Debug clasp itself
DEBUG=clasp:* clasp push

clasp run-function を実行するには、プロジェクトをAPI 実行可能ファイルとしてデプロイするか、Apps Script API を有効にした GCP プロジェクトをリンクする必要があります。この設定がない場合は、script.google.com の Apps Script エディタから直接プッシュしてテストするか、リンクされたシートからトリガーしてください。


バージョンとデプロイ

バージョンは変更できないスナップショットです。デプロイはバージョンを参照し、スクリプトを外部に公開します。

clasp create-deployment --description "v1.0 initial release"
clasp create-deployment --versionNumber 3 --description "hotfix"

clasp list-deployments
clasp update-deployment <deploymentId> --versionNumber 4 --description "v1.1"
clasp delete-deployment <deploymentId>
clasp delete-deployment --all

デプロイの種類(appsscript.json で設定):

  • ウェブアプリ — doGet(e)/doPost(e) が必要です。公開 URL からアクセスできます
  • API 実行可能ファイル — 外部の呼び出し元から clasp run-function を実行できるようにします
  • アドオン — Google Workspace Marketplace で配布できます

認証

clasp login                              # standard OAuth (opens browser)
clasp show-authorized-user               # confirm active account
clasp logout

# Multiple accounts
clasp login --user work
clasp login --user personal
clasp push --user work                   # specify per command

# CI/CD (no browser)
clasp login --adc                        # uses GOOGLE_APPLICATION_CREDENTIALS
clasp login --creds client_secret.json   # org GCP project OAuth

API の管理

clasp enable-api sheets                  # enable Sheets API for this project
clasp list-apis                          # see available and enabled APIs
clasp disable-api drive

TypeScript

Clasp v3 では、組み込みの TypeScript トランスパイル機能が削除されました。推奨される方法は、外部でコンパイルしてから出力をプッシュすることです。

セットアップ:

npm install --save-dev typescript rollup @rollup/plugin-typescript @types/google-apps-script

rollup.config.js:

import typescript from '@rollup/plugin-typescript';
export default {
  input: 'src/index.ts',
  output: { file: 'dist/Code.js', format: 'esm' },
  plugins: [typescript()]
};

.clasp.json — コンパイル済み出力を rootDir に指定します:

{ "scriptId": "...", "rootDir": "dist/" }

ビルドしてプッシュします:

npx rollup -c && clasp push

TypeScript を使わずに型ヒントを利用する — VS Code の自動補完のために型定義をインストールします:

npm install --save-dev @types/google-apps-script

GAS ライブラリ

ライブラリを使うと、ファイルをコピーせずに GAS プロジェクト間でコードを共有できます。

ライブラリの使用方法:

  1. 作成者からライブラリのスクリプト ID を入手します
  2. appsscript.json に追加します:
{
  "dependencies": {
    "libraries": [
      {
        "userSymbol": "MyLib",
        "libraryId": "1T03atLib...",
        "version": "3"
      }
    ]
  }
}
  1. コード内で MyLib.functionName() としてアクセスします

ライブラリの作成方法:

  1. 通常どおりスクリプトを作成します
  2. 「ライブラリ」タイプとしてデプロイします(スクリプトエディタで、デプロイ → 新しいデプロイ → ライブラリ)
  3. スクリプト ID を利用者と共有します。新しいデプロイのたびに、利用者はバージョン番号を追加します

注:GAS が実行時にライブラリを解決するため、ライブラリを使うと関数呼び出しごとに約 50 ミリ秒のオーバーヘッドが発生します。パフォーマンスが重要なホットパスでは、代わりにコードをインライン化してください。


GAS のコード品質

Sheets の操作をまとめて実行する

Google サービス(Sheets、Drive、Gmail など)を呼び出すたびに、約 100~500ms の HTTP ラウンドトリップが発生します。ループ内で 100 個のセルを個別に読み取ると、100 回のリクエストが順番に実行され、6 分の実行タイムアウトに達することもよくあります。読み取りと書き込みはまとめて実行してください。

❌ API 呼び出し 100 回 — 遅く、タイムアウトのリスクがあります:

for (let i = 1; i <= 100; i++) {
  const val = sheet.getRange(i, 1).getValue();
  sheet.getRange(i, 2).setValue(val * 2);
}

✅ API 呼び出し 2 回 — 高速です:

const vals = sheet.getRange('A1:A100').getValues();   // one read
const result = vals.map(([v]) => [v * 2]);
sheet.getRange('B1:B100').setValues(result);           // one write
SpreadsheetApp.flush();   // commit buffered writes before any subsequent read

GAS は書き込みをバッファリングするため、SpreadsheetApp.flush() が必要です。これを省略すると、書き込み直後の読み取りで古いデータが返されることがあります。

言語の制限
// ✅ Works in V8
const fn = (x) => x * 2;
const [a, ...rest] = array;

// ⚠️ async/await syntax works in V8, BUT GAS has no event loop
// Only use it if you have a real native Promise to await.
// setTimeout, setInterval, and browser I/O never fire — there's no scheduler.
async function example() {
  const result = await someNativePromise;   // ok
  // await fetch(...) — won't work, use UrlFetchApp.fetch() instead
}

// ❌ Never works in GAS (any runtime)
import { foo } from './utils.js'   // no ES modules — global scope only
export default function() {}
fetch('https://api.example.com')   // use UrlFetchApp.fetch() instead
setTimeout(() => {}, 1000)         // no timer callbacks
window / document / localStorage   // no DOM or browser APIs

// ❌ V8 parse error — avoid
class Foo { #privateField = 1; }   // private class fields not supported
PropertiesService に設定を保存する

.gs ファイルに API キーや設定をハードコードすると、Google にプッシュされ、スクリプト編集者から見える状態になります。代わりに PropertiesService に保存してください。デプロイ間で保持され、ソースファイルにも含まれません。

// Write once (e.g., a setup function)
PropertiesService.getScriptProperties().setProperty('API_KEY', 'your-secret');

// Read anywhere
const key = PropertiesService.getScriptProperties().getProperty('API_KEY');

よくあるパターン

ウェブアプリ(HTTP ハンドラー):

function doGet(e) {
  return HtmlService.createHtmlOutputFromFile('ui').setTitle('My App');
}
function doPost(e) {
  const data = JSON.parse(e.postData.contents);
  // process...
  return ContentService.createTextOutput(JSON.stringify({ ok: true }))
    .setMimeType(ContentService.MimeType.JSON);
}

時間ベースのトリガー:

function setupTrigger() {
  ScriptApp.newTrigger('myFunction').timeBased().everyHours(1).create();
}
// To remove all triggers:
ScriptApp.getProjectTriggers().forEach(t => ScriptApp.deleteTrigger(t));

外部 HTTP リクエスト:

const res = UrlFetchApp.fetch('https://api.example.com/data', {
  method: 'post',
  contentType: 'application/json',
  payload: JSON.stringify({ key: 'value' }),
  headers: { Authorization: 'Bearer ' + token }
});
const json = JSON.parse(res.getContentText());

コストの高いフェッチをキャッシュする(最大 6 時間):

const cache = CacheService.getScriptCache();
let data = cache.get('mykey');
if (!data) {
  data = JSON.stringify(UrlFetchApp.fetch('https://api.example.com').getContentText());
  cache.put('mykey', data, 1500);   // 25 minutes
}
return JSON.parse(data);

スリープによるレート制限対策:

// When hitting APIs that throttle (e.g. UrlFetch returning 429)
items.forEach((item, i) => {
  processItem(item);
  if (i % 10 === 9) Utilities.sleep(1000);   // pause 1s every 10 calls
});

Gemini AI(Ai サービス経由 — GAS ネイティブ):

// Available in GAS without any API key setup — uses project's linked GCP
function summarizeText(text) {
  const model = Ai.getGenerativeModel({ model: 'gemini-2.0-flash' });
  const result = model.generateContent(text);
  return result.response.text();
}

注:Ai サービスを使用するには、Vertex AI または Generative Language API が有効になっている GCP プロジェクトをリンクする必要があります。または、独自の API キーを使って UrlFetchApp.fetch() 経由で Gemini REST API を呼び出してください。


トラブルシューティング

エラー原因対処方法
Apps Script API has not been usedアカウントで API が有効になっていませんhttps://script.google.com/home/usersettings → 有効にする
Could not find .clasp.jsonプロジェクトのルートにいませんプロジェクトディレクトリに cd します
Authorization requiredマニフェストで OAuth スコープが変更されています再度プッシュし、スクリプトエディタで再認証します
Script timeout6 分の実行制限を超えています小さなバッチに分割し、トリガー経由で連鎖させます
Service using too much computer time1 日あたりの割り当て上限に達していますバッチ操作を使用し、24 時間待ちます。Workspace アカウントでは上限が高くなります
書き込み後に古いデータが表示される書き込みがバッファリングされています読み取りの前に SpreadsheetApp.flush() を呼び出します
プッシュ確認のループ対話型ターミナルのプロンプトです--force フラグを追加します
アップグレード後にコマンドが見つからないClasp v2 → v3 で名前が変更されましたreferences/clasp-commands.md の名称変更表を参照してください
HttpResponseException: 429UrlFetch のレート制限に達しています呼び出しの間に Utilities.sleep(1000) を追加し、リクエストをまとめます
ReferenceError: X is not definedファイルの読み込み順序に問題があります.clasp.json に filePushOrder を追加します

MCP / AI 統合

clasp を MCP サーバーとして使用すると、Claude Code から GAS プロジェクトを直接管理できます。

claude mcp add clasp -- npx -y @google/clasp mcp
# Or in Claude Code:
# /plugin install @google/clasp

参考ファイル

必要に応じて読み込んでください。詳細が必要でない限り、事前に読み込まないでください。

ファイル読み込むタイミング
references/clasp-commands.md任意のコマンドのフラグをすべて確認する場合、または clasp v2 から移行する場合(名称変更表がすべて記載されています)
references/gas-reference.md1 日あたりの割り当て、利用可能なすべてのサービス、デプロイマニフェストのフィールド、その他のコードパターン、トリガーの種類を確認する場合
references/config-files.md.clasp.json / appsscript.json / .claspignore のフィールドをすべて確認する場合

コメント