プロジェクトの.ai-jail
ai-jailはこれを信頼できないものとして扱います。ジェイルを厳しくはできても、開けることはできません。allow_hostsやforward_portsのリストを縮めることはできても、足すことはできません。ai-jailがシンボリックリンク越しにこのファイルを読むことはなく、エージェントにはその場所に空のファイルが見えます。
設定は、プロジェクト内のファイル、ホームディレクトリのファイル、あなたが打つフラグから来ます。権限の弱いものから順に並べています。
↔ 横にスワイプすると図全体を見られます
.ai-jailai-jailはこれを信頼できないものとして扱います。ジェイルを厳しくはできても、開けることはできません。allow_hostsやforward_portsのリストを縮めることはできても、足すことはできません。ai-jailがシンボリックリンク越しにこのファイルを読むことはなく、エージェントにはその場所に空のファイルが見えます。
~/.ai-jailあなたのものなので、ai-jailは信頼します。すべての実行に適用される基本テーブルと、コマンドの最初の単語で選ばれる[commands.<name>]テーブルを持てます。
フラグの権限が最も強くなります。ほとんどのスイッチは--networkと--no-networkのように対になっているので、ファイルが開けたものをフラグで閉じることもできます。
コマンドテーブルでは、単一の値は基本テーブルの値を置き換え、マップやマスクなどのリストは基本テーブルに追加されます。
# 基本:すべてのコマンドに適用hide_dotdirs = [".my_secrets"]mask = [".env", ".env.*"] # コマンドが"claude"で始まるときだけ[commands.claude]network = trueenv_pass = ["ANTHROPIC_BASE_URL"]mask = ["*.pem"]どの行も、指定するまでは無効です。例外はシアンの2行で、こちらはデフォルトで有効です。機能を開けるフラグにはそれぞれ、閉じ直すための--no-付きの対があります。赤いバッジは、ジェイルを弱めるスイッチの印です。全一覧と理由はセキュリティのページにあります。
| フラグ | 設定キー | 動作 | リスク |
|---|---|---|---|
--network | network = true | ネットワーク全体。エージェントが読めるものは何でも外に送れます。必要なホストが少数なら、--allow-hostのほうが厳密です。どちらのフラグもなければ、サンドボックスが届くのは既知のエージェント自身のAPIホストと、Linuxではツールチェーンがプロキシ経由で開けるパッケージレジストリだけです。--no-networkはその両方を閉じます。 | ジェイルを弱める |
--allow-host <HOST> | allow_hosts = [...] | サンドボックスは、指定したホストとそのサブドメインにだけ、ai-jail組み込みのプロキシ経由のTCPで届きます。フラグは繰り返せます。2.8.1からはリストがデフォルトに足されるので、既知のエージェントは自身のAPIホストを保ちます。--networkや--browserとは併用できず、プロジェクトファイルはリストを縮めることしかできません。 | 1つだけ開ける |
--forward-port <PORT> | forward_ports = [...] | ホストのループバックのポート1つを、サンドボックス自身のループバックに中継します。ホストの127.0.0.1にあるローカルのMCPサーバー、エディタのソケット、開発用データベースが中でも同じポートで応答し、ホストのほかのポートはすべて閉じたままです。ポートを増やすにはフラグを繰り返します。Linuxのみで、--networkとの併用と1024未満のポートは拒否されます。--allow-hostと併用でき、--lockdown下でも動きます。ポートの先のサービスは丸ごと信頼され、許可リストも監査の記録もありません。プロジェクトファイルはリストを縮めることしかできません。設定ファイルでforward_portsを書く場所。 | ジェイルを弱める |
--ssh | ssh = true | 読み取り専用の~/.sshとSSHエージェントのソケット。git pushが動くようになります。 | 1つだけ開ける |
--docker | no_docker = false | Dockerソケット。デーモンはホストをマウントしたコンテナを起動できるので、事実上そのマシンのroot権限です。 | ジェイルを弱める |
--tailscale | tailscale = true | Tailscaleのソケット。 | 1つだけ開ける |
--systemd-user | systemd_user = true | systemdのユーザーバス。エージェントはユーザーマネージャーに、ホスト上でサービスを動かすよう依頼できます。Linuxのみ。 | ジェイルを弱める |
| フラグ | 設定キー | 動作 | リスク |
|---|---|---|---|
--agent-state | agent_state = true | エージェント自身のログイン情報。~/.claudeや~/.codex、Devinの~/.local/share/devinと~/.config/devinなど、起動したハーネスの状態を読み書き可能でマウントし、シェルに設定されていればそのAPIキーもコピーします:ANTHROPIC_API_KEY、OPENAI_API_KEY、GEMINI_API_KEYまたはGOOGLE_API_KEY、XAI_API_KEY、MOONSHOT_API_KEY。エージェントはログイン済みで起動し、ジェイルの中のものは何でもそのログインを使えます。--no-agent-stateを付けるとログアウト状態での実行になります。ロックダウンでは無効で、プロジェクトファイルは無効にすることしかできません。 | デフォルトで有効 |
--claude-dir <PATH> | claude_dir = "..." | 指定したディレクトリをClaudeの状態保存先として使い、CLAUDE_CONFIG_DIRを設定します。 | 1つだけ開ける |
--env <NAME[=VALUE]> | なし | シェルの変数を1つ渡すか、NAME=VALUEで1つ設定します。繰り返し指定でき、ディスクには保存されません。Linuxでは値はメモリ上のファイルを通してサンドボックスに渡り、ランチャーのコマンドラインには現れませんが、NAME=VALUEをそのまま書けばai-jail自身のコマンドラインには見えるので、シークレットには--env NAMEか--env-from-fileを使ってください。 | 1つだけ開ける |
--env-from-file <PATH> | env_from_file = [...] | ファイルから厳密なKEY=VALUE形式の行を読み、--envと同じように渡します。重なった場合はそちらが優先です。ファイルはあなたが所有する通常ファイルで、モードは0600かそれより厳しく、プロジェクトの外にある必要があります。満たさなければ起動は失敗します。ai-jailが値をディスクに保存することはなく、設定キーはグローバルファイルでのみ有効です。 | 1つだけ開ける |
--secret <KEY=host> | secret_hosts = { ... } | KEYの本物の値をサンドボックスの外に置きます。エージェントにはプレースホルダーが見え、プロキシは本物の値をそのホスト宛てのリクエストだけに入れます。--allow-hostが必要で、キーは--envか--env-from-fileで先に渡しておく必要があります。グローバルファイルのみで、保存はされません。対象は、そのホストに向けてプロキシへ平文のHTTPを送れるクライアントで、HTTPSトンネルには触れません。 | 1つだけ開ける |
--inherit-env | inherit_env = true | シェルの環境全体を、中にある秘密情報ごと渡します。使わないでください。 | ジェイルを弱める |
| なし | env_pass = ["NAME"] | --envと同じですが、グローバルファイルでのみ有効です。プロジェクトファイルで設定しても無視されます。 | 1つだけ開ける |
| フラグ | 設定キー | 動作 | リスク |
|---|---|---|---|
--toolchains | no_toolchains = false | コンパイラとパッケージマネージャーは読み取り専用、その依存キャッシュはジェイル専用のストアに、パッケージレジストリにはフィルタ付きプロキシ経由で届きます。Linux限定で、そこではデフォルトで有効です。macOSでは何もマップされず、レジストリにも届きません。ロックダウンはこれを無効にし、プロジェクトファイルも無効にすることしかできません。詳細は下に。 | デフォルトで有効 |
--github | github = true | ghの設定ディレクトリを読み取り専用で、さらに有効なgithub.comのトークンをその起動の間だけGH_TOKENとして転送するので、トークンがシステムのキーリングにあってもghはログイン済みです。ai-jailはホスト側でgh auth tokenを実行し、結果をメモリ上のファイルで渡します。コマンドラインにもディスクにも載りません。--dry-runは取得せず、--envでGH_TOKENを渡せば取得を省きます。github.comのみ、有効なアカウントのみです。それでも、ジェイル内のものはGitHubであなたとして振る舞えます。 | 1つだけ開ける |
--aws | aws = true | 読み取り専用の~/.aws。認証情報が有効な間、ジェイルの中のものは何でも、あなたとしてAWSを操作できます。 | 1つだけ開ける |
--kube | kube = true | 読み取り専用の~/.kube。ジェイルの中のものは何でも、あなたとしてクラスタと通信できます。 | 1つだけ開ける |
--gcloud | gcloud = true | 読み取り専用の~/.config/gcloud。ジェイルの中のものは何でも、あなたとしてGoogle Cloudを操作できます。 | 1つだけ開ける |
--docker-config | docker_config = true | 読み取り専用の~/.docker/config.json。レジストリのログイン情報が入っています。ジェイルの中のものは何でもそれを使えます。 | 1つだけ開ける |
| フラグ | 設定キー | 動作 | リスク |
|---|---|---|---|
--gpu | no_gpu = false | GPUデバイス。同時に、ドライバの攻撃対象領域も開きます。Linuxのみ。 | 1つだけ開ける |
--kvm | kvm = true | /dev/kvm。QEMUやAndroidエミュレータなど、ハードウェア支援の仮想マシン用です。ホストカーネルのKVMインターフェースを晒します。ゲストが使えるのはサンドボックスのネットワークだけで、tunやvhostのデバイスは渡しません。Linuxのみ。 | 1つだけ開ける |
--display | no_display = false | Waylandのソケット。セッションのそれ以外のものは渡しません。Linuxのみ。 | 1つだけ開ける |
--x11 | x11 = true | X11のソケット。X11では、プログラムがキー入力を記録したりスクリーンショットを撮ったりできます。 | ジェイルを弱める |
--audio | audio = true | PipeWireとPulseAudioのソケットと/dev/snd。ジェイルの中のものは何でも録音と再生ができます。Linuxのみ。 | 1つだけ開ける |
--host-shm | host_shm = true | ホストの/dev/shm。ジェイルの外のプロセスとの共有メモリが開きます。 | 1つだけ開ける |
--pictures | pictures = true | 読み取り専用の~/Pictures。 | 1つだけ開ける |
--browser[=hard|soft] | browser_profile = "hard" | 独立したブラウザプロファイル。hard(デフォルト)は実行をまたいで何も残さず、softは~/.local/share/ai-jail/browsersの下にプロファイルを残します。 | 1つだけ開ける |
| フラグ | 設定キー | 動作 | リスク |
|---|---|---|---|
--map <PATH|SOURCE:DEST> | ro_maps = [...] | パスを1つ、読み取り専用で追加マウントします。別の場所にマウントするにはSOURCE:DESTと書きます。繰り返し指定できます。 | 1つだけ開ける |
--rw-map <PATH|SOURCE:DEST> | rw_maps = [...] | パスを1つ、読み書き可能で追加マウントします。繰り返し指定できます。 | 1つだけ開ける |
--overlay-map <PATH> | overlay_maps = [...] | パスをコピーオンライトでマウントします。エージェントの書き込みは別のレイヤーに入り、元のファイルは変わりません。Linuxのみ。macOSでは読み取り専用のマウントになります。 | 1つだけ開ける |
--hide-dotdir <NAME> | hide_dotdirs = [...] | 指定したドットディレクトリ(例:.my_secrets)を決してマウントしません。繰り返し指定できます。 |
| フラグ | 設定キー | 動作 | リスク |
|---|---|---|---|
--no-landlock | no_landlock = true | カーネル側でファイルのルールを二重に適用するLandlockを無効にします。--lockdownでは拒否されます。 | ジェイルを弱める |
--no-seccomp | no_seccomp = true | 危険なシステムコールを止めるフィルターを無効にします。 | ジェイルを弱める |
--no-rlimits | no_rlimits = true | 暴走したプロセスを抑える制限を無効にします。 | ジェイルを弱める |
--no-private-home | private_home = false | 新しいホームディレクトリを使うのをやめます。本物のホームへの広いアクセスを与えることになります。必要なパス1つだけを--mapで渡すほうが安全です。 | ジェイルを弱める |
各層の役割は仕組みのページで説明しています。
| フラグ | 設定キー | 動作 | リスク |
|---|---|---|---|
--audit-log | audit_log = true | 起動のたびに1件のレコードを~/.local/share/ai-jail/history.jsonl(ディレクトリは0700、ファイルは0600)に追記します。内容は時刻、コマンド、実際に有効だった機能、設定の出どころ、終了コード、所要時間です。--allow-hostを使っていれば許可または拒否された接続もすべて記録され、--secretを使っていれば注入もすべて記録されます。各行は1つ前の行のハッシュを持ちます。デフォルトでは無効で、プロジェクトファイルは無効にできても有効にはできません。 | 1つだけ開ける |
--audit-show | なし | ログを読みやすくまとめて表示し、終了します。内容は起動、フィルタ付きネットワークの判断、秘密情報の置き換えです。チェーンの検証はしません。終了コードは、表示できれば0、レコードが不正か読み取りエラーなら1、ログがなければ2です。起動の記録にはコマンドの引数が含まれることがあるので、引数に秘密情報を入れないでください。 | |
--audit-verify | なし | 監査ログのハッシュチェーンをたどって終了します。終了コードは、チェーンが無傷なら0、最初に壊れた箇所が見つかれば1、ログがなければ2です。2.2より前に書かれたレコードはlegacyとして報告されますが、エラーではありません。 |
| フラグ | 動作 |
|---|---|
--dry-run | サンドボックスコマンドを表示するだけで、何も実行しません。設定ファイルを書くこともありません。 |
--init | プロジェクトの.ai-jailを作成または更新して終了します。 |
--clean | 今回の実行では、プロジェクトの.ai-jailを無視します。 |
--bootstrap | AIツール自体の権限設定ファイルを生成します。 |
status | 現在の.ai-jailの設定を表示します。 |
-v, --verbose | ジェイルの構築中に、すべてのマウントを表示します。 |
残りのオプションはai-jail --helpで確認できます。ステータスバー、worktree、mise、ターミナル関連です。ツールチェーンのキーも古いものと同じく反転していて、no_toolchains = trueで無効になります。
.envファイルはプロジェクトの中にあり、プロジェクトは読み書き可能です。ネットワークが有効なら、エージェントはそこで読めるものを何でも外へ送れます。マスクすれば、そうしたファイルを取り除けます。
↔ 横にスワイプすると図全体を見られます
--mask <PATH|GLOB>一致したものをすべて空のプレースホルダーに置き換えます。エージェントにはファイルがあることは見えますが、中身は得られません。存在を確認するだけのツールはそのまま動きます。マスクが変えるのはサンドボックスから見えるものだけです。DockerデーモンやMCPサーバーなど、ホスト側でエージェントの代わりに動くものは本物のファイルを読みます。
--deny-path <PATH|GLOB>一致したものすべてを、アクセスすると権限エラーになるようにします。
--mask-exceptと--deny-path-exceptルールからパスを1つ除外します。保護を弱めるので、プロジェクトファイルでは設定できません。
# globは引用符で囲む。シェルに展開させず、パターンのままai-jailに渡すためai-jail --mask .env --mask '.env.*' --mask '*.pem' --deny-path secrets/ claude ai-jail --mask '.env.*' --mask-except .env.example claude# プロジェクトファイルは厳しくする方向なら設定できるので、リポジトリ内でも使えるmask = [".env", ".env.*", "*.pem"]deny_paths = ["secrets/"]マスクの対象はプロジェクト内のファイルです。エージェント自身のキーは、--env NAMEでシェルから渡すか、--env-from-fileで自分しか読めないファイルから渡してください。どちらも.ai-jailファイルに書かれることはなく、プロジェクトファイルからは設定できません。フィルタ付き外向き通信が有効なら、--secret KEY=hostで本物の値をサンドボックスの外に置くこともできます。下のレシピで示します。
# ファイルは自分の所有で、モード0600、プロジェクトの外に置くchmod 600 ~/.secrets/claude.envai-jail --env-from-file ~/.secrets/claude.env claude# グローバルファイルのみ。プロジェクトファイルで設定しても無視される[commands.claude]env_from_file = ["~/.secrets/claude.env"]ビルドにはコンパイラ、パッケージマネージャー、そのキャッシュが要ります。Linuxでは、ai-jailがデフォルトでそれらを持ち込みます。ツールは読み取り専用、キャッシュはジェイル専用のストア、パッケージレジストリにはフィルタ付きプロキシ経由で届きます。
↔ 横にスワイプすると図全体を見られます
2.4.1から、ai-jailはmiseでインストールしたものと設定を読み取り専用でマップします。Rustでは~/.cargo/binと~/.rustupも同じ方法でマップするので、cargoとrustcが解決できます。Cargoの認証情報とconfig.tomlは入れません。miseは読み取り専用のマップには何もインストールできないので、ai-jailは中でMISE_NOT_FOUND_AUTO_INSTALL=falseを設定し、足りないツールは一度だけ失敗し、呼び出しのたびに失敗することはありません。
依存キャッシュは~/.local/share/ai-jail/cache/の下に置かれ、セッションをまたいで残ります。Cargoのレジストリとgitのキャッシュもここです。pip、uv、Go、npm、yarn、pnpm、bun、deno、Maven、Gradle、Coursier、Composer、Crystal、Zigのデフォルトのキャッシュも、そのツールのディレクトリがマシンにあれば同じです。
ツールチェーンが有効でネットワークのフラグがなければ、サンドボックスはcrates.io、npm、PyPI、Goプロキシ、Maven Central、Clojars、Packagist、github.comとそれぞれのサブドメインに、--allow-hostと同じプロキシ経由で届きます。既知のエージェント自身のAPIホストも同じ経路で通り、macOSでも同様です。レジストリはLinux限定です。
# Linuxのデフォルトai-jail claude # キャッシュは有効、ネットワークは一切なしai-jail --no-network claude # 何もマップせず、どこにも届かないai-jail --no-toolchains --no-network claudeデフォルトは作業がはかどるように調整されています。以下のステップは1つずつ何かを閉じていき、--lockdownはその大半を一度に閉じます。それぞれが何を防ぐかはセキュリティのページにあります。
--no-network:完全にオフライン。--allow-hostのリストを併用すると、サンドボックスは指定したホストだけに到達し、自動のデフォルトは付きません。--no-agent-state:ログインなし。ハーネスの状態は外に残り、APIキーもコピーされません。--no-toolchains:依存キャッシュもパッケージレジストリもなし。--mask、--deny-path、--hide-dotdirは個別のパスを取り除き、狭い--mapや--rw-mapは広い許可の代わりになります。これらが変えるのはサンドボックスから見えるものだけで、Dockerデーモンや--forward-portの先のサービスなど、ホスト側のヘルパーは本物のファイルを読みます。--lockdown:プロジェクトは読み取り専用、ログインもツールチェーンもレジストリもなし、Landlockとseccompは厳格。それでもVMではありません。--lockdownはレビューや監査のためのモードです。エージェントはプロジェクトを読んで質問に答えられますが、ファイルは1つも変更できません。
↔ 横にスワイプすると図全体を見られます
/tmpだけ。macOSではどこにも書き込めないPATHはシステムディレクトリに固定されるai-jail --lockdown claudeコピーして使ってください。何が組み立てられるかを確かめるには、先に--dry-runを付けて実行します。
既知のエージェントはログイン済みで始まり、フィルタ付きプロキシ経由で自身のAPIホストに届きます。Linuxではパッケージレジストリにも届きます。タスクにもっと必要なら、グローバルファイルのallow_hostsに追加のホストを書くか、network = trueでネットワーク全体を開けます。
# 足すものなし:ログイン情報とapi.anthropic.comはデフォルトで付くai-jail claude # タスクにもっと必要なときは、~/.ai-jailに一度だけ(APIホストと、Linuxではレジストリに足される)[commands.claude]allow_hosts = ["api.example.com"]# または、ネットワーク全体を開ける:network = trueai-jailが自らAPIホストを許可するのは5つのエージェントです。それ以外のエージェントのホストは--allow-hostであなたが指定します。リストにホストがなければ、起動時の警告がその名前を示します。
ai-jail --allow-host api.example.com myagent# 既知のエージェントにフラグは不要:ai-jailが自らAPIホストを許可するエージェントに認証情報を一切持たせたくないときは、--no-agent-stateで状態ディレクトリもAPIキーも外に置きます。エージェントはログアウト状態で起動し、新しいホームの中でログインしたものも、実行が終わると消えます。
ai-jail --no-agent-state claudeこのリストはそのコマンドの毎回の実行に、エージェント自身のAPIホストに加えて適用されます。Linuxではgithub.comとパッケージレジストリに最初から届くので、書くのはmacOSのときだけです。許可したホストは丸ごと信頼されます。そこであなたの認証情報が許すことなら、エージェントは何でも頼めます。
[commands.claude]allow_hosts = ["api.example.com"]--networkなしではサンドボックスに専用のループバックがあるので、ホストの127.0.0.1で動くサーバーには届きません。--forward-portはそのポート1つだけを中継します。Linuxのみです。グローバルファイルではforward_portsをコマンドのテーブルの下に書き、ベーステーブルには書かないでください。このフラグは--network(--browserは通常これを含みます)との併用時とmacOSでは拒否されるので、ベースに書くとそれらの起動が失敗します。
ai-jail --forward-port 49374 claude # または~/.ai-jailに一度だけ、コマンドのテーブルの下に書く[commands.claude]forward_ports = [49374]サンドボックスのANTHROPIC_API_KEYにはプレースホルダーが入り、ai-jailのプロキシが本物のキーをapi.anthropic.com宛てのリクエストだけに入れます。クライアントはそのホストに向けてプロキシへ平文のHTTPを送る必要があり、http://のベースURLならそうなります。その後、ai-jailがリクエストをTLSで本物のホストへ運びます。HTTPSトンネルしか開かないクライアントは、置き換えなしでそのまま動きます。
# キーは0600のファイルにある。サンドボックスに見えるのはAIJAIL-PHANTOM-...だけai-jail --allow-host api.anthropic.com \ --env-from-file ~/.secrets/claude.env \ --secret ANTHROPIC_API_KEY=api.anthropic.com \ --env ANTHROPIC_BASE_URL=http://api.anthropic.com claude--sshは~/.sshを読み取り専用でマウントし、SSHエージェントのソケットを転送します。ネットワークは開けないので、レシピでは--networkと組み合わせています。ghのトークンでHTTPS経由でpushするなら、GitHub CLIのレシピを見てください。
ai-jail --network --ssh claudeLinuxでは何も足す必要がありません。cargo build、npm install、go getはプロキシ経由でレジストリから取得してジェイル専用のストアにキャッシュし、miseでインストールしたものも読み取り専用で付いてきます。何にも触れず、どこにも届かない実行にしたいなら、両方を無効にします。
# Linuxのデフォルト:キャッシュ有効、レジストリにはプロキシ経由で届くai-jail claude # 何もマップせず、どこにも届かないai-jail --no-toolchains --no-network claude--githubはghの設定ディレクトリを読み取り専用でマウントし、有効なgithub.comのトークンをGH_TOKENとして転送するので、キーリングの有無にかかわらずghとHTTPS経由のgit pushはログイン済みです。Linuxではgithub.comとそのサブドメインがデフォルトのリストに入っているので、ホストは足しません。macOSでは--allow-host github.comを足します。その後は、ジェイル内のものはGitHubであなたとして振る舞えます。
ai-jail --github claude # macOS:github.comはそこではデフォルトのリストに入っていないai-jail --github --allow-host github.com claude--browserだけでは、ページの読み込みもウィンドウの表示もできないブラウザになります。Linuxでは--networkと--displayも必要です。X11のブラウザなら、--displayの代わりに--x11を使います。
# Waylandai-jail --browser=soft --network --display chromium# X11ai-jail --browser=soft --network --x11 chromium実行ごとに別のClaudeディレクトリを指定すれば、仕事用と個人用のログインを分けておけます。
ai-jail --network --claude-dir ~/.claude-work claudeオーバーレイを使うと、エージェントの書き込みはプロジェクト内の.ai-jail-overlaysの下にある別レイヤーに入ります。後で元のファイルと比べて、気に入った変更だけを取り込めます。Linuxのみ。
ai-jail --network --overlay-map ~/Projects/my-app/src claude後方互換性はプロジェクトのルールで、フラグや設定キーが削除されることはありません。未知のキーは無視され、足りないキーにはデフォルト値が入るので、古いバージョン向けに書いたファイルもそのまま読み込めます。
古いスイッチは、trueで機能が無効になる反転した名前のままです。no_gpu、no_docker、no_display、no_mise、no_toolchains、no_landlock、no_seccomp、no_rlimitsが該当します。--gpuがno_gpu = falseとして保存されるのはそのためです。新しいスイッチはnetwork = trueのような素直な名前を使います。--allow-tcp-portは今も解析されますが、UDPに柵をかけられないため、起動は引き続き拒否されます。そのエラーは--allow-hostを案内します。
ai-jailは単一のバイナリで、デーモンもroot権限も要りません。いつものコマンドの前に1語足すだけです。
brew tap akitaonrails/tap && brew install ai-jailai-jail claude