claspでGAS開発をモダンにする|ローカル開発・Git管理・TypeScript対応の実務ガイド

claspとは

clasp(Command Line Apps Script Projects)は、GoogleがOSSで提供するGASのCLIツールです。ローカルのファイルとGASプロジェクトを双方向に同期できます。

通常、GASの開発はブラウザ上のスクリプトエディタで行います。claspを使うと、ローカルのエディタ(VS Codeなど)でコードを書き、コマンドひとつでGASプロジェクトに反映できます。

ローカル開発にすることで、Git管理やTypeScript対応、エディタの補完機能など、モダンな開発体験が得られます。GASプロジェクトが増えてきた段階、または複数人で開発する段階で導入を検討する価値があります。

なぜclaspを使うべきか

スクリプトエディタの限界

GAS標準のスクリプトエディタは、簡単なスクリプトの記述には十分です。しかし、プロジェクトの規模が大きくなると以下の課題が顕在化します。

課題スクリプトエディタclasp + ローカルエディタ
バージョン管理手動のバージョン保存のみGit で全履歴を管理
コード補完基本的な補完のみVS Codeの強力な補完
型チェックなしTypeScriptで静的解析
複数人開発同時編集で上書きリスクブランチ + PRベースで安全
コードレビュー不可GitHubのPR機能を利用
テストなしローカルでユニットテスト可能
リファクタリング手動のみエディタのリネーム・検索置換

1〜2個のシンプルなスクリプトなら、スクリプトエディタで十分です。しかし、ファイル数が増えてきた場合や、チームで管理する場合は、claspの導入で開発効率が大幅に向上します。

以下の図は、スクリプトエディタでの直接開発と、claspを使ったローカル開発の比較です。

開発フローの比較スクリプトエディタ直接開発ブラウザでスクリプトエディタを開くエディタ上でコードを編集「実行」ボタンで動作確認バージョン管理なし(手動保存のみ)clasp + ローカル開発VS Codeでコードを編集(型補完あり)git commit でバージョン記録clasp push でGASプロジェクトに反映clasp deploy でバージョン公開

運用メモ claspは既存のGASプロジェクトにも導入できます。clasp cloneで既存プロジェクトをローカルに取り込み、そこからGit管理を開始する方法が最も低リスクです。新規作成の場合はclasp createを使います。

セットアップ手順

前提条件

claspの実行にはNode.jsが必要です。Node.js v16以降がインストールされていることを確認してください。

node -v
# v20.x.x 以降が推奨

claspのインストール

npmでグローバルにインストールします。

npm install -g @google/clasp

インストール後、clasp --versionでバージョンが表示されれば成功です。

Googleアカウントへのログイン

claspからGASプロジェクトを操作するために、Googleアカウントで認証します。

clasp login

ブラウザが開き、Googleアカウントの選択と権限の承認を求められます。承認が完了すると、ホームディレクトリに.clasprc.jsonが作成されます。

ファイル場所内容
.clasprc.jsonホームディレクトリログイン認証情報(トークン)
.clasp.jsonプロジェクトルートスクリプトID・ルートディレクトリ設定
.claspignoreプロジェクトルートpushから除外するファイルのパターン

GAS APIの有効化

初回利用時は、Google Apps Script APIを有効にする必要があります。以下のURLにアクセスし、APIを有効化してください。

https://script.google.com/home/usersettings

「Google Apps Script API」のトグルをオンにします。これが無効のままだと、clasp pushclasp createが失敗します。

プロジェクトの作成とクローン

新規プロジェクトを作成する場合はclasp createを使います。

mkdir my-gas-project
cd my-gas-project
clasp create --type sheets --title "レポート自動化"

--typeオプションで紐づけるGoogleサービスを指定できます。

type作成されるもの
standalone独立したGASプロジェクト
sheetsスプレッドシートに紐づくプロジェクト
docsドキュメントに紐づくプロジェクト
slidesスライドに紐づくプロジェクト
formsフォームに紐づくプロジェクト

既存のGASプロジェクトをローカルに取り込む場合はclasp cloneを使います。

clasp clone <スクリプトID>

