Claude Media
Claude CodeでServiceNow SDKのFluentアプリを作る — build通過を完了条件に

Claude CodeでServiceNow SDKのFluentアプリを作る — build通過を完了条件に

Claude CodeでServiceNow Fluent SDKのアプリを作る手順です。auth・init・build・installの流れと、build通過を完了条件にしinstallへ確認を挟む設定例を示します。

ServiceNow Fluent SDKは、ServiceNowアプリのメタデータをTypeScriptで書き、ビルドしてインスタンスへ入れるための道具です。Claude Codeに任せやすいのは、buildという手元で完結する検証があるからです。完了条件を「buildが通ること」に置けば、インスタンスに触れる前にClaude Codeが自分で誤りを直せます。

この記事では、初期化からbuild・installまでの流れと、Claude Codeに渡す3つの入口、CLAUDE.mdとpermissionsの設定例を順に示します。

ServiceNow Fluent SDKとは何か

ServiceNow SDKは、ServiceNow Fluentでアプリをソースコードとして開発するためのSDKです。Fluentは、プラットフォームのレコードに直接対応する型付きAPI関数を並べた、アプリメタデータ用のドメイン固有言語(DSL)です。画面で設定する代わりにTypeScriptで定義し、SDKでデプロイします。

ServiceNowのアプリは、StudioやフォームでUIから作るのが普通です。それでもコードレビューしにくく、差分が追いにくく、何が変わったか見失いやすいという問題があります。Fluentはこのメタデータをコードにして、バージョン管理・IDE補完・型チェック・ビルドを使えるようにします。

Claude Codeとの相性は、次の3点から説明できます。

  • メタデータが.now.tsファイルなので、Claude Codeが通常のコードと同じ手つきで読み書きできる
  • buildが参照・型・構造を検証するので、Claude Codeが結果を読んで直す反復が成立する
  • queryでインスタンスのレコードを引け、explainでSDK同梱のドキュメントを読める

前提と認証

作業を始める前に、次の3点を揃えます。

項目内容
Node.js内容20以上とnpm
ServiceNowインスタンス内容adminアクセスのあるもの。PDI(個人開発者インスタンス)でも動く
知識内容TypeScriptと、コマンドラインでの開発の基本

認証は、インスタンスからinitする前、またはアプリを入れる前に済ませます。

npx @servicenow/sdk auth --add https://<インスタンス名>.service-now.com
npx @servicenow/sdk auth --list

--addは対話式のセッションを開き、既定の認証情報を手元のマシンに保存します。複数のインスタンスを使い分けるときは、インスタンスに触れる各コマンドに--auth <alias>を付けて、使う認証情報を指定します。

認証情報はAES-256-GCMで暗号化されて~/.now-sdk/credentials.encに保存され、暗号鍵だけがOSのキーチェーンにあります。パスワードや長期シークレット(リフレッシュトークン)は、--listや--printでも表示されません。Claude Codeにパスワードを渡す必要はなく、認証は人が先に済ませておけば足ります。

エージェント経由やCIのように対話できない環境では、--usernameと--password-stdinで渡す形が用意されています。パスワードをpsにも履歴にも残さない、docker login --password-stdinと同じ方式です。

Claude Codeに渡す3つの入口

Fluentは新しい言語に見えて、実体はTypeScriptです。ただしAPIは数十種類あり、Claude Codeが推測で書くと、存在しないプロパティを使いがちです。正しい知識の入口は3つあります。

入口1: AIエージェント用のスキル

SDK 4.6.0以降の@servicenow/sdkは、専用のAIエージェント用スキルを同梱しています。Claude、Cursor、GitHub Copilot、Grokなどのエージェントでの利用が想定されています。ドキュメントによると、次の特徴があります。

  • どのプロジェクトでも、コードを書く前に、クイックスタートとFluent言語のドキュメントを自動で読む
  • 汎用の資料ではなく、プロジェクトに入っている@servicenow/sdkのバージョンのドキュメントを読む
  • 接続済みインスタンスに問い合わせて、sys_idの検索・テーブル列の確認・レコードの有無・選択肢の値・ロールとスコープを調べる
  • Table()・BusinessRule()・Record()の定義を、確認なしに削除しないといった安全上のルールを持つ

