Claude Codeでcli-kintoneを動かす権限設計 — exportは許可しimportは確認する
cli-kintoneのrecord export・import・deleteをClaude Codeに任せるときの権限設計です。コマンド単位のallow・ask・denyと、本番トークンを渡さない分け方を示します。
cli-kintoneのrecord exportは読み取りだけなのでallowに置け、record importは上書きもあり得るのでask、record deleteはdenyに置けます。ただしコマンドの文字列で止めるルールには抜け道があり、これだけでは本番アプリを守り切れません。本番の認証情報をClaude Codeのセッションに渡さないことが、本当の境界になります。
cli-kintoneの3コマンドは何をするか
cli-kintoneは、kintoneのレコードをCSVで入出力するコマンドラインツールです。GitHubのリポジトリはCybozuの公開で、ドキュメントは専用サイトにあります。権限設計で見るのは、レコードを扱う次の3コマンドです。
| コマンド | 動作 | 取り返しがつくか |
|---|---|---|
record export | 動作アプリのレコードを標準出力へ書き出す | 取り返しがつくか読むだけ。ただし本番データがローカルに出る |
record import | 動作CSVのレコードを追加する | 取り返しがつくか--update-keyを付けると既存レコードを更新する |
record delete | 動作レコードを削除する | 取り返しがつくか公式に「ロールバックできない」と明記 |
record exportは--appでアプリIDを指定し、出力はシェルのリダイレクトでファイルに落とします。--conditionで絞り込み、--fieldsで項目を選べます。添付ファイルは--attachments-dirを付けたときだけダウンロードされます。
record importは--file-pathにCSVを取り、添付ファイル項目を含むなら--attachments-dirが必須です。--update-keyを指定すると、キーが一致するレコードは更新され、残りは新規追加されます。つまりimportは「追加だけ」とは限りません。
record deleteは--file-pathを省くと、対象アプリの全レコードを削除します。確認プロンプトは--yes(-y)で飛ばせます。このコマンドはAPIトークン認証にしか対応していません。
認証情報の渡し方がそのまま権限設計になる
認証まわりのオプションは、環境変数を既定値に取ります。
| オプション | 既定値になる環境変数 |
|---|---|
--base-url | 既定値になる環境変数KINTONE_BASE_URL |
--api-token | 既定値になる環境変数KINTONE_API_TOKEN |
--username / --password | 既定値になる環境変数KINTONE_USERNAME / KINTONE_PASSWORD |
--guest-space-id | 既定値になる環境変数KINTONE_GUEST_SPACE_ID |
--api-tokenの説明は「アプリのAPIトークン」です。アプリごとに発行するトークンなので、本番アプリ用とステージング用は別のトークンになります。発行済みのトークンにどの操作を許しているかは、kintoneのアプリ設定の画面で確かめてください。
ここから設計の順序が決まります。
- ステージング用のトークンだけを、Claude Codeを起動するシェルの環境変数に置く
- 本番用のトークンは、そのシェルにもリポジトリにも置かない
- 本番へのimportは、人が別のターミナルで実行する
トークンを環境変数に置くと、Claudeはecho $KINTONE_API_TOKENを実行できます。echoは組み込みの読み取り専用コマンドで、確認なしに走るからです。だからこそ、セッションに入れるのは壊れても困らないステージング用に限ります。
settings.jsonに書くルール
コマンドの粒度でallow・ask・denyを分けると、次のようになります。
{
"permissions": {
"allow": [
"Bash(cli-kintone record export *)"
],
"ask": [
"Bash(cli-kintone record import *)"
],
"deny": [
"Bash(cli-kintone record delete *)",
"Read(./.env*)",
"Read(./secrets/**)"
]
}
}ルールの*は、サブコマンドの後ろに置きます。ワイルドカードより前の文字列が書いたとおりに照合されるので、record exportまでを固定すれば、他のサブコマンドには広がりません。
次の2点は、書いた意図どおりに動くことが公式の説明で確かめられます。
- deleteは
--yesの有無に関わらず止まる: denyはcli-kintone record deleteで始まる全コマンドに当たるので、--yesを付けた形も対象です。 - 先頭の環境変数代入を挟んでも止まる: denyとaskは、先頭に
KINTONE_BASE_URL=...のような代入が付いていても一致します。逆にallowは、既知の安全な変数以外の代入が付くと一致しません。KINTONE_API_TOKEN=xxx cli-kintone record export ...のような書き方は、exportであっても確認に回ります。
本番アプリを指す呼び出しだけ止めたいとき
「アプリID 12への呼び出しだけは確認を挟む」といったルールも書けます。たとえばBash(cli-kintone record import * --app 12 *)をaskに足す形です。ただし引数で絞るルールは壊れやすいと公式が警告しています。オプションの順序が入れ替わる、変数経由で値を渡す、といった形に一致しないためです。
本番を指す呼び出しの判定は、引数ではなく認証情報の側に持たせるほうが堅実です。ステージング用のトークンしか持たないセッションなら、アプリIDを書き換えても本番は読めません。
文字列ルールが止められない呼び出し
Bashのルールは、Claudeが書いたコマンド文字列に対して働きます。同じプログラムを別の形で呼ぶと、denyに当たりません。公式の表にある例を、cli-kintoneに置き換えて考えます。
| ルール | 止まる形 | 止まらない形 |
|---|---|---|
Bash(cli-kintone record delete *) | 止まる形cli-kintone record delete --app 12 | 止まらない形絶対パスで呼ぶ形、sh -c '...'で包んだ形 |
公式の表はcurl・rm・git pushで説明していますが、仕組みは同じです。さらに、環境ごとのコマンドランナー(npxやdocker execなど)は取り除かれるラッパーの一覧に入っていません。ランナー越しに呼ばれたときは、ルールが期待どおりに働かない前提で考えます。
穴を塞ぐ手段は、公式が2つ挙げています。
- サンドボックス: ファイルシステムとネットワークをOSの側で制限します。kintoneのドメインへの通信を、許可する宛先に絞る使い方ができます
- PreToolUseフック: コマンドの全文を自前のロジックで検査してから実行を許すか決めます
どちらも、設定を足す前に「本番トークンを渡していない」という前提が成り立っていれば、補強の位置づけで足ります。
exportで手元に出すデータを絞る
exportをallowにすると、本番のデータがどこまで手元に出るかは引数しだいになります。--fieldsで項目をカンマ区切りに指定し、--conditionでレコードを絞れば、必要な分だけを取れます。たとえば個人情報の項目を含まないCSVで足りる作業なら、CLAUDE.mdに「--fieldsで項目を明示する」と書いておけます。
ただし--fieldsは強制力のある制限ではありません。引数を省いたexportもallowに一致するため、あくまでClaudeへの指示です。強制したいなら、個人情報を含まない項目だけを閲覧できるステージング用アプリを用意します。
なお、テーブル内のフィールドは--fieldsで指定できません。文字コードは--encodingでutf8かsjisを選べます。Excelで開く前提のCSVはsjisが要る場面がありますが、Claudeに読み書きさせるCSVはutf8のままにしておくと扱いやすくなります。
複合コマンドと添付ファイル
cli-kintone record export ... && cli-kintone record import ...のようにつなぐと、各サブコマンドが別々に検査されます。exportがallowでも、importがaskなら全体が確認に回ります。denyは入れ子になったコマンドにも当たるので、forループの中にrecord deleteを隠しても止まります。
添付ファイルには別の注意があります。--attachments-dirを付けたexportは、添付をローカルにダウンロードします。ファイルは<attachmentsDir>/<フィールドコード>-<レコードID>/<ファイル名>に置かれます。本番データを手元に出したくない場合は、このオプション付きのexportだけaskに移す選択肢があります。
作業の分け方とCLAUDE.mdの記述
ルールを入れたあとの作業分担を、CLAUDE.mdに書いておくとClaudeが迷いません。次は断片の例です。
## kintone データ操作
- 取得は `cli-kintone record export` を使う。出力は exports/ に置く
- 取り込みは staging アプリ(アプリID 99)でだけ試す。`record import` は確認が出る
- `record delete` は使わない。削除が必要なときは人に依頼する
- CSV の1行目はフィールドコード。フィールド名(表示名)は使わないCSVの先頭行がフィールドコードであることは、cli-kintoneのCSV形式の説明にあります。カスタマイズ側の作業でも同じ注意が要ります。フィールドコードをCLAUDE.mdに固定する考え方は、Claude Codeでkintoneカスタマイズを書くで扱っています。
次の流れなら、Claudeに任せる範囲と人が実行する範囲がはっきり分かれます。
ステージングで試し、本番は人が取り込む
- 1
ステージングからexportする
Claudeが
record exportを実行します。確認なしで走り、CSVがexports/に出ます。 - 2
CSVを加工する
Claudeが取り込み用のCSVを作ります。ヘッダはフィールドコードに揃えます。
- 3
ステージングへimportする
askの確認が出るので、人がコマンドの引数を見て許可します。 - 4
本番へは人が別ターミナルで実行する
本番のトークンは、別のターミナルのシェルにだけ置きます。
設定が効いているか確かめる
ルールを書いたら、/permissionsで一覧に出ているか見ます。そのうえで、ステージング用トークンのセッションで次を試します。
cli-kintone record delete を --app 99 で実行してdenyに当たれば、コマンドは実行されずに拒否されます。確認が出る、またはそのまま走る場合は、ルールの書き方かコマンドの形が想定と違います。
落とし穴
allowを広く書くと、importの確認まで外れる
Bash(cli-kintone *)のようにサブコマンドの前で止めると、exportもimportもdeleteも一括でallowになります。denyは別に書けば効きますが、askにしたかったimportは確認なしで走ります。allowはrecord exportまでを固定してください。
どこまでを任せるかの目安
exportだけを任せるなら、ステージングでも本番でも事故の形は「データが手元に出る」ことに限られます。importを任せるなら、更新キーの有無で意味が変わるため確認を残します。deleteは戻せないので、Claudeのセッションから外します。
権限の書き方そのものの勘所は、PRのマージ前にだけ確認を残す形で書いたDVCの権限設計と同じ型です。コマンドの文字列で止めるルールと、認証情報を渡さない境界を分けて考えると、設定が小さく済みます。署名鍵のように読ませたくないファイルがあるなら、ppkをClaude Codeに読ませない設定も合わせて読めます。kintone側にClaudeをつなぐ方法は、Claude kintone連携ガイドにまとまっています。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。