スクリプトIDは、スクリプトエディタのURL(https://script.google.com/home/projects/<スクリプトID>/edit)から確認できます。

運用メモ clasp create --type sheetsで作成した場合、Googleドライブのルートに新しいスプレッドシートが自動作成されます。意図したフォルダに配置したい場合は、作成後にドライブ上で移動するか、--parentIdオプションでフォルダIDを指定してください。

基本操作

push / pull

ローカルのファイルをGASプロジェクトに反映するにはclasp pushを使います。

clasp push

逆に、GASプロジェクトの最新状態をローカルに取り込むにはclasp pullを使います。

clasp pull

open

ブラウザでGASのスクリプトエディタを開きます。

clasp open

動作確認やトリガー設定を管理画面から行いたい場合に便利です。

deploy

デプロイメントを作成し、特定のバージョンを公開します。

clasp deploy --description "v1.0 初回リリース"

Web APIとして公開する場合や、アドオンとして配布する場合にデプロイメントが必要です。通常のスクリプト実行であれば、pushだけで動作します。

.clasp.json の設定

clasp createまたはclasp cloneを実行すると、.clasp.jsonが生成されます。

{
  "scriptId": "1a2b3c4d5e6f...",
  "rootDir": "./src"
}

rootDirを指定すると、そのディレクトリ内のファイルだけがpush対象になります。TypeScriptのソースコードをsrc/に配置し、設定ファイルやテストはルートに置く構成が一般的です。

.claspignore の設定

pushから除外するファイルを指定します。.gitignoreと同じ書式です。

node_modules/**
tests/**
*.test.ts
tsconfig.json
package.json
package-lock.json
README.md
.git/**

TypeScriptの設定ファイルやテストコード、依存パッケージはGASプロジェクトには不要なため、除外します。

TypeScript対応

claspはTypeScriptファイル(.ts)を自動的にJavaScriptに変換してからpushします。追加のビルドステップは不要です。

なぜTypeScriptを使うのか

GASはJavaScriptベースですが、TypeScriptを使うことで以下のメリットが得られます。

  • 型の定義により、関数の引数や戻り値の誤りをコード記述時に検出できる
  • VS Codeの補完がGASのAPI(SpreadsheetApp等)に対しても正確に機能する
  • リファクタリング時に、型の不整合を即座に発見できる
  • コードの可読性が向上し、チーム内での認識のずれが減る

型定義のインストール

GASのグローバルオブジェクト(SpreadsheetApp、DriveApp等)の型定義をインストールします。

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

tsconfig.json の設定

プロジェクトルートにtsconfig.jsonを作成します。

{
  "compilerOptions": {
    "lib": ["ES2020"],
    "target": "ES2020",
    "module": "None",
    "strict": true,
    "noImplicitAny": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*.ts"]
}

claspの内部トランスパイラがtsconfig.jsonを参照します。moduleNoneに設定してください。GASにはモジュールシステムがないため、import/export構文は使用できません。

運用メモ claspのTypeScript変換は、型チェックを行わずにトランスパイルのみ実行します。型エラーがあってもclasp pushは成功してしまいます。push前にnpx tsc --noEmitを実行して型チェックを行う習慣をつけてください。後述のGit hookで自動化するのが確実です。

TypeScriptでのGASコード例

以下は、TypeScriptで記述した広告レポート集約のコード例です。

/**
 * 広告媒体のデータ型定義
 */
interface AdMetrics {
  date: string;
  platform: string;
  campaignName: string;
  impressions: number;
  clicks: number;
  cost: number;
  conversions: number;
}

/**
 * 設定値の型定義
 */
interface ScriptConfig {
  reportSheetName: string;
  dataSourceUrl: string;
  notifyEmail: string;
  cpaThreshold: number;
}

/**
 * 設定シートから設定値を読み取る
 */
function loadConfig(): ScriptConfig {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('設定');

  if (!sheet) {
    throw new Error('設定シートが見つかりません');
  }

  return {
    reportSheetName: String(sheet.getRange('B1').getValue()),
    dataSourceUrl: String(sheet.getRange('B2').getValue()),
    notifyEmail: String(sheet.getRange('B3').getValue()),
    cpaThreshold: Number(sheet.getRange('B4').getValue()),
  };
}

/**
 * スプレッドシートのデータをAdMetrics型に変換する
 */
function parseAdData(
  rawData: unknown[][],
  platform: string
): AdMetrics[] {
  const result: AdMetrics[] = [];

  for (let i = 1; i < rawData.length; i++) {
    const row = rawData[i];
    const cost = Number(row[4]) || 0;
    const conversions = Number(row[5]) || 0;

    result.push({
      date: Utilities.formatDate(
        new Date(row[0] as string), 'Asia/Tokyo', 'yyyy-MM-dd'
      ),
      platform,
      campaignName: String(row[1]),
      impressions: Number(row[2]) || 0,
      clicks: Number(row[3]) || 0,
      cost,
      conversions,
    });
  }

  return result;
}

/**
 * CPAの異常値を検出する
 */
function detectCpaAnomalies(
  metrics: AdMetrics[],
  threshold: number
): AdMetrics[] {
  return metrics.filter((m) => {
    if (m.conversions === 0) return false;
    const cpa = m.cost / m.conversions;
    return cpa > threshold;
  });
}

/**
 * メイン実行関数
 */
function main(): void {
  const config = loadConfig();

  const sourceSs = SpreadsheetApp.openByUrl(config.dataSourceUrl);
  const sourceData = sourceSs.getSheets()[0].getDataRange().getValues();
  const metrics = parseAdData(sourceData, 'Google広告');

  const anomalies = detectCpaAnomalies(metrics, config.cpaThreshold);

  if (anomalies.length > 0) {
    const lines = anomalies.map((a) => {
      const cpa = Math.round(a.cost / a.conversions);
      return `${a.campaignName}: CPA ${cpa.toLocaleString()}円`;
    });

    MailApp.sendEmail(
      config.notifyEmail,
      `【アラート】CPA異常値 ${anomalies.length}件`,
      lines.join('\n')
    );
  }

  Logger.log(`処理完了: ${metrics.length}件中 ${anomalies.length}件が異常値`);
}

型定義(interface)を導入することで、データ構造が明示されます。関数の引数と戻り値の型が宣言されているため、呼び出し側での誤用をエディタが検出できます。

Git連携の実務

.gitignore の設計

GASプロジェクトのGit管理では、以下の.gitignoreを設定します。

node_modules/
.clasprc.json
.env
*.log
dist/

.clasprc.jsonにはGoogleアカウントの認証トークンが含まれるため、絶対にGitにコミットしないでください。.clasp.jsonにはスクリプトIDが含まれますが、これは秘密情報ではないためコミットして問題ありません。

ファイルGit管理理由
.clasp.jsonするスクリプトIDはチームで共有する
.clasprc.jsonしない認証トークンが含まれる
.claspignoreするpush対象の定義はチームで統一する
tsconfig.jsonするTypeScript設定はチームで統一する
package.jsonする依存パッケージの定義
node_modules/しないnpm installで再現可能

ブランチ戦略

GASプロジェクトの開発には、シンプルなブランチ戦略が適しています。

main(本番)
  └── feature/xxx(機能開発)

GASには「ステージング環境」の概念がないため、複雑なブランチモデルは不要です。mainブランチが本番のGASプロジェクトに対応し、機能追加はfeatureブランチで開発してPRをマージする流れが実用的です。

PRベースのデプロイフロー

clasp開発ワークフローローカル開発VS Code + TypeScriptgit commitfeatureブランチgit pushGitHubPR + レビューコードレビューmainにマージマージコミットclasp pushGASに反映GASプロジェクト本番実行環境PRがマージされたタイミングでclasp pushを実行し、GASプロジェクトに反映する

PRがマージされた後にclasp pushを実行するのが基本的な流れです。GitHub Actionsで自動化することも可能ですが、GASプロジェクトの認証情報(.clasprc.jsonのトークン)をCI環境に配置する必要があるため、セキュリティ面の検討が必要です。

小規模チームであれば、マージ担当者がローカルでclasp pushを手動実行するシンプルな運用で十分な場合が多いです。

プロジェクト構成のベストプラクティス

ディレクトリ構成

以下は、claspプロジェクトの推奨ディレクトリ構成です。

my-gas-project/
├── .clasp.json          # スクリプトID設定
├── .claspignore         # push除外ファイル
├── .gitignore           # Git除外ファイル
├── package.json         # npm依存定義
├── tsconfig.json        # TypeScript設定
├── src/                 # GASソースコード(pushの対象)
│   ├── main.ts          # エントリーポイント
│   ├── config.ts        # 設定読み取り
│   ├── fetcher.ts       # データ取得
│   ├── reporter.ts      # レポート生成
│   ├── notifier.ts      # 通知送信
│   └── appsscript.json  # GASプロジェクト設定
└── tests/               # テストコード(pushされない)
    ├── config.test.ts
    └── fetcher.test.ts

src/ディレクトリにGASにpushするファイルだけを配置し、.clasp.jsonrootDir./srcに設定します。

ファイル分割の指針

ファイル責務内容
main.tsエントリーポイントトリガーから呼ばれる関数を定義
config.ts設定管理スクリプトプロパティ・設定シートの読み取り
fetcher.tsデータ取得外部APIやスプレッドシートからのデータ取得
reporter.tsレポート生成データの加工・シートへの書き出し
notifier.ts通知Slack・メール通知の送信

1ファイルに全処理を書くと、可読性が下がり変更の影響範囲が把握しにくくなります。責務ごとにファイルを分割し、各ファイルは300行以内に収めるのが目安です。

運用メモ GASにはモジュールシステムがないため、TypeScriptのimport/exportは使えません。ファイルを分割しても、すべての関数はグローバルスコープに配置されます。名前の衝突を避けるために、ファイルごとにプレフィックス(config_loadfetch_adData等)を付けるか、名前空間オブジェクトを使う方法があります。

appsscript.json

GASプロジェクトのマニフェストファイルです。使用するGoogleサービスのスコープや、タイムゾーン、ランタイムバージョンを定義します。

{
  "timeZone": "Asia/Tokyo",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/spreadsheets",
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/script.send_mail"
  ]
}