最後の削除の話は、実装上の理由があります。削除が、次のインストール時にkeys.tsを通じて伝播する場合があり、コードを見ただけでは分からないからです。

入口2: Claude Codeのプラグイン

Claude Codeのプラグインページにはservicenow-sdkが載っています。提供元はServiceNowで、説明は「Fluent SDKでServiceNowアプリの作成・編集・デプロイを行う」ものです。ページに載っているインストールコマンドは次のとおりです。

claude plugin install servicenow-sdk@claude-plugins-official

プラグインの中身(スキルやコマンドの構成)は、ページには書かれていません。入れたあとに/pluginで内容を確かめてください。プラグインの仕組みそのものはClaude Codeのプラグインとマーケットプレイスで扱っています。

入口3: SDK同梱のドキュメントとllms.txt

スキルを使わないなら、ドキュメントサイトを直接参照できます。llms.txtは、ガイドとAPIページへのリンクを集めた索引です。バージョンごとの索引もversions.jsonから辿れるので、プロジェクトのSDKバージョンに合わせられます。

now-sdk explainは、SDK同梱のドキュメントを端末に表示します。APIは<名前>-api、ガイドは<名前>-guideという命名で、キーワードでも検索できます。

now-sdk explain --list
now-sdk explain BusinessRule
now-sdk explain business-rule-guide --format raw

--format rawは装飾のないMarkdownを返すので、Claude Codeに読ませるときはこちらが向きます。

手順: 初期化からinstallまで

流れは、プロジェクトの作成、Fluentの記述、build、installの4段階です。

1. プロジェクトを作る

新しいアプリはinitで作ります。フラグを省くと、対話式で聞かれます。

npx @servicenow/sdk init \
  --appName "My App" \
  --packageName "my-app" \
  --scopeName "x_acme_my_app"
npm install

スコープ名はx_<会社コード>_<アプリ名>の形です。会社コードは、システムプロパティsn_appauthor.all_company_keysで調べられ、アプリのスコープはこの会社コードで始まっていないとinstallが通りません。initは現在のディレクトリにファイルを書くので、空のフォルダーを先に作ってください。

生成されるプロジェクトは、おおよそ次の構成です。

metadata/**/*.xml      # 既存のXMLメタデータ
src/
  fluent/              # Fluentファイル(.now.ts)
    generated/
      keys.ts          # sys_idを保持するキーファイル
now.config.json        # スコープ・アプリ名などの設定
package.json

now.config.jsonはスコープとアプリ名を持ち、インスタンスの接続情報は持ちません。接続情報はauthで別に管理されます。型定義が要るときは、npx @servicenow/sdk dependenciesを実行します。GlideRecord<'incident'>のような型の補完は、これで効くようになります。

すでにインスタンスにあるアプリを取り込む場合は、--fromにsys_appレコードのsys_idを渡します。

npx @servicenow/sdk init --from <sys_appレコードのsys_id>

この場合、既存のメタデータはXMLのままmetadata/に置かれ、アプリには変更が入りません。Fluentへの変換はtransformで、あとから少しずつ進められます。

2. Fluentでメタデータを書く

Fluentのファイルは、既定でsrc/fluent/の下に.now.tsとして置きます。@servicenow/sdk/coreから関数を読み込み、レコードを定義します。ドキュメントの例は、incidentの短い説明を大文字にするビジネスルールです。

// src/fluent/business-rules/uppercase-short-description.now.ts
import { BusinessRule } from '@servicenow/sdk/core'
 
BusinessRule({
    $id: Now.ID['uppercase-short-description'],
    name: 'Uppercase Short Description',
    table: 'incident',
    when: 'after',
    action: ['insert', 'update'],
    script: `(current) => {
        current.short_description = current.short_description.toString().toUpperCase()
    }`,
})

