IDE - TECH PLAY - TECH PLAY

TECH PLAY

IDE

イベント

該当するコンテンツが見つかりませんでした

マガジン

技術ブログ

Claude Code は認証トークン・設定・会話履歴を、すべて ~/.claude の下(と、すぐ隣の ~/.claude.json )に置きます。Dev Container で使うときは、再ビルドのたびの再ログインを避けるために、このディレクトリをホストから丸ごとマウントするのが定番です。 この構成を複数のプロジェクトで使っていて、気になり始めたことがあります。 全部のコンテナが、ホストにある同じ ~/.claude を書き換え合っている 、ということです。 手元の ~/.claude.json の中身を数えると、こうなっていました。 $ python3 -c "import json,os; d=json.load(open(os.path.expanduser('~/.claude.json'))); \ print('projects:', len(d['projects']), '/ githubRepoPaths:', len(d['githubRepoPaths']), '/ numStartups:', d['numStartups'])" projects: 36 / githubRepoPaths: 13 / numStartups: 1278 36プロジェクト分の状態が1ファイルに入っています。 projects/ 配下の会話履歴も同じで、 いま作業しているリポジトリとは関係のないプロジェクトの履歴が、どのコンテナからも見えます 。逆方向も起きます。自分がいるコンテナの外で走った Claude Code の書き込みが、知らないうちに手元のファイルに反映されます。 先に正直に書いておくと、 この構成で壊れた経験は一度もありません 。直したかった理由は単純で、 コンテナに閉じたはずの作業が、コンテナの外と混ざっているのが気持ち悪い からです。コンテナに入れた意味が薄れます。 本記事では、 ~/.claude の中身を 更新頻度で分類 して、コンテナをまたいで共有し続けるものと、プロジェクトごとに独立させるものの線を引きます。そのうえで後半では、その線引きを Dev Container(docker-compose 版と素の devcontainer.json 版)で実装します。ディレクトリの中身そのものについては、同じブログに Claude Codeが作成する~/.claudeディレクトリの詳細解析 があります。 .credentials.json や projects/ が何をしているファイルなのかはそちらが詳しいので、役割から知りたい場合は先に読むと早いです。 この記事でわかること : ~/.claude の中身を更新頻度で2つに分ける線引き(共有し続けるもの / コンテナごとに分けるもの) .claude.json が既定ではどこにあるのか。なぜそれが「全コンテナの共用ノート」になるのか 履歴と設定をプロジェクトごとに独立させつつ、再ログインは不要に保つ実装(compose ベースと素の devcontainer.json の両方) named volume の所有者問題( chown を 非再帰 にする理由) 「稀更新なら共有してよい」の例外( plugins/ を共有すると壊れる理由) 検証環境 : ホストは Linux / WSL2 です。リポジトリも WSL 上に置きます。macOS は認証情報の保存先が異なり本構成がそのままは成立しません(末尾の「制約・前提」で扱います)。 向き / 不向き : 対象は ホストの ~/.claude.json まで bind している人 です。すでに volume だけで運用しているなら、ここで扱う「混ざる」現象は起きていません。なお切り替えても ホスト側の履歴が消えることはありません 。ホストにはそのまま残り、以降の会話がコンテナ側にだけ増えていきます。見えなくなるだけですが、 --resume でホスト側の過去を頻繁に遡る使い方とは正面からぶつかります(一度きりの持ち込み手順は後述します)。 ~/.claude は全コンテナの共用ノートになっている .claude.json は ~/.claude の中に無い まず位置関係から押さえます。共有すると混ざるファイルの主役は .claude.json ですが、 これは既定では ~/.claude の中にありません 。 ~/.claude.json という、 ~/.claude と並ぶ別のパスに置かれます。 $ ls -la ~/.claude.json ~/.claude/.claude.json -rw-r--r-- 1 vscode vscode 104786 Jul 30 15:27 /home/vscode/.claude.json ls: cannot access '/home/vscode/.claude/.claude.json': No such file or directory だから、以前書いた Claude Code×DevContainer 環境構築ガイド の設定も、この2つを別々に bind していました。 "mounts": [ "source=${localEnv:HOME}/.claude,target=/home/vscode/.claude,type=bind,consistency=cached", "source=${localEnv:HOME}/.claude.json,target=/home/vscode/.claude.json,type=bind,consistency=cached" ] つまりプロジェクトの状態が全コンテナで混ざるのは、正確には 2行目のほうを共有しているから です。 ~/.claude だけを bind して ~/.claude.json を共有していない人は、混ざりの主役をまだ共有していません。 中身を更新頻度で並べ直す settings.json や skills/ のような user レベルのものは、そもそもどこで作業していても同じものを使う前提で用意されています。共有したいのは自明で、迷いません。 迷うのは .claude.json です。名前も中身も「設定ファイル」の顔をしていて、実際に user レベルの設定も入っています。役割で並べると共有側に落ちます。ところがこのファイルは起動や操作のたびに書き換わり、中身の大半はプロジェクトごとの状態です。 書き込み頻度で並べると、ここが状態側に落ちます。 中身 役割 書き込み頻度 .credentials.json 認証トークン 稀 (ログイン時・トークン更新時のみ) settings.json user レベル設定(権限の許可リストなど) 稀 (設定を変えたときだけ) CLAUDE.md user レベルのメモリ 稀 (書いたときだけ) skills/ user レベルの skill 稀 .claude.json (既定では ~/.claude.json ) 設定・プロジェクトの信頼状態など 高 (起動・操作のたびに書き換わる) projects/ ・ sessions/ ・ history.jsonl 会話履歴・プロンプト履歴・実行中セッションの検出 高 (操作のたびに書き換わる) この表で上下がきれいに分かれます。 コンテナをまたいで共有して嬉しいのは上の稀更新グループだけ です。認証トークンは共有したいから共有している。user レベルの設定・メモリ・skill も、どのプロジェクトで作業していても同じものを使いたい種類のものです。 混ざって困るのは下の高頻度グループ です。ここには2つの向きの困りかたがあります。 他のプロジェクトの状態が見えてくる : .claude.json の projects は全プロジェクト分の信頼状態を1ファイルに持ちます。 projects/ 配下の会話履歴も、いま開いているリポジトリと無関係なものまで並びます 自分のいるコンテナの外からの書き込みが入ってくる : 別のコンテナ(あるいはホスト)で走った Claude Code が、同じファイルを更新します。手元では何もしていないのに中身が変わります 再ログイン不要のために本当に欲しいのはトークン1つなのに、丸ごと共有はその巻き添えで、混ざって困るものまで全部共有してしまう。これが直したかった状態です。 この下側の分け方は、こちらで発明したものではありません。公式の claude project purge (v2.1.124 以降)は、プロジェクト1つぶんの状態を消すコマンドです。その削除対象が projects/ の会話ログ、 history.jsonl の該当行、そして ~/.claude.json のそのプロジェクトのエントリ—— 本記事が隔離するものとほぼ同じ です。Anthropic 自身も、この3つを「プロジェクト固有の状態」として数えています。ただし purge は溜まったものを後から消すコマンドなので、作業している最中に他プロジェクトの状態が見えることは変わりません。 それでも「丸ごと共有」が広まったのは、そのほうが手軽だから この分類を無視して丸ごと扱う方式が広く使われているのには理由があります。Dev Container で再ビルドのたびに再ログインしたくない、という要望に対して、 ~/.claude をまとめてコンテナに渡すのが一番手数が少ないからです。 以降は bind と volume を、この記事の軸で読み分けてください。 bind はホスト側の実体を指すので共有される 。 named volume はコンテナ側の実体なので共有されない 。この記事がやろうとしているのは、その2つを1つのディレクトリの中で使い分けることです。 定番の方式は、大きく2つに分かれます。 定番方式 何をするか 達成できること 抱える問題 丸ごと named volume(公式リファレンス実装がこれ) ~/.claude 全体を named volume で永続化する 再ビルドを跨いで設定・履歴・認証を保持でき、 コンテナごとに独立する ホストとログインを共有しない= コンテナ側で別途ログインが要る 丸ごと bind(ホスト共有系) ホストの ~/.claude をそのまま bind する ホストのログインをそのまま使え、 再ログインが不要 全コンテナが同じファイルを書き換え合う 前者は Anthropic 自身の リファレンス実装 が採っている形です。 "source=claude-code-config-${devcontainerId},target=/home/node/.claude,type=volume" 後者はさきほどの入門編で採ったものです。表を見ると、2つの方式は「再ログインの手間」と「コンテナごとの独立」をトレードオフにしています。どちらも捨てたくない、というのが本記事の出発点です。 なお公式のこの実装は、 CLAUDE_CONFIG_DIR にも同じ /home/node/.claude を指定しています。後述するとおり本記事も同じことをします。環境変数のリファレンスに項目が無い変数ですが、公式のリファレンス実装自身が使っている、という位置づけのものです。 分離設計:共有し続けるものと、プロジェクトごとに分けるもの ここからが本記事の主張の中心です。方針は 稀更新のものはホストと共有し続け、頻繁更新のものは named volume でコンテナごとに独立させる こと。前述の二択(丸ごと volume / 丸ごと bind)のどちらでもない、 第3の中間設計 です。 先に性格を断っておきます。これは 公式のリファレンス実装が示す形から外れた回避策 です。Docker がマウントを深さ順に並べ替えること、 CLAUDE_CONFIG_DIR が集約先を動かすこと——この2つの挙動に乗って成立しています。どちらも後で実物で確かめますが、公式が保証した組み合わせではないので、 どちらかが変われば追従が要る 前提で採ってください。 対象 扱い なぜ .credentials.json (トークン) ホストと bind 共有 再ログインを不要にしたい。更新は稀 settings.json ・user CLAUDE.md ・ skills/ ホストと bind 共有 稀更新。どのプロジェクトでも同じものを使いたい。分けるとホスト側で育てた許可設定や user 資産がコンテナで使えなくなる .claude.json ・ projects/ ・ sessions/ ・ history.jsonl named volume でコンテナごとに独立 頻繁に更新される。他プロジェクトの状態が見えず、外からの書き込みも入らない。volume は再ビルドで消えず永続する plugins/ 共有しない(コンテナごと) 稀更新だが例外。理由は「ハマり所」で述べます バイナリ( ~/.local/ ) コンテナ固有(共有しない) 再ビルド時に入れ直す。代償として再ビルドまで版が固定される volume 名をプロジェクトごとに変えるのが肝 です。同じ名前を使い回すと、せっかく volume にしてもプロジェクト間で中身を共有してしまいます。リポジトリ名を含めた名前(例: myrepo-claude-config )にしておけば、履歴と .claude.json はプロジェクトごとに完全に独立します。 この設計は次の2段構えで成立します。 1段目: CLAUDE_CONFIG_DIR で集約先を $HOME/.claude に固定する。 ポイントは、これが 既定と同じパスの明示指定 であることです。効果は「外にあった .claude.json が ~/.claude の中に入る」ことです。これで .claude.json が volume の内側に入り、 リビルドを跨いで残せるようになります 。指定しなくてもコンテナごとに独立はしますが、その場合は volume の外=リビルドで消える場所に書かれるので、独立と永続の両方を取るにはこの1段が要ります。認証情報についても、Linux / Windows では CLAUDE_CONFIG_DIR を設定すると .credentials.json がそのディレクトリ配下に置かれることが 認証ドキュメント に明記されています。 公式のリファレンス実装が現に使っている変数で、 .claude ディレクトリの解説 にも「これを設定すれば ~/.claude 配下のパスはそちらの下に移る」と書かれています。それでも環境変数の 公式リファレンス には項目として載っていません。 前者は後者へリンクを張っているのに、飛んだ先にその項目が無い 、という状態です(2026-08-02 時点)。ドキュメント化を求める Issue #33430 は not planned として close されました 。載せてほしいという要望も「この変数が効いていない」というバグ報告も上がっているのに項目は無い—— 動くから使われている 、という位置づけの変数です。 さらに、この公式の記述は ~/.claude 配下 のパスについてのものです。本記事が頼っているのは、その外にある ~/.claude.json を配下へ引き込む挙動のほうで、そちらはどの公式ドキュメントにも書かれていません(後述の「動作確認」で実物を見ます)。機能はしますが、リファレンスに裏付けられた公式仕様ではない点は承知の上で採ってください。 既定と同じパスを指定することには副産物もあります。 CLAUDE_CONFIG_DIR を尊重せず ~/.claude を見にいってしまう既知バグ( #4739 は /ide 連携のロックファイル、後継の #30538 は VS Code 拡張機能。後者は現在も open)がありますが、フォールバック先と指定先が同じディレクトリになるため、この一族のバグは実質的に無効化されます。 なおどちらも IDE 連携側の不具合で、CLI 本体の資格情報の集約には及びません。 2段目: 集約先を named volume にし、その上に稀更新のものだけを深いパスで bind して重ねる。 ディレクトリ全体を指す volume に対して、より深いパスを名指しした bind を重ねます。後者が前者の上に乗るので、ディレクトリ全体は volume(コンテナ固有)のまま、名指しした少数のファイルだけがホスト共有になります。 この重なりは 書く順番に依存しません 。わざと bind 4本を volume より先に書いたコンテナを起動して、中から実際のマウント順を見るとこうなります。 $ grep -i claude /proc/self/mountinfo | awk '{print $5}' /home/vscode/.claude /home/vscode/.claude/.credentials.json /home/vscode/.claude/settings.json /home/vscode/.claude/CLAUDE.md /home/vscode/.claude/skills 指定した順ではなく、 浅いものから順に 並び直っています。volume を先・後・真ん中に置いた3通りで試しましたが、どれも同じ並びになり、共有した4つの中身もホスト側のものが見えました。 並べ替えているのは Docker デーモンです(上の対照は docker run で直接組みましたが、compose も devcontainer.json も最後は同じデーモンを通ります)。moby の daemon/volumes.go に、target のパス区切りの数でマウントを整列する sortMounts があります。コメントは「マウントが他のマウントを覆い隠さないようにするため。たとえば /etc と /etc/resolv.conf をマウントするなら、 /etc/resolv.conf を先にマウントしてはならない」と、まさにこの用途を書いています。 書く順番は気にしなくて構いません。深さの関係さえ作れていれば狙った重なりになります。実際に重なったかどうかは、後述の「動作確認」で自分の環境で目視できます。 つまり「コンテナ固有の volume の中に、共有したいものだけホストへの窓を開ける」構成です。これで「再ログイン不要」と「履歴や状態がプロジェクトごとに独立する」を同時に満たせます。正確には、 導入時の1回だけはログインが必要 で、そこで書かれたトークンがホスト側に残るため2回目以降のリビルドで不要になります(実測は後述の「動作確認」)。 引き換えに、履歴の置き場所が弱くなる 得るものだけ書くのは不誠実なので、先に払うものを1つ出しておきます。 この設計は、会話履歴の耐久性を確実に下げます。 丸ごと bind の構成では、履歴はホストの ~/.claude/projects/ にありました。ホームディレクトリごとバックアップを取っていればその中に入りますし、コンテナを何回作り直しても残ります。本構成に移すと、履歴は named volume の中へ移ります。リビルドでは消えませんが、 ホームのバックアップ対象からは外れます 。そして docker volume prune や docker system prune -a --volumes で消えます。ディスクが逼迫したときに反射で叩くコマンドです。 「再ビルドで消えない」ことと「消えない」ことは別だ、と理解したうえで採ってください。履歴を資産として扱っているなら、volume を対象にしたバックアップを別途組む必要があります(本記事ではそこまで踏み込みません)。混ざらないことと引き換えに何を差し出すのかは、末尾の「制約・前提」にも一覧で置いています。 Dev Container で実装する ここからは、上の線引きを実際の設定ファイルに落とします。読者の環境がどちらでも動くように、compose ベースと素の devcontainer.json の両方の完成コードを載せます。 検証状況 : compose 版は別のリポジトリで運用中の構成です。素の devcontainer.json 版はこの記事を書いているリポジトリに適用し、リビルドを2回跨いだ実測を後述の「動作確認」に載せています(Claude Code v2.1.220 / WSL2)。 compose ベースの場合 workspace サービスに、環境変数・named volume・重ね bind を定義します。 services: workspace: environment: CLAUDE_CONFIG_DIR: /home/vscode/.claude DISABLE_AUTOUPDATER: "1" volumes: # 頻繁更新分(.claude.json / projects / sessions / history.jsonl)はコンテナ隔離 - type: volume source: claude_config target: /home/vscode/.claude # 稀更新分だけ、深いパスの bind を重ねてホスト共有する - type: bind source: ${HOME}/.claude/.credentials.json target: /home/vscode/.claude/.credentials.json - type: bind source: ${HOME}/.claude/settings.json target: /home/vscode/.claude/settings.json volumes: claude_config: CLAUDE_CONFIG_DIR は集約先を固定します。前述のとおり、外にある .claude.json を ~/.claude 配下に引き込むのが狙いです。 DISABLE_AUTOUPDATER: "1" はバージョンを決定的にします。バイナリは ~/.local/ (コンテナ固有)にあるため、更新は再ビルド時に入れ直す形になります。裏を返せば 再ビルドするまで古い版に留まる ということなので、更新を取り込みたいタイミングで再ビルドしてください。 named volume を /home/vscode/.claude にマウントし、設定・履歴・ .claude.json をコンテナに隔離して再ビルドを跨いで永続させます。 稀更新のファイルを同名パスへ重ね bind します。より深いパスの bind が volume の上に重なるため、そのファイルだけがホスト共有になります。 consistency: cached は付けていません。Docker Desktop for Mac(osxfs)時代のオプションで、 Linux では無視される ためです。既存の設定に残っている場合は機能上無害ですが、意味があるように見えるぶん紛らわしいので外しておくのが親切です。 環境変数をもう1つ入れるなら CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1" も候補で、共有と隔離の線引きとは独立した話題になりますが、チームで使うときの考え方は Claude Code Auto Memory をチームでは使わない理由 に書いています。 素の devcontainer.json の場合 compose を使わない構成では、マウントは devcontainer.json の mounts 配列に書きます。Claude Code に関係する部分だけ抜き出すと次の形です。 { "remoteUser": "vscode", // ホストとコンテナで uid が食い違う場合に揃える。重ね bind したファイルの // 権限調整をこれに委ねるため、本構成では明示的に有効化しておく "updateRemoteUserUID": true, "remoteEnv": { // 既定の $HOME/.claude と同一パスを明示指定する(.claude.json を配下に引き込む) "CLAUDE_CONFIG_DIR": "/home/vscode/.claude" }, // bind のソースはコンテナ生成前にホスト側へ実体を作っておく(ホスト上で実行される) "initializeCommand": "mkdir -p ~/.claude/skills && touch -a ~/.claude/.credentials.json ~/.claude/CLAUDE.md && chmod 600 ~/.claude/.credentials.json && { [ -s ~/.claude/settings.json ] || echo '{}' > ~/.claude/settings.json; }", // 先頭の chown に -R を付けてはいけない(理由は後述) "postCreateCommand": "sudo chown vscode:vscode /home/vscode/.claude && curl -fsSL https://claude.ai/install.sh | bash", "mounts": [ // 頻繁更新分はコンテナ隔離。volume なのでリビルドで消えない。 // volume 名にはリポジトリ名を入れる(理由は直後の「3点目」を参照) "source=myrepo-claude-config,target=/home/vscode/.claude,type=volume", // 稀更新分だけ深いパスの bind を重ねる "source=${localEnv:HOME}/.claude/.credentials.json,target=/home/vscode/.claude/.credentials.json,type=bind", "source=${localEnv:HOME}/.claude/settings.json,target=/home/vscode/.claude/settings.json,type=bind", "source=${localEnv:HOME}/.claude/CLAUDE.md,target=/home/vscode/.claude/CLAUDE.md,type=bind", // ディレクトリでも同じように重ねられる "source=${localEnv:HOME}/.claude/skills,target=/home/vscode/.claude/skills,type=bind" ] } compose 版との違いは3点です。 マウントを書く場所 (各サービスの volumes: か、 devcontainer.json の mounts 配列か)、 HOME の変数記法 ( ${HOME} か ${localEnv:HOME} か)、そして volume 名の扱い 。前の2つは書き換えるだけですが、3点目は設計の肝に関わるので単独で説明します。 compose の top-level volumes: に書いた名前は、 compose プロジェクト名でプレフィックスされます 。 Compose Specification が既定動作として定めていて、例外は name: を明示したときだけです。だから claude_config という汎用名のままでも、プロジェクトごとに別の volume になります。 一方 devcontainer.json の mounts は compose を経由せず、Docker CLI のマウント構文へそのまま渡ります。 プレフィックスの仕組みが挟まらないので、書いた名前がそのまま volume 名になります 。これは後述の確認2で実際に見えます。手元の devcontainer.json には source=sios-claude-config と書いてあり、 findmnt が返す実体も /var/lib/docker/volumes/sios-claude-config/_data です。リポジトリ名は付いていません。 つまり汎用名のままだと全プロジェクトが同じ volume を掴み、前述の「プロジェクトごとに独立させる」が成立しなくなります。 ただ、名前を手で付け分けるのは規律に頼る運用です。忘れれば静かに壊れます。ここは変数で自動化できます。 // リポジトリのフォルダ名から導出する(読める名前になる) "source=claude-config-${localWorkspaceFolderBasename},target=/home/vscode/.claude,type=volume" ${localWorkspaceFolderBasename} は devcontainer 仕様の変数で、 json_reference が mounts での利用を認めています。 ただしこれは フォルダ名から導出するので、別の場所にある同名リポジトリとは衝突します 。 ~/work/app と ~/oss/app を両方 Dev Container で開いていれば、どちらも claude-config-app を掴みます。手で命名するよりは安全ですが、衝突が消えるわけではありません。 そこまで潰すなら ${devcontainerId} を使います。Anthropic 自身のリファレンス実装がこれです。上と同じ json_reference が「その dev container に固有で、リビルドを跨いで安定する識別子」と定めているので、同名フォルダでも衝突しません。代わりに名前が不透明になり、 docker volume ls で目視できなくなります。 同名リポジトリを複数開く可能性があるなら ${devcontainerId} 、読める名前を優先するならフォルダ名 、という選び方になります。 initializeCommand について補足します。ファイル bind はソースが存在しないと、Docker がそれを root 所有のディレクトリとして誤生成してしまいます。これを防ぐため、ホスト側に空ファイルを先に作ります。 initializeCommand はコンテナ生成前にホスト上で実行されるので、ここが適切な置き場所です。 3点、細かいが外せない注意があります。 chmod 600 を付ける 。公式ドキュメントは Linux の .credentials.json を “file mode 0600 ” と明記しています。 touch だけだと既定の umask で 644 のトークンファイルができあがるため、明示的に絞ります。 settings.json は空ファイルにしない 。 {} で初期化します。 .credentials.json は空でも “Not logged in” として扱われますが、 settings.json が空だと JSON パースに失敗しうるためです。 mkdir -p / touch -a は冪等 なので、すでにファイルを持っているメンバーの環境では何もしません。 postCreate での所有者修正とインストール コンテナ生成後は、所有者修正 → インストーラの順で実行します。 # 新規 named volume はマウントポイント(~/.claude)が root 所有で初期化される。 # 非再帰で「ルートだけ」を vscode へ。-R は使わない(重ね bind したホスト側の # 実体を巻き込むため。理由は後述) if [ -d "$HOME/.claude" ]; then echo "[postCreate] Fixing ownership of .claude volume root (non-recursive)" sudo chown vscode:vscode "$HOME/.claude" fi # 非ブロッキング: ネットワーク/プロキシ起因の失敗で postCreate 全体を止めない echo "[postCreate] Installing Claude Code (native installer)" if curl -fsSL https://claude.ai/install.sh | bash; then echo "[postCreate] Claude Code installed" else echo "[postCreate][WARN] Claude Code install failed (network/proxy?); continuing" fi echo "[postCreate] Completed" インストーラを if で包んでいるのは、企業プロキシなどで到達できなかったときに postCreate 全体を止めないためです。 既存の履歴を持ち込む この構成に移ると projects/ は空から始まります。ホストに残った過去の会話を引き継ぎたい場合は、手でコピーできます。ただし cp だけでは足りず、 ディレクトリ名の付け替えが要ります 。 projects/ 配下のディレクトリ名は、開いていたワークスペースのパスから機械的に導かれます。ホストで /home/ryu/product/blog/sios-tech-blog-with-claude を開いていたなら -home-ryu-product-blog-sios-tech-blog-with-claude 、コンテナで /workspaces/sios-tech-blog-with-claude を開けば -workspaces-sios-tech-blog-with-claude です。名前が違うので、そのままコピーしてもコンテナ側は「このプロジェクトの会話は無い」と言います。実際に名前を揃えずに入れてみたところ、 claude --resume は空のままでした。 ホスト側で ls ~/.claude/projects/ を見て自分のディレクトリ名を確かめてから、名前を付け替えつつ volume へ流し込みます。 # ホスト側で実行。<volume> は devcontainer.json に書いた volume 名 docker run --rm \ -v <volume>:/dst \ -v ~/.claude/projects/-home-ryu-product-blog-sios-tech-blog-with-claude:/src:ro \ alpine sh -c 'mkdir -p "/dst/projects/-workspaces-sios-tech-blog-with-claude" \ && cp -a /src/. "/dst/projects/-workspaces-sios-tech-blog-with-claude/" \ && chown -R 1000:1000 /dst/projects' chown の 1000 はコンテナ側 vscode の uid です。root 所有のまま置くと Claude Code が書き込めません。 必要なのはここまでで、 .jsonl の中身を書き換える必要はありません 。各行は cwd にホスト側の絶対パス( /home/ryu/... )を持ったままですし、 sessions-index.json の originalPath もホストのパスのままですが、コンテナ内の claude --resume はディレクトリ名だけを見てセッションを拾います。持ち込んだセッションを実際に開くと、リビルド前のやり取りがそのまま復元されて続きから会話できました。 ただし持ち込めるのは その時点の断面だけ です。これ以降ホスト側で増えた会話は入ってきません。あと、リポジトリによっては projects/ 配下が数百MBあるので(手元の1リポジトリで885MB)、流し込む前にサイズは見ておいてください。 ハマり所 ここからは実装上の落とし穴です。本構成を実際に組んだときに踏んだものだけを並べます。 named volume の初期所有者は root なので chown は非再帰で named volume を 新規作成 すると、マウントポイント( ~/.claude )は root(uid 0)所有 で初期化されます。このままだと vscode ユーザーが配下に書き込めず、設定の保存が失敗します。そのため postCreate で ~/.claude の所有者を vscode に直します。volume は再ビルドで消えないため、初回作成後はすでに vscode 所有となり、この処理は冪等です。 ここで重要なのが、 chown に -R (再帰)を付けてはいけない ことです。 この時点の ~/.claude は、新規 volume(空)に重ね bind したファイルが乗っているだけの状態です。root 所有なのはルートディレクトリ自身だけで、サブディレクトリは Claude 初回起動時に vscode 所有として作られます。ルートだけ直せば十分です。 -R を付けると、重ね bind したファイルまで再帰の対象に入ります。この bind 元は ホスト側のファイルそのもの(コンテナとホストで同じ実体を指しています) なので、コンテナ内での再帰 chown が ホスト側の所有権まで書き換えます 。ホストの uid が 1000 でない環境では、書き換えられた結果ホスト側の Claude Code がトークンを読めなくなります。共有するファイルを増やすほど、この事故の影響範囲は広がります。 非再帰なら共有ファイルには一切触れません。権限調整は initializeCommand (ホスト側で実行)と updateRemoteUserUID: true に委ねます。 plugins/ は稀更新でも共有できない 「稀更新なら共有してよい」の例外です。 plugins/ は更新頻度こそ低いのですが、 レジストリの中身がコンテナの絶対パスを持っています 。 known_marketplaces.json の installLocation installed_plugins.json の installPath / projectPath これらに /home/vscode/.claude/plugins/... や /workspaces/... といったコンテナ側のパスが記録されます。ここまでは実物を開いて確認した事実です。 ホストと共有すると、両者が互いに解決できないパスを見ることになります。片方が「存在しないパスを指している=壊れている」と判断してレジストリを自分のパスで上書きし、次はもう片方が同じことをする——というピンポンが起きるはずです。 ただしこれは記録されるパスから導いた推測で、実際に往復させて確かめたわけではありません 。確かめる価値より断つコストのほうが安いので、構成で切っています。 共有をやめた場合の復旧コストは /plugin install を1回やり直すだけです。共有した settings.json に marketplace の情報が残るので、そこから復元できます。 未導入メンバーへの配布では空ファイルを先に作る これはチームへ配布したときに実際に踏んだ罠です。ホストに ~/.claude/.credentials.json が無いと、Docker が bind ソースを root 所有のディレクトリとして誤生成 します。Claude Code をまだ使っていないメンバーの環境では bind ソースが存在せず、root 所有で生成された結果、 vscode から書き込めなくなって壊れました。 対応は前述の initializeCommand です。空の .credentials.json は “Not logged in” として扱われるためクラッシュせず、初回に claude /login するとトークンがこのファイルに書き込まれ、以降は永続します。 壊れてしまった状態からの復旧 すでに root 所有のディレクトリとして誤生成されている場合は、それを消してからやり直します。 # ホスト側で実行(root 所有ディレクトリになっているものを削除) sudo rm -rf ~/.claude/.credentials.json このとき注意したいのが、 initializeCommand の中で権限を直そうとして chown を書く場合です。ホスト上で sudo なしに実行されるため、root 所有のものに対しては失敗します。そして initializeCommand が失敗するとコンテナの作成自体が止まります ( json_reference はライフサイクルスクリプトの失敗について「後続は実行されない」とだけ書いており、ホスト側で走る initializeCommand の失敗時にどうなるかは明記していません。ここは仕様の裏を取れていない挙動です)。「壊れた」状態で検索して来た読者がまず踏むのはここなので、先にホスト側で消しておくのが確実です。 volume 側が壊れた場合は docker volume rm で作り直せますが、 中の履歴と設定も一緒に消えます (後述の制約を参照)。 動作確認 本構成の中核は、 CLAUDE_CONFIG_DIR による集約先の移動と、volume の上への bind の重なりです。どちらも設定ファイルを読んだだけでは効いたかどうか分かりません。組んだあとに確認してください。以下は本記事の素の devcontainer.json 版をこのリポジトリに適用し、リビルドを2回跨いだうえで、さらに3日そのまま使って取った実測です。 4本あります。 どれもコンテナの中でコマンド1つ なので、順に叩けば数分で終わります。1と2で設計の2段が効いたかを見て、3で看板(再ログイン不要)を、4でその結果として何が変わったかを確かめる流れです。 先に、記事の主張を正確な形に直しておきます。 「リビルドしても再ログイン不要」ではありません。導入時に1回だけログインが必要で、そのとき書かれたトークンがホスト側に残るため、2回目以降のリビルドで不要になります。 initializeCommand が作るのは0バイトの空ファイルなので、導入時点でホストにトークンを持っていなければ初回の1回は必ずログインが要ります。実際、1回目のリビルド直後はログインを求められました。ここを飛ばして読むと、導入直後に「効いていない」と誤解します。 1. .claude.json が ~/.claude の中に入ったか まず1段目からです。記事の冒頭で、既定では .claude.json が ~/.claude の 外 にあることを ls で見ました。同じコマンドを新構成のコンテナ内で叩くと、そっくり反転します。 $ ls -la ~/.claude.json ~/.claude/.claude.json ls: cannot access '/home/vscode/.claude.json': No such file or directory -rw------- 1 vscode vscode 42482 Aug 1 12:56 /home/vscode/.claude/.claude.json 外にあったはずのファイルが消え、 ~/.claude の中に現れています。 CLAUDE_CONFIG_DIR が効いた証拠がこれです。ここが反転していなければ、 .claude.json は volume の外に残っています。その場合、コンテナ固有ではあるものの リビルドで消える 場所に書かれているので、隔離できたように見えて永続しません。 2. bind が volume の上に乗っているか 2段目です。 findmnt を階層表示のまま .claude で絞ると、重なり方が1画面で見えます。 $ findmnt -o TARGET,SOURCE | grep -i claude ├─/home/vscode/.claude /dev/sdc[/var/lib/docker/volumes/sios-claude-config/_data] │ ├─/home/vscode/.claude/CLAUDE.md /dev/sdc[/home/ryu/.claude/CLAUDE.md] │ ├─/home/vscode/.claude/skills /dev/sdc[/home/ryu/.claude/skills] │ ├─/home/vscode/.claude/settings.json /dev/sdc[/home/ryu/.claude/settings.json] │ └─/home/vscode/.claude/.credentials.json /dev/sdc[/home/ryu/.claude/.credentials.json] ディレクトリ自体は volume( /var/lib/docker/volumes/... )を指し、その 内側にぶら下がった4つだけ がホストのパス( /home/ryu/.claude/... )を指しています。狙った重なり方です。共有すると決めたものが4つとも子として並んでいることも、ここで同時に確認できます。ぶら下がりが1つも出ないなら bind が効いておらず、以降の確認は通りません。 なお skills はファイルではなくディレクトリですが、扱いは同じです。volume 側の同名ディレクトリを丸ごと覆い隠して、ホストの中身が見えます。 出力はこのリポジトリの実測そのままなので、volume 名がサンプルの myrepo-claude-config ではなく sios-claude-config になっています。前述のとおりリポジトリ名を入れた名前にしているためで、読み替えてください。 ここまで出ていれば、トークンがホストと同じ実体であることも同時に決まります。 source がホストのパスを指している時点で、そのパスでは volume 側のコピーが隠れている からです。コンテナから読める中身は、ホストのファイル以外にありません。逆に .credentials.json の行だけホスト以外を指しているなら、 ${localEnv:HOME} の解決先がずれています(Windows のファイルシステム上でリポジトリを開いた場合に起こりえます。末尾の「制約・前提」も参照)。 3. 再ログインが要らないか claude auth status がログイン状態を JSON で返します。対話セッションを起こす前に確かめられるので、これが一番早い確認です。 $ claude auth status { "loggedIn": true, "authMethod": "claude.ai", "apiProvider": "firstParty", ... } ただし「ログイン画面が出なかった」だけでは、裏で新しくログインし直していないことの証明になりません。判別できるのは .credentials.json の中身です。 リフレッシュトークンの有効期限が変わっていなければ、新規ログインは起きていません 。新規ログインならリフレッシュトークンが再発行され、期限もそれに合わせて先へ動くためです。 この推論は片道でだけ使ってください。「動いていない → ログインしていない」は言えますが、逆の「動いた → ログインした」は言えません。トークン更新のたびにリフレッシュトークン自体を再発行する実装なら、ログインなしでもここは動きうるからです(手元の v2.1.220 では、後述のとおり更新をまたいでも動きませんでした)。 $ python3 -c "import json,os,datetime as dt; \ d=json.load(open(os.path.expanduser('~/.claude/.credentials.json')))['claudeAiOauth']; \ [print(k, dt.datetime.fromtimestamp(d[k]/1000).strftime('%Y-%m-%d %H:%M:%S')) \ for k in ('expiresAt','refreshTokenExpiresAt')]" expiresAt 2026-07-31 00:20:05 refreshTokenExpiresAt 2026-08-27 19:01:56 リビルドの前後と、さらに3日そのまま使ったあとで並べるとこうなりました。3日後の列は挙動を見極めるためにこちらで取った追試です。 読者が3日待つ必要はありません 。 項目 リビルド前(7/30) リビルド後(7/30) 3日後(8/1) inode 1396334 1396334 1396334 サイズ 509 509 509 mtime 07-30 16:20:05.958 07-30 16:20:05.958 08-01 11:21:35.319 expiresAt (アクセストークン) 2026-07-31 00:20:05 2026-07-31 00:20:05 2026-08-01 19:21:35 refreshTokenExpiresAt 2026-08-27 19:01:56 2026-08-27 19:01:56 2026-08-27 19:01:56 refreshTokenExpiresAt が動いていないので、2回目のリビルドで新規ログインは発生していません。 リビルドの直後だけを見ると、アクセストークンの期限(7/31 00:20)がまだ生きていたため mtime すら動いていません。1回目が書いたファイルをそのまま読んだだけです。3日後の列で、その先が見えます。アクセストークンは期限切れを迎えて更新され、 mtime と expiresAt は動きました。 それはログイン不要のまま起こる正常系 です。一方で refreshTokenExpiresAt は動いていません。判定に使うのがこちらでよい理由が、この1列で確かめられます。 同じ列がもう1つ示しているのが inode の不変 です。トークンが書き換わっても番号が変わっていない=Claude Code はこのファイルを その場で上書き しており、一時ファイルを作って rename で差し替えてはいません。単一ファイルの bind が切れる典型的な原因がこの rename なので、ここが動かないことは本構成が長期的に保つかどうかの目安になります(後述の制約も参照)。 4. 他のプロジェクトが見えなくなったか ここまでの3つは「設計が効いたか」を見てきました。最後は、効いた結果として 何が変わったか です。記事の冒頭で .claude.json を数えたのと同じコマンドを、新構成のコンテナ内で叩きます。 $ python3 -c "import json,os; d=json.load(open(os.path.expanduser('~/.claude/.claude.json'))); \ print('projects:', len(d['projects']), '/ githubRepoPaths:', len(d['githubRepoPaths']), '/ numStartups:', d['numStartups']); \ print('project keys:', list(d['projects'].keys()))" projects: 1 / githubRepoPaths: 1 / numStartups: 10 project keys: ['/workspaces/sios-tech-blog-with-claude'] 36プロジェクトが1つになりました 。しかもその1つは、いま開いているリポジトリそのものです。 numStartups も 1278 から 10 に落ちていて、このカウンタがコンテナの中だけで数え直されていることが分かります。他プロジェクトの信頼状態は、もうここからは見えません。 会話履歴も同じです。 $ ls ~/.claude/projects/ -workspaces-sios-tech-blog-with-claude ディレクトリが1つだけ。ここに無関係なリポジトリの名前が並んでいたら、 .claude.json か projects/ のどちらかが volume の外に残っています。逆に 中を覗いてリビルド前のセッションの .jsonl がそのまま読めれば 、隔離した側が消えずに永続していることも同時に確認できます。ここが空なら、意図した named volume ではなく匿名ボリュームやコンテナのレイヤに書いている可能性があります。 制約・前提 本構成を採る前に知っておくべき制約を整理します。 項目 内容 認証トークンの露出 .credentials.json はコンテナから読み書きできます。コンテナ内の任意のコード・MCP・エージェントがトークンを取得しうる、という共有の本質的なトレードオフです。許容できない場合は共有をやめ、初回都度ログインする構成(volume のみ・bind なし)にします volume を消すと設定・履歴も消える docker compose down -v / docker volume rm / docker volume prune を実行すると、隔離した .claude.json と会話履歴は失われます。ホームディレクトリごとバックアップしている場合も、隔離した分はその対象から外れます。「再ビルドで消えない」ことと「消せない」ことは別です 分けたことの代償 プロジェクトの信頼状態・ projects/ の会話履歴・ history.jsonl はコンテナ側で空から始まります。 --resume がホスト側の過去セッションを自動で拾うことはありません(ディレクトリ名を付け替えて volume へコピーすれば、一度きりの持ち込みはできます。「既存の履歴を持ち込む」を参照)。初回にプロジェクトの信頼プロンプトが出ます。**「混ざらない」の裏返しは「手を動かさないと入ってこない」**なので、過去の履歴を頻繁に遡る使い方をしている場合は、この構成は向きません user スコープの MCP サーバが引き継がれない claude mcp add --scope user で登録した MCP サーバは .mcp.json ではなく ~/.claude.json に書き込まれることが 公式ドキュメント に明記されています。このファイルを隔離するので、 user スコープで登録した MCP サーバはコンテナごとに登録し直し になります。リポジトリに置いた .mcp.json (プロジェクトスコープ)は bind の対象外なので影響を受けません。なお手元は user スコープの登録が0件で、この不便自体は踏んでいません(ドキュメントからの指摘です) 断てるのはホスト コンテナ経路だけ 混ざりを断てるのはホストと各コンテナのあいだです。同一コンテナ内で claude を複数起動すれば、それらは同じ volume 上の同じ .claude.json を共有します トークン更新をまたいだ長期挙動 単一ファイルの bind は、書き手が「一時ファイルに書いて rename で差し替える」方式を採ると実体の対応が切れることがあります。v2.1.220 の実測では、初回ログインでコンテナ内から書かれたトークンが inode を変えずにホストへ貫通し、次のリビルドで読み出せました。さらに3日後、アクセストークンの期限切れによる更新が実際に走ったあとも inode は同じままでした(=上書き方式)。ただしこれは実装の観察であって保証された仕様ではないので、版が上がったら上記「動作確認」で確かめ直してください ホスト前提 Linux / WSL2 で検証しています。macOS では認証情報が Keychain に保存され .credentials.json としてファイル化されないことが 認証ドキュメント に明記されているため、トークンの bind 共有は成立しません(コンテナ側で claude /login し、volume で以降永続させる形になります)。保存先はおそらくログインキーチェーン内のアプリケーションパスワード相当の項目だと思われますが、 macOS 実機では未検証 なので、場所の特定は各自で確認してください $HOME の食い違い Windows のファイルシステム上でリポジトリを開くと、 initializeCommand の $HOME と compose の ${HOME} がずれる恐れがあります。リポジトリは WSL 上に置いてください CLAUDE_CONFIG_DIR の位置づけ 機能しますが、環境変数の 公式リファレンス には項目として載っていません( 認証ドキュメント と .claude ディレクトリの解説 で挙動が言及されるのみ。後者はリファレンスへリンクを張っていますが、飛んだ先に項目はありません=2026-08-02 時点)。ドキュメント化を求める Issue #33430 は not planned で close されており、リファレンス化を待つ前提では組まないほうが安全です なお、認証情報をホストに保持してコンテナから参照する考え方そのものは、Claude Code に限った話ではありません。 Azure CLI と gh をチームで統一する構成 や Gemini CLI の認証共有 でも同じ発想を採っています。本記事はそこに「何を共有し、何をプロジェクトごとに分けるか」という線引きを一段持ち込んだ形です。 まとめ ~/.claude を丸ごとマウントすると、 全コンテナがホストの同じファイルを書き換え合う 状態になります。手元の .claude.json には36プロジェクト分の状態が入っていました。他プロジェクトの履歴が見え、コンテナの外からの書き込みが入ってくる。壊れなくても、コンテナに閉じたはずの作業が外と混ざっているのは気持ち悪いです。 ~/.claude の中身は 更新頻度の違うものの寄せ集め で、上下できれいに分かれます。共有したいのは稀にしか更新されないもの(認証トークン・user 設定・user メモリ・user skill)だけ。混ざって困るのは起動や操作のたびに書き換わる .claude.json と履歴です。しかも .claude.json は既定では ~/.claude の外にあるため、「丸ごと」で扱おうとすると取りこぼしやすい位置にいます。 頻繁更新分を named volume でコンテナごとに独立させ、稀更新分だけを bind 共有すれば、 履歴と状態をプロジェクトごとに分けたまま、再ログインの手間を導入時の1回で済ませられます (そこで書かれたトークンがホストに残るため、2回目以降のリビルドでは不要)。実測では、36プロジェクト分あった .claude.json の状態が いま開いているリポジトリ1つだけ になりました。volume 名はプロジェクトごとに変えてください。素の devcontainer.json の volume 名は compose と違ってプレフィックスされないので、ここを汎用名のままにすると分けたつもりで分かれません。 ただし タダではありません 。履歴はホストのホームから named volume へ移るので、ホームのバックアップから外れ、 docker volume prune で消えます。過去のセッションを頻繁に遡る使い方をしているなら、この構成は向きません。「混ざらない」の裏返しは「手を動かさないと入ってこない」です(導入時の持ち込みだけは、ディレクトリ名を付け替えて volume へコピーすれば通せます)。 「稀更新なら共有してよい」にも例外があります。 plugins/ はレジストリがコンテナの絶対パスを持つため、共有するとホストとコンテナで壊し合います。 これは公式のリファレンス実装が採る「丸ごと volume」でも、多くの記事がやる「丸ごと bind」でもない 中間設計 です。更新頻度で線を引くと、再ログインの手間とコンテナごとの独立を両方取れます。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Codeの~/.claude、どれを共有してどれを分ける? first appeared on SIOS Tech Lab .
こんにちは。ファインディ株式会社でプリンシパルエンジニアをしている戸田です。 2026年8月5日(水)に、Findy AI Meetup in Fukuoka #7を福岡で開催しました。当日参加くださったみなさま、ありがとうございました! findy-inc.connpass.com 今回のテーマは「AI開発の"今まで"と"これから"を語り尽くそう」です。 皆さまの熱いご支援のお陰で、Findy AI Meetup in Fukuokaは今回で1周年を迎えました。節目となる今回は、AI開発のこれまでを振り返りつつ、これからを見据える内容の登壇が揃いました。 この記事では、ファインディメンバーによる2つの登壇を振り返ります。 Findy AI Meetup in Fukuokaについて え?フロントエンドエンジニアのワイがインフラも!? 「開発は一人です」から始まった新規サービス 武器は社内に揃っていた 2つの誤算 変わったこと、変わらなかったこと VibeCodingからAgenticWorkflowへ 速くなったのは開発工程ではなくコード生成 レベル1「速く作る」— VibeCodingと現場の課題 レベル2「正しく作る」— 協働から委任へ ターミナルへの回帰 — 開発環境そのものが変わった 順番を間違えない — 基本が先、AI活用は後 まとめ Findy AI Meetup in Fukuokaについて Findy AI Meetupは、ファインディのエンジニアが主催する技術系オフラインイベントです。 生成AIやAIエージェントの活用を通じた開発生産性の向上をテーマに、社内での実践事例の紹介やエンジニア同士の交流を目的としています。 福岡での開催は今回で7回目、そして1周年となりました。この1年でAI開発の景色は大きく変わりましたが、回を重ねるごとに参加者同士の交流も深まり、福岡のエンジニアコミュニティとして根付いてきたことを実感しています。 え?フロントエンドエンジニアのワイがインフラも!? まずは、フロントエンドテックリードの新福による登壇です。フロントエンドエンジニアが生成AIとともに専門外の領域へ越境した実体験をお話ししました。 speakerdeck.com 「開発は一人です」から始まった新規サービス きっかけは、新しいサービスの立ち上げでした。ファインディでは生成AI時代のプロダクトが次々に生まれており、立ち上げ期のプロダクトは少数精鋭・スピード重視で職種の枠に囚われないフルサイクル志向となることが多いです。 そんな中で、新規サービス開発を任されることになりました。ただし、人員の確保が難しいため開発は一人です。これまでなら、良いアイデアがあっても専任のメンバーが足りなければ諦めるしかありませんでした。 しかし、生成AI時代ならそれも可能かもしれません。そう考えて、フロントエンドはもちろん、バックエンド、そして完全に初見のインフラ(AWS/Terraform)まで、全部を一人で担当することにしました。 領域 内容 フロントエンド 本来の専門領域 バックエンド Honoを採用、テーブル設計などは専門メンバーによるレビュー インフラ(AWS/Terraform) IAM、VPC、ECS、RDSなど、SREチームによるレビュー 武器は社内に揃っていた 挑戦を支えたのは、弊社SREチームが整備していた社内資産でした。Terraformやバックエンド側APIのスターターキット、社内標準の構成を再利用可能な形にまとめたAWS汎用モジュール、そして環境構築を手助けするエージェントスキルです。 これらの社内資産を活用し、社内の作法に沿ったやり方でAIが書き、人間がレビューして判断するという流れで開発を進めました。 結果、アプリケーション(フロントエンド+バックエンド)に約1ヶ月、完全に専門外のインフラに約1ヶ月、合計約2ヶ月で一人で作り上げることができました。 2つの誤算 一方で、やってみて見えてきた誤算もありました。 1つ目の誤算は「時間」です。 当初は生成AIによる開発期間の短縮を見込んでいましたが、実際は専門メンバーやSREチームによるレビュー待ち、そして試行錯誤のたびに発生するTerraformの反映待ちが作業時間の相当部分を占めました。フィードバックを待つ必要があるものはAIでの高速化が難しく、AIが圧縮したのはあくまで「人間が考える時間」だったのです。 2つ目の誤算は「理解」です。 自分で書いていたときは、仕組みや依存関係を把握しなければそもそも書けないため、両者は常にセットで、疑う機会すらありませんでした。ところが生成AIに書かせると、内容を把握せずとも書けてしまいます。そのまま進めると、なぜ動くか、あるいは動かないかがわからず、インフラでこれは致命的となり得ます。だからこそ、浮いたはずの時間の一部を使って、生成AIの出力を読んで理解する時間を確保する必要がありました。まさに「思考は外注できるが、理解は外注できない」を実感した経験となりました。 変わったこと、変わらなかったこと 生成AI時代では、着手するまでの意思決定コストが下がりました。これまで人員確保がネックになっていた部分も、生成AIが実装や意思決定のコストを下げたことで、諦めなくても良くなったのです。 逆に変わらなかったのは、最終的な責任を持つのは人間だということです。生成AIの出力を判断するためには、結局のところ実装者自身が仕組みを理解し、専門知識を身につけなくてはいけません。 生成AIの発展により、越境しやすい環境になりましたが、専門知識の価値は変わりません。「理解は外注できない」という事実をしっかりと頭に留め、基礎を大事にするというのがこの挑戦から得られたものでした。 VibeCodingからAgenticWorkflowへ 続いて戸田からは、ファインディがこの1年で歩んできたAI活用の変遷を「VibeCodingからAgenticWorkflowへ」と題してお話ししました。 speakerdeck.com 速くなったのは開発工程ではなくコード生成 出発点は、AIを導入して見えてきた現実です。AIが高速化したのは「コードを書く」工程だけで、レビューや検証といった「正しいか」の確認に時間がかかり、開発フロー全体のスループットは横ばいのままでした。これは体感ではなく、可視化した数値が示した事実です。 速くコードを書けても、理解せずに生成されたコードは質が落ち、レビューでの指摘が増え、結局速さの恩恵が消えてしまう。この連鎖を断ち切るために、ファインディでは「正しい作り方と手順」をハーネス化する開発フロー改革に取り組み、AI活用レベルを3段階に分けて段階的に進めてきました。 レベル テーマ 内容 レベル1 速く作る コード生成の自動化 レベル2 正しく作る モノ作り全体の再設計 レベル3 必要なものを作る 他領域への越境 先ほどの新福の登壇は、まさにこのレベル3「他領域への越境」を体現した実例です。ここからは、そこへ至るまでのレベル1とレベル2の道のりを紹介します。 レベル1「速く作る」— VibeCodingと現場の課題 レベル1は、VibeCodingでコードを生成し、Pull requestを作成してレビュー依頼を投げるところまでをAIで自動化するフェーズです。 ただしこのフェーズでは、現場で次のような課題が起きていました。活用レベルの個人差が大きい、AI出力の合否判断ができないまま理解せずにレビュー依頼を出してしまう、Pull requestの質が低下してリードクラスのレビュー負担が増える、そしてAI主導になり人間側の理解が追いつかない「AIに使われている」状態です。 この課題に対して、まずAIが参照するドキュメントやルールを整えるガードレール整備を行いました。READMEやプロジェクトドキュメントで前提や運用ルールを記述し、AGENT.mdやrulesでコード規約・命名規則・テスト方針をAIに参照させ、よくある作業はカスタムコマンドとして規格化する。ガードレールがあって初めて、AIは「使い物になるコード」を出してくれます。 レベル2「正しく作る」— 協働から委任へ レベル2では、正しい方法と手順を用意して、AgenticWorkflowに委任します。 このフェーズの課題は、要件を実現する手順がAIフレンドリーではないことでした。タスクの粒度や手順を誰も決めておらず、生成AIへ何を渡せば精度よく動くかが属人化している。つまり、明確で簡潔なステップ構造、AIに渡す「設計図」が必要だったのです。 そこで、AIが処理しやすい単位へのタスク分解、構造化された設計図を親子Issueで表現するIssue作成、そしてAIと人間でレビュー領域を分割するコードレビューの再定義に取り組みました。人間はレビューで「作り方と実現方法が合っているか」を検証し、設計図にフィードバックする。タスク分解の品質が、そのままアウトプットの品質を決めます。 このレベル1からレベル2への移行は、AIとの関係性の変化でもあります。登壇では「協働」して書くVibeCodingと、「委任」して任せるAgenticWorkflowの違いを次のように整理しました。 観点 AIとの協働(レベル1 VibeCoding) AIへの委任(レベル2 AgenticWorkflow) 関係性 隣で並走するパートナー タスクを任せる実行者 人間の役割 ハンドルを握る運転手 行き先を決める指揮者 AIの役割 助手席のナビゲーター 自走する実行エージェント 任せる粒度 1行〜1関数 タスク/PR/フロー全体 AgenticWorkflowとは、人間がゴールと制約を与え、AIエージェントが計画・実行・自己検証までを自律的に進める開発スタイルです。ゴール指向、計画と分解、ツール使用、自己検証ループという4つの自律性を備えており、人間の仕事は成果物に対するレビューへと移っていきます。 ターミナルへの回帰 — 開発環境そのものが変わった AI委任の並列性は、開発環境そのものも変えました。2026年からファインディではメインツールがIDEからターミナルへ移行しています。 1ウインドウで1タスクずつ進めるスタイルから、複数ウインドウ・ペインで同時にAIへ委任するスタイルへ。IDEの役割は「すべての開発作業を行う場所」から「広域に渡るコードリーディングで理解を深めるとき」に使うものへと変化しました。AIに並列で任せる前提に合わせて、開発環境が「並列委任しやすいもの」へ変わってきているのです。 順番を間違えない — 基本が先、AI活用は後 最後に強調したのは、順番を間違えないことです。土台が弱いと、ガードレールもAIも成果を出せません。 統一規約・型定義・テストコードといったコード品質をまず充実させ、Pull requestの粒度やレビュー文化といった開発文化を育てる。その上でガードレール・ハーネスを整備し、最後にAI SkillやPluginを横展開して組織全体でAI活用を加速させる。基本が固まってからAI活用を載せる、この順番が重要です。 AI時代の本丸は「速く作る」ではなく、「正しく作る」「必要なものを作る」への段階的な越境です。人間の役割はコードの読み書きから、何をどう作るかの判断へと上流に移っていきます。それでも、やるべきことはAI以前から変わりません。基本の徹底こそがAI活用の大前提なのです。 まとめ 今回のテーマは「AI × これまでと、これから」でした。 2つの登壇に共通していたのは、AIによって変わったことと変わらないことの整理です。変わったのは、AIに任せられる範囲です。職種の壁を越えることが現実的な選択肢になり、協働から委任へと関係性も進化しました。変わらないのは、理解と責任が人間に残ることです。AIにどれだけ委任しても、出力を判断する専門知識と基本の土台がなければ、AIは成果を出せません。 この1年でVibeCodingという言葉が当たり前になり、いまはAgenticWorkflowへの移行が始まっています。これからも変化は続きますが、基本を固め、理解を手放さず、段階的に任せる範囲を広げていく。この姿勢は変わらないと考えています。 なお、登壇でも紹介したファインディの開発知見は、ドキュメントサイト「Findy Library」で公開しています。開発の基本からVibeCodingやAgenticWorkflowの実践まで、今回の登壇のベースになっている知見をまとめていますので、ぜひ活用してみてください。 lib.findy.co.jp そして早くも次回開催が決定しました!2026年11月12日(木)に開催予定です。次回は「AI × 並列開発 AIに委任して変わりゆく開発手法」と題しまして、AIへの委任で変わっていく開発手法について語り合う会にしたいと思っています。今回の登壇でも触れた「並列委任」をさらに深掘りするテーマです。ぜひご参加ください。 findy-inc.connpass.com ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。 herp.careers
本記事は 2026 年 8 月 3 日に公開された Clare Liguori、Romain Dura、Al Harris、Richard Threlkeld による “ One agent, every surface: how we built the Kiro agent harness ” を翻訳したものです。 Kiro の開発初期、私たちは開発者の 1 日のなかでエージェント駆動の開発がどのように感じられるべきかを議論し始めました。繰り返し立ち返ったのは、セッションがラップトップとクラウドサンドボックスの間を摩擦なく行き来する姿でした。1 日の終わりにラップトップを閉じても、Kiro セッションはクラウドで動き続けます。コーヒーを取りに行く合間にスマートフォンから状況を確認できます。翌朝、Kiro IDE を開いて中断したところから作業を再開します。 Web 版 Kiro でプロジェクトを開始し、Kiro IDE でコンテキストを追加し、既にテストとイテレーションを進めているターミナルでは Kiro CLI を使い続け、Slack から進捗を確認します。エージェント駆動の開発とは、作業するあらゆるクライアントを横断する 1 つの連続した会話であるべきです。 今年の初め、私たちはエージェントのアーキテクチャがこのビジョンの実現を妨げていることに気づきました。当時、Kiro IDE、CLI、Web の各クライアントは、それぞれ独自のセッションフォーマット、ツールセット、設定モデルを持つ専用のエージェントを実行していました。セッションと環境の間を容易に移動するには、どのクライアントを使っていても、どこで動作していても同じように振る舞う単一のエージェントが必要です。クライアント専用のエージェントアーキテクチャでは、エージェント同士が十分な共通基盤を持っていなかったため、あるクライアントで開始したセッションを別のクライアントに移すことができませんでした。本記事では、3 つのエージェントのコードベースを 1 つの Kiro エージェントハーネスに統合した過程 (もちろん Kiro 自身を使って構築しました) と、私たちのビジョンを実現可能にしたアーキテクチャ上の決定について解説します。 分岐していった 3 つのハーネス Kiro を作り始めた当初、私たちはスピードと実験を優先しました。各クライアントチームが独自のエージェントハーネスを作ることを推奨しました。エージェントハーネスとは、エージェントループ、ツール実行、サブエージェントへの委譲、セッション管理、設定のロード、モデルとの通信を管理するオーケストレーション層のことです。IDE チームは Code OSS の拡張モデルに合わせて TypeScript で、CLI チームはパフォーマンスを重視して Rust で、Web チームは最新のエージェント研究に近い場所に居るために Python で、それぞれ独自に構築しました。 ハーネスを分けたことで各チームは独立して素早くリリースし、イテレーションできましたが、同時にそれぞれのチームが異なる選択をすることも意味しました。セッションストレージはクライアントごとに動作が異なりました。権限システムは独立して設計されており、互換性のない構文を使っていました。CLI は正規表現ベースの allowedCommands / deniedCommands を使い、IDE は trustedCommands にプレフィックスマッチを、denylist にはサブストリングマッチを使っていました。コンパクション戦略も分岐しました。サブエージェントのコンテキスト共有も異なるモデルに従っていました。カスタムエージェントもクライアントごとに動作が違いました。機能セットも分裂しました。仕様駆動開発と powers は IDE のみで動作し、プランモードとコードインテリジェンスは CLI のみで動作していました。 実装コストは時間とともに複利で膨らみました。新しい機能は 3 回作って 3 回保守する必要があり、その結果としてエージェントの挙動がわずかに異なることもありました。バグも 3 回修正する必要がありました。ユーザーはどのクライアントを選ぶかによって不整合を体験することになりました。セッションがクライアントとコンピュートを横断して移動するという私たちのビジョンは、共有のセッションフォーマット、共有のツールセット、共有の設定モデルが存在しないためアーキテクチャ的に不可能でした。各チームの独立性と個別のスピードを維持するために、クライアント間でエージェントの振る舞いに関する契約を合意し、3 つのハーネスそれぞれで実装するという案も検討しました。しかしインターフェースの整合を取ることも、新機能ごとに増えていく調整コストを生みます。新機能ごとに仕様書、3 つの実装、そして同一の振る舞いを継続的に検証する作業が必要になるのです。 転機となったのは、Web 版 Kiro のパブリックローンチの準備を進めていたときでした。Web 版 Kiro を独自のエージェントとともにローンチし、この複利的な実装コストを払い続けるのではなく、各チームが学んだベストな知見を組み合わせた単一のエージェントハーネスを構築することを決めました。単一のハーネスであればチーム間の重複がなくなり、すべての労力を 1 箇所に集中投資できます。 Kiro エージェントハーネスのアーキテクチャ 私たちが早い段階で下した重要なアーキテクチャ判断は、ハーネスを各クライアントにコンパイルして組み込むライブラリではなく、独立したサーバープロセスとして構築することでした。過去の試みから、共有ライブラリでは十分に強い境界を強制できないことがわかっていました。クライアントコードは公開を意図していない内部メソッドを呼び出し始めるか、ライブラリの上に独自のエージェントロジックを重ねてしまいます。そうなれば実装は再び分岐していきます。独立したプロセスであれば、この分離が現実のものになります。ハーネスとクライアントは同じ言語やランタイムを共有する必要がないため、各クライアントは自分のプラットフォームに適したスタックのまま留まれます。 これにより、3 つの密結合したクライアントとエージェントのペアではなく、 ┌────────────┐ ┌────────────────────────────────┐ │ Kiro IDE ├──────│ IDE agent (TypeScript) │ └────────────┘ └────────────────────────────────┘ ┌────────────┐ ┌────────────────────────────────┐ │ Kiro CLI ├──────│ CLI agent (Rust) │ └────────────┘ └────────────────────────────────┘ ┌────────────┐ ┌────────────────────────────────┐ │ Kiro Web ├──────│ Web agent (Python) │ └────────────┘ └────────────────────────────────┘ クライアントと単一のエージェントハーネスとの間にきれいな分離ができました。 ┌─────────────────────────┐ ┌─────────────────────────────────┐ │ Clients │ │ Kiro agent harness │ │ │ │ │ │ UX and presentation │ │ Agent loop │ │ User interaction │───protocol───│ Tools and sub-agents │ │ Platform-native tools │ │ Session state │ │ (optional overrides) │ │ MCP client │ │ │ │ Configuration and steering │ │ │ │ Permissions │ │ │ │ Telemetry │ └─────────────────────────┘ └─────────────────────────────────┘ Kiro エージェントハーネスはコードベースの隣で動作する軽量なプロセスで、高速に起動し、エージェント側のすべてを所有します。クライアントはユーザーがエージェントとどのようにやり取りするか、エージェントの作業をどのように提示するかを所有します。この境界を越える唯一の方法は、定義されたプロトコルインターフェースです。コンパイルされて組み込まれるライブラリではなく独立したプロセスであるため、あらゆるコンピュート上で動作できます。同じハーネスがラップトップ上でも、クラウド上の VM 内でも、クライアントに意識させることなく起動できます。 サーバーとクライアントの間に明確なインターフェースがあるということは、エージェントのコードがクライアントとは独立して進化することを意味します。ハーネスの変更がプロトコルインターフェースに影響を与えない場合 (たとえば新しいツールの追加、プランニングの改善、エージェントループのチューニング)、クライアント側の変更ゼロですぐにすべてのクライアントにリリースできます。たとえば最近、カスタムエージェントのライブリロード機能を追加しました。セッション中に .kiro/agents/ のファイルを編集すると、ハーネスがすぐに検知し、利用可能なコマンドをクライアントに再度通知します。利用可能なコマンドの通知タイプはすでにプロトコルに存在していたため、クライアントの変更は不要でした。どのクライアントも追加の変更なしにこの機能を手に入れられたのです。 サポート対象のクライアントが多様なため、このハーネスは画一的な設計ではありません。クライアントごとに機能が異なり、一部の操作はクライアントネイティブの機能を使ってクライアント層で実装するほうが理にかなっています。クライアントは独自のツールを提供して組み込みツールを抑制でき、自分のフォームファクター (form factor) に合ったものを使えます。たとえば IDE はファイル操作に Code OSS の API を使い、ファイルシステム上で直接動作するハーネスの組み込みツールではなく、独自のファイル読み書きツールを提供しています。エージェントがこれらのクライアント提供ツールのいずれかを実行する必要があるときは、クライアントに通知し、クライアントがツールを実行して結果を返します。 プロトコル: Agent Client Protocol (ACP) クライアントとハーネスの境界を定義するプロトコルとして、 Agent Client Protocol (ACP) を選びました。ACP はエージェントとクライアントの通信を標準化した仕様で、2026 年 6 月に 1.0 に到達しました。このプロトコルは JetBrains の IDE、Xcode、Zed といった IDE や、Obsidian、Emacs、Neovim といったほかのエディターでもサポートされています。私たちは今年の初めに Kiro CLI で ACP を採用した経験 から、これらのアプリケーション内で直接 Kiro とやり取りできるようにしていました。統一されたハーネスにも ACP を採用することにしたのは、サードパーティ製エディター向けだけでなく、Kiro 自身のクライアントと私たち自身のエージェントの間のインターフェースとして使うためです。ACP の 2 つの性質がこれを可能にしました。カスタムメソッドに対する拡張性と、トランスポートの柔軟性です。 ACP は公式にトランスポートとして stdio をサポートしています。これはハーネスがエディターやターミナルの子プロセスとして動作するローカルクライアントで機能します。Web 版 Kiro や iOS アプリのようなリモートクライアントには、別のトランスポートが必要でした。これらのクライアントがクラウドサンドボックスで動作するハーネスに接続できるように、独自の WebSocket ベースのトランスポートを追加しました。クライアントがどのトランスポートを使うかに関わらず、バイナリ、ツール、エージェントの振る舞いは同一です。 ┌─────────────────────────────────────────────────────────────┐ │ Kiro agent harness │ └──────────┬────────────────┬────────────────┬────────────────┘ │ stdio │ stdio │ WebSocket │ │ │ ┌──────┴──────┐ ┌──────┴─────┐ ┌───────┴──────────────┐ │ Kiro CLI │ │ Kiro IDE │ │ Kiro Web · iOS app │ │ (terminal) │ │ (Code OSS) │ │ (browser · mobile) │ └─────────────┘ └────────────┘ └──────────────────────┘ トランスポートを超えて、私たちは ACP のメソッドセットを Kiro-ACP と呼ぶものに拡張しました。標準の ACP は基本的な部分 (セッションのライフサイクル、メッセージのストリーミング、ツール呼び出しのレポート) を扱いますが、Kiro の機能にはそれ以上のものが必要でした。たとえばライブステアリングを追加しました。ユーザーはエージェントの作業中でもメッセージを送信でき、そのメッセージが次の推論ターンで注入されることで、キャンセルや待機なしにエージェントの方向性を調整できます。ACP はメッセージのキューイングをサポートしていないため、ライブステアリングを実現するために新しいメソッドプロパティと通知で ACP を拡張しました。また Kiro の仕様駆動開発ワークフローを専用のメソッド群としてモデル化し、ACP の基本的なツール承認を豊富なマルチスコープの権限システムへと拡張し、コンテキストウィンドウの使用状況とフック実行に関する通知を追加しました。合計で Kiro-ACP はベースプロトコルに加えて 20 を超えるエージェント呼び出し可能なメソッド、15 のクライアント呼び出し可能なメソッド、20 の通知タイプを追加しています。ACP の拡張モデルはこれをきれいに保ちます。仕様どおり、カスタムメソッドはアンダースコアのプレフィックスを使い、Kiro の拡張はすべて _kiro/ 名前空間の下に配置されています。プロトコルをフォークすることなく、Kiro 固有の機能のために拡張できるのです。 結果として、サードパーティのクライアントはファーストパーティのクライアントと同じ方法で接続できます。ACP 互換のクライアントであれば、ツール、サブエージェント、セッション管理、MCP 接続を含む完全なエージェントを利用できます。ファーストパーティのクライアント (IDE、CLI、Web、iOS) は加えて Kiro-ACP の拡張を利用して、ライブステアリング、仕様、リッチな権限 UI、コンテキスト使用量トラッキングといった機能を提供します。 仕様、エージェント、フックがどこでも使える 単一のハーネスがもたらす直接的なメリットは、これまで 1 つのクライアントに閉じ込められていた機能が、同じ設定フォーマットと同じ振る舞いで、どのクライアントでも使えるようになったことです。 仕様駆動開発 は以前は IDE 限定でした。今では CLI ( /spec new で開始できます) と Web 版 Kiro でも動作します。エージェントは仕様ワークフローを駆動する LLM とのやり取りと自動化された推論 (要件の生成、技術設計の作成、作業のタスクへの分解) を扱い、各クライアントは自分のフォームファクターに合った形でそれを提示します。IDE は仕様のアーティファクトを横並びのペインで表示します。CLI はターミナル内でレンダリングします。Web 版 Kiro はブラウザーでインラインレビューとマルチユーザーコラボレーションとともに表示するので、チームが一緒に仕様をイテレーションできます。エージェントは ACP を話し、クライアントは出力をどう提示するかを決めます。 カスタムエージェント は、どのクライアントでも同じ .kiro/agents/ Markdown フォーマットを使います。エージェントには説明、システムプロンプト、タグベースのツール選択 (個別のツール名ではなく read 、 write 、 shell といったシンプルなタグ)、アクセス可能なサブエージェント、インラインの MCP サーバー定義、インラインの権限ルールを定義できます。カスタムエージェントの設定をバージョン管理にコミットすれば、チームメンバー全員がすべてのクライアントで使えるようになります。 --- description: セキュリティ上の問題を確認するコードレビューエージェント tools: [read, shell, "@github"] permissions: rules: - capability: fs_read effect: allow - capability: shell match: ["git diff *", "git log *", "npm audit"] effect: allow mcpServers: github: url: https://api.githubcopilot.com/mcp/ headers: Authorization: Bearer ${GITHUB_TOKEN} --- あなたはセキュリティに重点を置いたコードレビュアーです。現在の差分を レビューし、脆弱性、認証情報の漏洩、安全でないパターンを確認してください。 依存関係のアドバイザリは npm audit で確認してください。 フック は同じ .kiro/hooks/*.json フォーマットを使い、同じトリガー ( SessionStart 、 PreToolUse 、 PostToolUse 、 FileCreate 、 FileSave ) で、すべてのクライアントで同じように動作します。 機能の可用性を超えて、統一されたハーネスは、正しく作るのが難しい領域でも一貫した振る舞いを提供します。コンテキスト管理、コンパクション、要約は、どのクライアントを使ってもすべて同じように動作します。以前はハーネスごとに独自のコンパクション戦略を持っていたため、IDE、CLI、Web クライアントのどれを使っているかによってセッションが長くなるにつれて振る舞いが変わることがありました。今では 1 箇所で実装、テスト、改善される単一の実装があります。統一されたハーネスをクライアント全体に展開して以来、コンテキスト保持を改善するため、ハーネスにより良いコンパクションプロンプトをすでにリリースしています。またハーネスの深い部分でレジリエンスとパフォーマンスの改善もリリースしました。モデル推論リクエストの改善されたリトライロジック、高速な権限評価、より弾力性のある MCP サーバー接続などです。すべてのクライアントがこれらの変更の恩恵を受けます。結果として、どのクライアントを好むかに関わらず、一貫した品質と信頼性が得られます。 単一のポリシー言語 統一ハーネスが登場する前、各クライアントは異なる構文、異なるセマンティクス、異なる設定場所を持つ独自の権限システムを持っていました。CLI は正規表現パターンによる allowedCommands / deniedCommands を使いました。IDE はプレフィックスマッチによる trustedCommands と、サブストリングマッチによる別の commandDenylist を使いました。どちらのクライアントでも権限はツール単位でした。 .env への読み取りを拒否する といった単一の意図は、ファイルを読める各ツール (read、glob、grep、コードインテリジェンス) に対して個別に設定する必要があります。1 つでも見落とすと、エージェントは別のツール経由でそのファイルにアクセスできてしまうのです。ユーザーはツール呼び出しごとに y を押し続けるか、すべてを信頼するかの二択を迫られ、その中間の実用的な選択肢がありませんでした。私たちが求めていたのは、ケイパビリティレベルで意図を表現でき、永続的かつ組み合わせ可能な同意によって承認疲れ (acceptance fatigue) を減らせる権限モデルでした。 今では、形式的に検証されたポリシー言語である Cedar に支えられた、単一のケイパビリティベースの権限モデルがあります。1 つのルールで、すべてのツールにまたがる同種の操作をまとめて対象にできます。 rules: # Block all tools that read files from accessing secrets - capability: fs_read match: [".env", ".env.*", "secrets/**", "**/*.pem"] effect: deny # Allow specific shell commands without prompting - capability: shell match: ["npm test *", "npm run build", "git status"] effect: allow # Allow an MCP server's tools - capability: mcp match: ["github/*"] effect: allow ケイパビリティはツールを機能ごとにグループ化します。 fs_read 、 fs_write 、 shell 、 web_fetch 、 mcp 、 subagent などです。fs_read の deny は、ファイルを読むすべてのツール ( read_file 、 grep_search 、 file_search 、そして今後追加される read 系ツール) を個別に列挙することなくブロックします。 ポリシーは複数のスコープにまたがって合成でき、deny が常に勝つセマンティクスでマージされます。Kiro 自体は変更不可能なセキュリティ不変条件を適用します (たとえば、エージェントは自身の権限ファイルを変更できません)。エンタープライズ管理者は MDM 経由で制限をプッシュできます。ユーザーは自分のルールをユーザーレベルまたはワークスペースレベルで設定します。エージェントプロファイルはその役割に応じた権限を宣言できます。セッションレベルの判断は、作業しながら積み上がっていきます。事前の設定は不要です。ポリシーは同意の判断を下すにつれて自然に育っていき、意味のあるスコープでそれを永続化できます。 ハーネスがビジョンを解き放つ 新しいエージェントハーネスアーキテクチャの成果はすでに現れています。すべてのクライアントが統一ハーネスに移行して以来、クライアント側の変更ゼロで複数の機能をクライアント横断でリリースしてきました。グローバルフックとポリシープリセットもその一例です。 グローバルフック は ~/.kiro/hooks/ でフックを一度定義するだけで、すべてのワークスペースで自動的に発火するため、保存時のリント実行やコミット前のセキュリティチェックといった横断的な振る舞いをプロジェクトごとに複製する必要がなくなります。 ポリシープリセット は edit-workspace や dev-shell のような合成可能な名前付きルールセットで、一般的なワークフローにおけるプロンプト疲れ (prompt fatigue) を減らします。権限にポリシープリセットを追加すると (たとえば policies: [dev-shell, edit-workspace, read-all] )、ハーネスのポリシーエンジンがロード時にそれらを個別のルールに展開します。どちらの機能もハーネスのアップデートだけですべてのクライアントに提供されました。 本記事の冒頭で述べたビジョンには、まだ構築が必要なエージェントの能力 (ケイパビリティ) がいくつかあります。たとえば、環境間でセッションを移動するためのセッションパッケージングや、ローカルとクラウドの両方のセッションをどのクライアントからも制御できる機能などです。統一されたハーネスなら、新しい能力を一度作るだけで済みます。多くの場合、グローバルフックやポリシープリセットのように、クライアント側の変更ゼロですべてのクライアントに配信できます。統一ハーネスがクライアント側の作業を完全になくしたわけではありませんし、そうしたいわけでもありませんでした。ターミナル、デスクトップの IDE、ブラウザー、スマートフォンは異なるインタラクションモデルを持っており、私たちは画一的な体験を提供するのではなく、各クライアントがそのフォームファクターに合った体験に感じられることを望んでいます。新しいエージェントハーネスアーキテクチャなら、エージェントのロジックはクライアント全体で同一で、各クライアントチームはそれとどうやり取りするのがベストかに集中できます。 Kiro のユーザーとして、新しいエージェントハーネスアーキテクチャは、新しい能力がより速く届き、一貫した振る舞いを示し、あなたが好むクライアントに関わらず同じ設定で動作することを意味します。 新しい Kiro エージェントハーネスを試す 新しい Kiro エージェントハーネスは 4 つの Kiro クライアントすべてでライブ稼働しているので、今日から試せます。 Kiro IDE 1.0 は、ケイパビリティベースの権限、タグベースツールとインライン MCP を備えたカスタムエージェント、並列セッションを指揮するためのエージェントフォーカスモード、ドッキング可能なチャットタブ、セッションエクスポートを提供します。 IDE 1.0 のドキュメントと移行方法 を参照してください。 Kiro CLI v3 (アーリーアクセス) は、仕様駆動開発、permissions.yaml、拡張されたフック、新しいエージェント設定フォーマットを備え、ターミナルで同じ統一ハーネスを実行します。 kiro-cli --v3 で試せます。 CLI v3 のドキュメントと移行方法 を参照してください。 Web 版 Kiro (プレビュー) はクラウドサンドボックスでハーネスを実行し、ブラウザーで仕様を使った自律的な開発、マルチリポジトリセッション、GitHub と GitLab の統合を提供します。 サインイン / サインアップ できます。 iOS 版 Kiro (プレビュー) は Web 版 Kiro と同じクラウドセッションにスマートフォンから接続し、ラップトップを開かずに自律的な作業のキックオフ、差分のレビュー、変更の承認を行えます。 アーリーアクセスをリクエスト してください。 翻訳は Solutions Architect の吉村が担当いたしました。

動画

該当するコンテンツが見つかりませんでした

書籍