oauthScopesを明示的に記述すると、スクリプトが要求する権限を最小限に制御できます。記述しない場合は、GASが使用するAPIから自動的に推定しますが、不要な権限が含まれることがあります。

Git hookによる品質チェック

push前に型チェックとリントを自動実行することで、GASプロジェクトへの不正なコードの反映を防止できます。

pre-commit hookの設定

package.jsonにhuskyとlint-stagedを導入します。

npm install --save-dev husky lint-staged
npx husky init

.husky/pre-commitに以下を記述します。

#!/usr/bin/env sh
npx lint-staged

package.jsonにlint-stagedの設定を追加します。

{
  "lint-staged": {
    "src/**/*.ts": [
      "npx tsc --noEmit"
    ]
  }
}

これにより、git commitのたびにTypeScriptの型チェックが実行されます。型エラーがある場合はコミットが中断されるため、GASプロジェクトに不正なコードがpushされるリスクを低減できます。

clasp push前チェックスクリプト

clasp pushの前にも型チェックを行うスクリプトをpackage.jsonに定義しておくと安全です。

{
  "scripts": {
    "check": "npx tsc --noEmit",
    "push": "npm run check && clasp push",
    "deploy": "npm run push && clasp deploy"
  }
}

npm run pushを実行すれば、型チェックが通った場合のみclasp pushが実行されます。