Nowはビルド時にSDKが登録するグローバルなので、importは要りません。スクリプトは文字列で書けるほか、別ファイルの関数をimportして渡す形も取れます。後者ならGlide APIの型チェックが効くので、Claude Codeに書かせるなら関数を別ファイルに切り出す形が扱いやすくなります。

ここで押さえる制約が1つあります。Fluentは静的に解析されて、ServiceNowにインストールできる成果物に変換される言語です。ローカルでは実行されず、if/elseやforのような動的な機能は、Fluentのファイルではコンパイルできません。Claude Codeが通常のTypeScriptの癖で条件分岐を書くとbuildで落ちるので、そのメッセージを読ませて直させます。

3. buildで検証する

npm run build

buildはすべての.now.tsを検証し、参照・型・構造を調べて、デプロイ用の出力をローカルに書きます。この段階ではインスタンスに何も触りません。ビルドエラーを直してから次へ進む、というのが公式の順序です。

4. インスタンスへinstallする

npm run deploy

ガイドは、直近のビルド成果物を認証済みのインスタンスに入れるコマンドとして、このnpm run deployを載せています。installはビルドをしてくれないので、buildが失敗しているなら、先に直す必要があります。日々の作業は、.now.tsの編集、build、install、インスタンスでの確認の繰り返しです。

Claude Codeに完了条件を持たせる

ここからは、公式の手順の外側にある運用の話です。方針は2つで、build通過を完了の基準にすることと、インスタンスに書き込む操作は人の確認を挟むことです。

CLAUDE.mdの断片

次の断片は、ドキュメントに書かれた制約を、Claude Codeへの指示に置き直した例です。

## ServiceNow Fluentアプリ
 
- Fluentは `src/fluent/**/*.now.ts`。実行はされず静的に解析される。`if/else` と `for` は書かない
- 変更したら `npm run build` を実行し、エラーが0になるまで直す。通るまで作業を完了としない
- `src/fluent/generated/keys.ts` はビルドが生成する。手で編集しない。変更されたらコミット対象に含める
- `Table()` `BusinessRule()` `Record()` の定義を削除する前に、必ず確認する
- 未知のAPIは推測せず、`now-sdk explain <名前>` で確認してから書く
- `npm run deploy` と `now-sdk install` は実行しない。実行は人が行う

keys.tsを手で触らない理由は、ドキュメントにあります。keys.tsはキー名とsys_idの対応表で、sys_idは初回ビルドで生成され、以後は固定されます。キー名を変えると新しいレコードが作られ、古いレコードは取り残されます。Claude Codeに「名前を整理して」と頼むと、この罠を踏みかねません。

permissionsでinstallだけ確認を挟む

CLAUDE.mdの指示は、守られなくても止まりません。インスタンスへの書き込みは、.claude/settings.jsonのpermissionsでも押さえておきます。

{
  "permissions": {
    "allow": [
      "Bash(npm run build)",
      "Bash(npx @servicenow/sdk build *)",
      "Bash(now-sdk explain *)"
    ],
    "ask": [
      "Bash(npm run deploy)",
      "Bash(npx @servicenow/sdk install *)",
      "Bash(now-sdk install *)"
    ]
  }
}

Bashルールは、Claude Codeが書いたコマンドの文字列に対して照合されます。同じプログラムを別の形で呼ぶと、ルールをすり抜けます。npm run deployが内部で何を実行するかは、package.jsonのscriptsで決まります。askはあくまで入口の確認で、安全境界ではないと捉えてください。ルールの書き方と照合の仕組みはClaude Codeの/permissionsコマンドにまとめています。

さらに強く縛りたいなら、フックでinstall系のコマンドを検査する手があります。Claude Code Hooks完全ガイドに、イベントの一覧と書き方があります。

既存アプリとインスタンスの変更を取り込む

インスタンス側で誰かがStudioからレコードを変えると、Fluentのコードと実体がずれます。transformは、このずれを戻すコマンドです。

やりたいことコマンド
インスタンスの変更をFluentに反映コマンドnow-sdk transform
特定のテーブル・レコードだけ反映コマンドnpx @servicenow/sdk transform --table sys_script --id <sys_id>
metadata/のXMLをFluentへ変換コマンドnpx @servicenow/sdk transform --from ./metadata

--fromなしのtransformは、ローカルの変更を上書きします。Claude Codeに実行させる前に、コミットかスタッシュで退避しておく必要があります。XMLのままでもビルドとデプロイはできますが、型チェックや補完、差分の見やすさは失われます。

運用の考え方として、ドキュメントはGitを正とする立場を取っています。開発用インスタンスは使い捨てにでき、Gitから再現できるものとして扱います。マージはプルリクエストを通し、ビルドと次の環境への反映はパイプラインに任せます。

つまずきやすい点

ドキュメント間の表記ゆれ

ドキュメントの中に、そのまま読むと迷う箇所があります。

箇所内容
installの呼び方内容入門ページの手順はnpm run deploy、CLIリファレンスの見出しはinstall
keysの凍結フラグ内容CLIリファレンスの表は--frozen-keys、CI連携ページの本文は--frozenKeys

前者は、npm run deployの実体がpackage.jsonのscriptsにあるためです。何が走るかは、自分のプロジェクトのpackage.jsonで確かめてください。後者は、どちらの綴りが通るか表からは断定できません。now-sdk build --helpの出力に合わせるのが確実です。Claude Codeに綴りを書かせるときも、まず--helpを読ませます。

キーファイルを含めないCIビルド

keys.tsがコミットされていないと、CIのビルドが毎回sys_idを新しく作ります。インストールでは更新が挿入に変わり、対象のインスタンスにレコードが重複します。CI連携ページは、パイプラインのinstallの前にbuildの凍結フラグを入れて、keys.tsが変わったらビルドを失敗させるよう勧めています。開発者のほうは、手元でbuildしてからkeys.tsをコミットします。

CIからの本番デプロイ

CIでinstallを使う認証には、環境変数を使います。SN_SDK_NODE_ENV=SN_SDK_CI_INSTALLが必須で、OAuthならSN_SDK_AUTH_TYPE=oauth・SN_SDK_INSTANCE_URL・SN_SDK_OAUTH_CLIENT_ID・クライアントシークレットを渡します。Basic認証はSN_SDK_USERとSN_SDK_USER_PWDです。

注意点が2つあります。インストールに使うユーザーはadminロールに足りる権限が必要で、sys_userのIdentity TypeがHumanでなければなりません。そして、本番インスタンスにCIからinstallしない、というのが公式の方針です。本番への反映は、アプリリポジトリや案内付きのアプリインストールなど、ServiceNowの標準の昇格の仕組みを使います。

reinstallで消えるもの

install --reinstallは、アプリをアンインストールして入れ直します。インスタンス上で作られたメタデータで、ローカルに無いものは失われます。Claude Codeが「同期がずれたので--reinstallで揃えましょう」と提案しても、そのまま許可せず、先にtransformで取り込める変更がないか確認してください。

接続系の記事との違い

ClaudeからServiceNowのチケットやワークフローを呼ぶ接続は、アプリ開発とは別の話です。コネクタ経由の接続はClaude ServiceNow連携の使い方、Claude CodeやCoworkで情シスの問い合わせ対応を自動化する話はServiceNowをClaude CodeやCoworkで使う手順にあります。本記事のSDKは、アプリの定義をコードとして書き、インスタンスへ入れる側です。

まとめ

Fluent SDKをClaude Codeで使うときの要点は、buildを完了条件にして、installを人の確認に回すことです。keys.tsとtransformの扱いは、CLAUDE.mdに明文化しておくと事故が減ります。導入は、プラグインか同梱スキルを入れ、now-sdk explainで未知のAPIを確かめさせる構成から始められます。

この記事を共有:XはてブLinkedIn