注意点

clasp pushの上書きリスク

clasp pushはGASプロジェクトの全ファイルをローカルの内容で上書きします。差分反映ではなく全量置換です。

もし別のメンバーがスクリプトエディタで直接編集した内容があれば、clasp pushで上書きされて消えます。claspを導入したら、スクリプトエディタでの直接編集は原則禁止にしてください。

操作動作リスク
clasp pushローカル → GAS(全量上書き)エディタの直接編集が消える
clasp pullGAS → ローカル(全量上書き)ローカルの未コミット変更が消える
clasp push —watchファイル変更を検知して自動push開発中の不完全なコードが反映される

push前には必ずclasp pullで最新の状態を確認する、もしくは「スクリプトエディタでは編集しない」というルールをチームで徹底してください。

認証の有効期限

.clasprc.jsonに保存される認証トークンには有効期限があります。期限切れになるとclasp push等のコマンドが失敗します。

clasp login --creds creds.json

再ログインで解決します。頻繁にログインが切れる場合は、サービスアカウントを使った認証も検討してください。

チーム開発時の競合対策

複数人で同じGASプロジェクトを開発する場合、以下のルールを設けておくと競合を防げます。

  • スクリプトエディタでの直接編集を禁止する
  • clasp pushの実行権限をmainブランチのマージ担当者に限定する
  • push前に必ずgit pullでmainブランチの最新を取り込む
  • .clasp.jsonのスクリプトIDは全員が同じ値を使用する

運用メモ 一人で開発する場合でも、claspの導入は有効です。Gitの履歴があれば、「先週まで動いていた処理がなぜ壊れたか」を差分から追跡できます。スクリプトエディタのバージョン保存機能では、変更の理由や背景を記録できません。コミットメッセージに変更の意図を残す習慣は、将来の自分へのドキュメントになります。

まとめ

claspは、GAS開発にバージョン管理・型安全・コードレビューのプラクティスを導入するためのツールです。スクリプトエディタでの開発が手狭に感じ始めたタイミングが導入の適期です。

導入の手順は、npm install → clasp login → clasp clone(またはcreate)の3ステップです。TypeScript対応も@types/google-apps-scriptを追加するだけで始められます。

最初のステップとしては、既存のGASプロジェクトをclasp cloneでローカルに取り込み、Git管理を開始するだけで十分です。TypeScript化やGit hookの導入は、その後で段階的に進めてください。

チームで開発する場合は、「スクリプトエディタでの直接編集を禁止する」というルールだけは初日から徹底することをおすすめします。claspの価値は、コードの一元管理にあります。管理画面での編集が混在すると、その価値が損なわれます。

r
ryottaman

運用型広告のコンサルタント。Google広告・Meta広告・Yahoo!広告を中心に10年以上の実務経験。

この記事について感想やご質問を送れます

誤りの指摘、補足情報、ご質問など、お気軽にどうぞ。