---
license: "MIT. Translation of the Hermes Agent documentation, Copyright (c) 2025 Nous Research. See https://wiki.winsmux.dev/hermes/licenses.txt"
title: "パッケージ管理"
description: "PM のツール固定、Python 環境、オプションの依存関係、インストールの所有者"
upstream_path: reference/package-management.md
upstream_blob: 1a2e7d333615c931617a0d7f61a322e7d8222683
sources:
  - https://hermes-agent.nousresearch.com/docs/reference/package-management
---

# パッケージ管理 {#package-management}

`hermes pm` は、Hermes が使うツールのバイナリと Python の依存環境を管理します。
アプリ本体を更新する仕組みではありません。Hermes 自体を更新するときは、インストール方法に合った
[更新方法](/hermes/docs/getting-started/updating/)を使ってください。

## 固定バージョン、インストール済みの状態、実行時の選択 {#pins-installed-state-and-runtime-selection}

ファイルごとに役割が分かれています。

| ファイル | 役割 |
|---|---|
| `pm/lock.json` | 管理対象ツールの正確なバージョン、ターゲットごとの URL、SHA-256 ハッシュ。 |
| `pm/pyproject.toml` と `pm/uv.lock` | 依存マネージャー自身が使う、アプリとは独立した Python の要件と、ロック済みの解決結果。 |
| `pyproject.toml` と `uv.lock` | Python の要件、extras、プラットフォームマーカー、コミット済みの Python の解決結果。 |
| ツールストアの `facts.json` | インストール済みツールのエントリ、その識別情報、環境変数のエクスポート、展開済みファイルのダイジェスト。 |
| インストールごとの `facts.json` | 選択中の Python 環境、その入力スタンプ、有効な extras。 |
| ペイロードの `manifest.json` | ペイロードの相対的な配置と、バンドルビルダーが確定させた起動の取り決め。 |
| `install-stamp.json` | ビルドの来歴と、宣言された配布・更新の所有者。 |

ロックファイルにエントリがあっても、そのパッケージがインストールされている証拠にはなりません。`hermes pm doctor`
はインストール済みの状態をロックと突き合わせ、展開済みのバイト列を検査します。
起動時にはもっと軽い検査を使います。起動のたびに上流のバージョンを問い合わせることはしません。
自分で管理するソースインストールでは、インポート前のランチャーが、PM が記録した
依存関係の同期成功スタンプを現在の入力と比べます。完了状態が無いか古ければ同期が走り、
そのあと同じコマンドが、アプリの依存関係を読み込む前に管理下の Python で再起動します。
同期に失敗した場合は以前の選択が残り、次回の起動で再試行します。保留中の更新を示すマーカーは要りません。
開発用のチェックアウトとパッケージ版のインストールは、それぞれ既存の所有者を保ちます。

過去の版の更新処理は、ソースツリーを置き換えたあとも古い Python コードを実行し続けることがあります。
互換用のエントリポイントは新しい子プロセスを起動し、その完了を待って、
終了ステータスを返します。子プロセスのブートストラップは、アプリのインポートより前に、
必要なツールの用意と Python の世代の選択を PM に依頼します。完了処理は、
更新のコンテキストと受領記録を持ったまま、そのインタープリターで動きます。親プロセスは
`sys.modules` を消去せず、新しいアプリのインポートグラフを読み込まず、pip によるフォールバックも再開しません。

現行のソース更新は、選択したチェックアウトを新しい完了処理の所有者へ引き渡します。
そのブートストラップ用 Python は、site-packages の初期化を無効にしてから、
記録済みの extras と有効なプラグインの同期を PM に依頼します。その後は選択された Python が、
フロントエンドのビルド、プロファイルと設定の保守、ゲートウェイの再起動、実行時の
検証を担います。Git、すでに最新の状態での再試行、ZIP のフォールバックもこの同じ経路を通ります。
元のコマンドは待っているあいだ更新ロックを保持します。完了結果が無いか失敗していれば、
成功とは報告できません。関連する PM の失敗は更新の受領記録に残り、
中断された再起動は、稼働中のプロセス全体を再起動する義務を引き継ぎます。
依存関係やビルドの失敗を、pip やソースの再ダウンロードで再試行することはありません。
依存ファイルが壊れたときは `hermes pm repair` を使ってください。開発者向けの
[ソース更新の完了処理の所有者に関する注記](/hermes/docs/developer-guide/source-update-completion/)も参照してください。

## ソースインストールとパッケージ版ビルド {#source-installs-and-packaged-builds}

ソース版のインストーラーは、必要なツールと Python を用意します。Python の extras は
`all` を選びます。名前付きのオプションツールは、指定されたときにインストールされます。

正規のソースインストールでは、Desktop が公開済みの
インストール用ランチャーを確認して実行します。そのインタープリターと依存関係の選択は PM が持ちます。Desktop
がこのコマンドを、推測した `venv` のパスに置き換えることはありません。開発者が上書き指定した場合は、
その選んだインタープリターが保たれます。

ネイティブのデスクトップバンドルは、パッケージ化の前に、対応するツール一式と、ターゲットで使えるすべての
Python extras を配置します。`--extra all` と `--all-extras` は
同じ意味ではありません。ターゲットで動かない依存関係は、引き続きプラットフォームマーカーで除外されます。

完全なデスクトップビルダーは、PM を Node とネイティブのパッケージ化の仕組みと組み合わせて動かします。
リリースタグのクリーンなチェックアウトから `python scripts/bundles/desktop.py --tag vX.Y.Z`
を実行すると、依存関係を用意してインストーラーをビルドします。準備だけで止めたいときは `--prepare-only` を付けます。
そのジョブ内の結果は、あとから
`python scripts/bundles/desktop.py --prepared .build/desktop-job/prepared.json` で使えます。
`--work` と `--cache` は、ビルドが所有する別々のルートを指定します。作業ディレクトリを作るのは
呼び出し側ではなく準備処理です。`--commit` を使えば、タグの代わりに完全なコミット SHA を指定できます。
その場合、チェックアウトがそのコミットと一致している必要があります。

準備処理では、分離された PM の状態、固定されたツール、パスに結び付いた新しい Python
環境、JS ワークスペースの全体、ネイティブバインディング、パッケージ化用の
ユーティリティを使います。再利用できる依存関係のキャッシュは、稼働中のインストールでも、持ち運べる
仮想環境でもありません。準備済みの結果はソース、ターゲット、パスに結び付きます。
入力が欠けていたり変わっていたりすると、ダウンロードを始めるのではなく、利用そのものが失敗します。
移動したり入力が変わったりしたら、準備をやり直してください。署名と公証では引き続き
ネットワークを使うことがあります。ネイティブコンパイラーの要件とリリース検証の限界については
[デスクトップのビルドガイド](https://github.com/NousResearch/hermes-agent/blob/main/apps/desktop/BUILDING.md)
を参照してください。

パッケージ版アプリの基本ペイロードは変更できません。Hermes はバックエンドを
そのペイロードから動かします。初回起動時にソースのチェックアウトをコピーすることはしません。
バンドルビルダーはファイルを検査し、起動パスをデスクトップの
ビルドスタンプへ書き込みます。Electron はそのパスを使い、ペイロードを探し回ったり修復したりはしません。
追加の固定ツールは、書き込み可能なツールストアを使えます。Python の追加分には、
署名済みパッケージの外にある、書き込み可能な完全な環境を使います。その最初の世代は、
同梱の extras を新しい要件と一緒に引き継ぎます。以降の世代は、
記録された extras の選択を基準にします。

Termux は別の bionic 向けビルドと、封をした APT パッケージを使います。Docker は
実行環境をイメージに焼き込み、必要時の依存関係インストールを無効にしています。Nix
は derivation を通じて実行環境を提供します。それぞれの制約は
[Termux](/hermes/docs/getting-started/termux/)、[Docker](/hermes/docs/user-guide/docker/)、
[Nix](/hermes/docs/getting-started/nix-setup/) の各ガイドを参照してください。

## 書き込み可能な状態 {#writable-state}

プラットフォームの既定のデータルートは、POSIX では `~/.hermes`、
Windows では `%LOCALAPPDATA%\hermes` です。`HERMES_HOME` とプロファイルによって、
プロセスが使うデータルートは変わることがあります。

| 状態 | 既定の場所 |
|---|---|
| 共有の書き込み可能なツールエントリ | 解決された既定の Hermes ルート配下の `tools/`。 |
| 再開可能なダウンロード | 同じルート配下の `cache/partials/`。署名済みペイロードの中には置きません。 |
| インストールごとの選択とジャーナル | 依存関係の状態ルート配下の `installs/INSTALL_KEY/`。 |
| Python の世代 | `installs/INSTALL_KEY/environments/`。 |
| 同期と更新の受領記録 | 有効なホーム配下の `logs/update_receipts/`。 |

インストールキーは、正規のソースまたはペイロードのリポジトリパスから導かれます。
そのため、チェックアウトが別なら Python の選択も別になります。1つのインストールを共有するプロファイルは、
同じ環境に依存関係を追加できます。
ただし設定と認証情報は、プロファイルごとに分かれたままです。

facts や世代のパスは手で編集しないでください。ランチャーは、サードパーティのインポートより前に
選択中の環境を解決します。プロセスは再起動するまで、すでにインポートしたものを
使い続けます。ガベージコレクションは、選択中の世代と、読み手が生きている
リース管理下の世代を残します。

ダウンロードは、部分ファイルの URL ごとに1つのロックを共有します。失敗または一時停止した転送が
部分的な保存先を公開することはなく、ガベージコレクションが進行中の
転送のファイルを消すこともありません。再開時に既存の範囲を再利用するのは、記録された長さ、
バリデーター、任意のハッシュがまだ一致する場合だけです。強い ETag か固定された
ハッシュが無い場合、中断した転送は、別のバージョンを混ぜないよう最初からやり直します。
小さな `.locks/` ファイルは完了後も残ります。待っているプロセスが
同じロックを使えるようにするためです。

## オプションの Python 依存関係とプラグイン {#optional-python-dependencies-and-plugins}

組み込み機能は、`pm.ensure_import` を通じてプロジェクトの extra を要求します。
ディレクトリ型のプラグインは、Python の要件を `pyproject.toml` で宣言します。
作者が書いたプロジェクトファイルが無い場合、PM は `plugin.yaml` または `plugin.yml` にある旧形式の `pip_dependencies` と
`python_dependencies` のリストを合わせて使います。PM が以前に生成した
古いプロジェクトファイルが、これらのリストより優先されることはありません。同意の確認、依存関係に
含まれるかどうか、最新かどうかの検査は、すべて同じ宣言の読み取り処理を使います。

PM は、コアの要件、有効な extras、有効なプラグインの要件を
まとめて用意します。解決は既存のロックを起点にします。互換性のある推移的依存の
バージョンは変わることがありますが、宣言された制約と厳密な固定は守られます。
候補ごとに、ソース、ロックの起点、用意する環境の入力を明示した
新しいワークスペースが作られます。生成されたワークスペースと拡張したロックは、
配布されるソースの外に置かれます。修復では、編集された稼働中のマニフェストに対して解決し直すのではなく、
記録済みのワークスペースとロックを、プラグインのビルド入力も含めてコピーします。

プラグインの有効化と、段階的に配置するコードの更新は、分離された
PM ワーカーへデータとして渡されます。ワーカーはインストールロックの下で、提案された依存関係の
全体を把握し、候補を検証してから、設定やプラグインのファイルと
メタデータを、環境の選択と一緒に公開します。準備中に変わった入力は
拒否します。永続的なジャーナルがあるので、アプリのインポートより前に復旧できます。
新しい環境を必要としない、コードだけの更新も同様です。

パックの有効化を含むプラグインの選択の変更も、同じ受け入れトランザクションを使います。
PM は変更を1つ適用するたびに、その前に共有ロックの下で最新の選択を読み込みます。
候補が失敗しても、選択中の環境が置き換わったり、ほかのプラグインが
黙って無効になったりはしません。準備が成功しても、稼働中の Hermes プロセスでは、
新しい環境を有効にするために再起動が必要なことがあります。

通常の Hermes アプリの更新では、ユーザーのプラグインディレクトリは保たれます。
プラグインを明示的に更新すると、対象のプラグインのファイルが変わることがあります。Python の
依存関係の宣言を持たないラッパーは、共有環境には加わりません。その外部の
サイドカーは、別の所有者が管理したままです。
[プラグインガイド](/hermes/docs/developer-guide/plugins/)を参照してください。

### 必要時インストールのポリシー {#lazy-install-policy}

`security.allow_lazy_installs` は、必要になったときのインストールを制御します。この設定が false でも、
すでにインストール済みの依存関係はそのまま使えます。

```bash
hermes config set security.allow_lazy_installs false
```

明示的なインストールコマンドは、必要時のインストールとは別物です。ただし
必要時インストールが無効な場合でも、バンドルの固定された機能リストは、要求できる Python の extra 名を
引き続き制限します。プラグインの明示的な受け入れは別の
操作で、必要時の機能要求ではありません。この設定を、
サンドボックスや、手動でのパッケージインストールの全面禁止として扱わないでください。
Docker はさらに、イメージ内で内部用の必要時インストール無効化フラグを設定しています。

PM は依存マネージャーであって、プラグインのコードを閉じ込めるサンドボックスではありません。プラグインをインストールするには、
そのプラグインと依存関係を信頼する必要があります。

## オプションのセキュリティツール {#optional-security-tools}

固定版の `bws` と `iron-proxy` パッケージは、PM が
`pm/security_packages.py` で管理します。そのバージョン、成果物の URL、SHA-256 ハッシュは
`pm/lock.json` から取ります。ダウンロードと公開には共有のツールストアを使い、
`$HERMES_HOME/bin` 配下の個別のインストーラーは使いません。

iron-proxy については、PM は固定された署名ファイルも取得し、
リリースのチェックサムが固定されたアーカイブを含んでいるかを確かめます。パッケージの配置時には、
連携先の署名チェッカーを呼び出します。GPG による検査は、
実行ファイルがある場合に限って行われます。ロックされた来歴ファイルは引き続き存在し、
ハッシュが一致していなければなりません。署名が明示的に拒否された場合は、インストールを中止します。
外部の実行ファイルは、PM のハッシュと署名の保証の対象外です。

`bws` と iron-proxy は、PM の選択を確認する前に、`PATH` 上の実行ファイルを優先します。
必要時のインストールは PM のポリシーに従います。明示的なインストールコマンドは、
`--force` 付きの要求も含めて、管理対象のエントリを検査し修復します。

## 開発者のワークフロー {#developer-workflow}

アクティベーションは、ソースのチェックアウト用のツールチェーンの準備または同期を PM に依頼し、
それをシェルで使えるようにします。エディターの Python
インタープリターを選んだり、インストール済みのデスクトップアプリをこのチェックアウトへ向け直したりはしません。

### チェックアウトを準備する {#prepare-a-checkout}

パッケージ版の Hermes アプリの外で、通常のターミナルを使ってください。既存の
Python 仮想環境に入っている場合は、先に抜けておきます。Windows では、Git を入れたネイティブの PowerShell を使います。
ARM64 では、チェックアウトから依存関係をビルドするたびに、その前に PM が Visual Studio C++ ツール、Clang、ネイティブの Rust、静的
OpenSSL 開発ライブラリを用意します。
セットアップ、`activate.ps1`、`install.ps1`、`hermes update`、修復のいずれでも同じです。
既存のインストールは再利用し、足りない前提条件をインストールします。足りない
Visual Studio コンポーネントには管理者権限が必要です。対話的なインストールでは
UAC のプロンプトで確認しますが、CI、ssh、スケジュール実行では
管理者の PowerShell が必要です。OpenSSL には
vcpkg の `arm64-windows-static-md` トリプレットを使います。共有のインストールが壊れている場合は、
自動で削除するのではなく、修復を促すエラーを出します。コンパイラーと OpenSSL の
環境変数は PM の依存関係ビルドにだけ適用され、利用者のシェルには決して反映されません。

ほかのプラットフォームでは、互換性のある wheel が無い依存関係のために、
ネイティブのコンパイラーツールとライブラリが引き続き必要です。

固定版の macOS 用 Python では、PM は `AR` の既定値を `/usr/bin/ar` にします。配布されている
インタープリターの sysconfig が、提供元の一時的な LLVM ディレクトリを指したままになっているためです。
これはソースビルドとバンドルビルドの両方に当てはまります。`AR` と `CC` を明示した場合はその値が
優先されます。PM は、Nix の Python のように呼び出し側が用意したインタープリターの
ツールチェーンは変えません。現在の固定版では、`CC` の既定値は必要ありません。

依存関係を準備する前に、リポジトリをクローンしてブランチを選んでください。

```bash
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
```

開発環境を分離したい場合は、最初の PM コマンドより前に、別のデータホームを
選んでください。このチェックアウトに戻ってくるときも、同じ値を使います。

Bash では、リポジトリのルートで次を実行します。

```bash
export HERMES_HOME="$HOME/hermes-dev-data"
export HERMES_RUNTIME_DIR="$HERMES_HOME/tools"
source ./activate
```

PowerShell では、リポジトリのルートで次を実行します。

```powershell
$env:HERMES_HOME = Join-Path $HOME 'hermes-dev-data'
$env:HERMES_RUNTIME_DIR = Join-Path $env:HERMES_HOME 'tools'
. .\activate.ps1
```

この例の `HERMES_RUNTIME_DIR` は、そのプロセスの中だけで効く開発用の上書き設定です。
これによって、ブートストラップと PM が同じ書き込み可能なストアを使います。インストール済みの MSIX や macOS のバンドルに、
このパスを永続的に設定しないでください。アクティベーションは、セットアップスクリプトの
実行環境だけを扱う経路を動かし、ツールを用意して Python の extra `all` を同期します。
`dev` は選ばず、JS ワークスペースもインストールしません。
インストール内のコマンドを保守し、所有している既存の PATH ラッパーを修復しますが、新しい PATH
の便利機能を作ったり、アプリの設定を読み込んだりはしません。セットアップのうち、利用者向けの
インストール作業、つまりシェルの設定、`.env`、同梱のスキルも省きます。
そうした完全なインストール手順が必要なら、セットアップスクリプトを別に実行してください。

Python がまだ無い段階では、シェルのブートストラップが固定版のインタープリターを取得します。
Python が動くようになると、依存関係の作業を PM に引き渡します。PM の内部エンジンは、
アプリの依存関係を解決する前に、自分用の小さなロック済み実行環境を用意します。
そのプロジェクトはアプリのワークスペースから独立しています。アプリの依存関係が壊れていても、
依存マネージャーの起動を妨げてはならないからです。

uv は PM の内部の実装の詳細です。アプリのコード、セットアップの処理、
ビルドの呼び出し側は Python の操作を要求するのであって、uv の実行ファイルやコマンド引数を要求するのではありません。
Hermes の環境を、素の pip や uv コマンドで書き換えないでください。

PM の実行環境に入っているのは `ruamel.yaml`、`packaging`、`tomli-w`、`truststore` で、アプリの
依存関係ツリーではありません。CLI コマンドと、アプリが要求するインストールや修復は
そこで動きます。読み取りだけのパスやインストール済みツールの参照は、その場で処理されます。環境が
最新かどうかの検査には、準備済みの PM ワーカーを使います。PM が、すでに動いているエージェントの
インポートに自分の依存関係を足すことはありません。ファーストパーティの YAML の
読み書きには ruamel を使います。サードパーティのパッケージは、引き続き
アプリの環境で PyYAML を必要とすることがあります。失敗の受領記録は標準ライブラリだけで書かれます。

PM の CLI とワーカーは、HTTPS クライアントをインポートする前に `truststore` を有効にします。
これにより、ブートストラップ用 Python に組み込まれた
OpenSSL のパスで証明書ストアが見つからない場合でも、プラットフォームの証明書ストアを使えます。アプリの依存関係や証明書パスの
上書き設定は必要ありません。最初のインストールのあと、PM は次の呼び出しで、自分の小さな環境を
管理下の Python に合わせて作り直します。それ以降の呼び出しでは、その環境を再利用します。

`pm.venv_is_current()` は、必要時インストールが無効でも、
既存の PM ワーカーを通じて検査します。確認のためだけに PM をブートストラップすることはありません。マネージャーの
実行環境が使えない場合は、ツールや依存関係をダウンロードせずに
false を返します。先に PM を用意するには、`hermes pm install` を明示的に実行してください。

ネイティブバンドルと Docker イメージは、共有の実行環境ビルダーを通じて、この同じ PM ロックを配置します。
Termux は、検証済みのオフライン wheelhouse をそのビルダーに渡します。
Nix は PM ロックを別の derivation としてビルドします。パッケージ版のワーカーが使うのは、
記録された PM の依存関係ディレクトリだけで、アプリのライブラリは決して使いません。

### 既存のインストールをアクティベートする {#activate-an-existing-installation}

新しいシェルを開くたびに、開発用ホームの値を戻してチェックアウトに入ります。
そのうえでアクティベートします。別途覚えておくべきセットアップコマンドはありません。

| シェル | 入る | 抜ける |
|---|---|---|
| Bash | `source ./activate` | `deactivate` |
| fish | `source ./activate.fish` | `deactivate` |
| PowerShell | `. .\activate.ps1` | `deactivate` |

PowerShell では、先頭のドットとスペースが必須です。
ドットソースせずに `.\activate.ps1` を実行しても、同じセッションのスコープにはなりません。
`activate` は Bash の構文を使っています。この手順では `sh` ではなく Bash を使ってください。
Zsh の起動ファイルが Bash と同じ意味で動くとも考えないでください。fish には専用の
`activate.fish` があり、同じように動きます。

アクティベートのたびに PM のインストールと同期の経路が呼ばれ、全エントリを再ハッシュする代わりに、
記録済みのツールのダイジェストを信頼します。それでも PM は、足りないツールをインストールし、
古くなった依存関係の世代を作り直します。意図的に実行するインストールでは、バイト列の
検査を残します。展開済みのバイト列を再検査するには、`python -m pm.cli install` か `hermes update` を実行してください。
セットアップが失敗した場合は、アクティベート済みのシェル環境を変える前に
エラーを返します。すでにアクティブな環境で再度 source した場合も同じです。

同期のあと、アクティベーションはインストール済みの PM ツールを `PATH` の先頭に追加し、
`PYTHONPATH` をこのチェックアウトとその選択中の依存関係ツリーに設定します。
さらに、このワークツリー用のシェル関数として `hermes` を定義します。この関数は
このチェックアウトの CLI を実行し、MSIX のエイリアスを含む、インストール済みのコマンドを隠します。
動くのはシェルがこのワークツリーの中にいるあいだだけで、外では実行を拒否します。
そのため、隣のワークツリーがこのコマンドを引き継ぐことはありません。プロンプトには
ブランチ名を示すプレフィックスが付き、ツリーの外に出ると外れます。
OS 全体の PATH は変えず、通常の venv 式のプロンプトも入れません。
別の venv の中で入れ子にせず、きれいなシェルから始めてください。
`deactivate` は、アクティベーションスクリプトが記録した環境変数の値を元に戻し、
関数とプロンプトのプレフィックスを取り除きます。
パッケージをアンインストールしたり、自分で起動したプロセスを止めたりはしません。

シェルをアクティベートせずに、その環境で1つのコマンドやスクリプトだけを実行するには、
先頭に `scripts/run-in-hermes-env` を付けます。同じ環境をそのコマンドにだけ適用し、
引き継げる環境がない場合や、引き継いだ環境が古くなっている場合は先に同期します。シェル自体には手を付けません。
`scripts/run_tests.sh` はこの方法で自分自身を実行し直し、リポジトリの Python スクリプトは
shebang から自分自身をこのコマンドに渡します。

```bash
scripts/run-in-hermes-env python scripts/release.py --help
```

作業を始める前に、インタープリターとソースを確認してください。

```bash
python -c "import sys, pm; print(sys.executable); print(pm.__file__)"
python -c "import httpx; print(httpx.__file__)"
node --version
npm --version
hermes --version
```

`python` は PM ストアのインタープリターを指していなければなりません。`pm.__file__` は
このチェックアウトの中を指している必要があります。依存関係は選択中の環境から読み込まれ、その環境は
リポジトリの外にあることもあります。インポートに失敗する場合は、`source ./activate` 自体が成功していても、
セットアップか選択に手当てが必要です。

### このソースツリーで作業する {#work-on-this-source-tree}

シェルがこのワークツリーの中にいるあいだ、`hermes` はこのワークツリーの CLI です。
ワークツリーの外では関数が実行を拒否するので、別のチェックアウトのツリーを動かしたり、
インストール済みのコマンドに流れたりすることはありません。

```bash
hermes setup
hermes
hermes --tui
python -m pm.cli status
```

これらのコマンドは、選んだ開発用ホームを使います。ソースファイルを編集すると、
次に起動するプロセスからその内容が反映されます。編集後は、影響を受ける CLI、ゲートウェイ、バックエンドを再起動してください。
Python のソースだけを変えた場合、依存関係をすべて入れ直す必要はありません。

JavaScript のワークスペースは、リポジトリのルートで `npm ci` を一度実行してから、
該当するワークスペースのコマンドを実行します。たとえば次のとおりです。

```bash
npm run build --workspace ui-tui
npm run dev --workspace apps/desktop
```

Web サイトは別扱いです。`npm ci --prefix website` を実行してから、
`npm run build:fast --prefix website` を実行します。PM のアクティベーションが提供するのはツールで、これらの
`node_modules` ディレクトリやビルド済みの成果物は含みません。ネイティブのデスクトップビルドには追加の
要件があり、[デスクトップのビルドガイド](https://github.com/NousResearch/hermes-agent/blob/main/apps/desktop/BUILDING.md)にまとまっています。

### ブランチを変えずに依存関係を更新する {#refresh-dependencies-without-changing-branches}

ブランチやロックファイルが変わったら、アクティベーションスクリプトをもう一度 source して、
新しい依存関係を同期・選択します（Bash では `source ./activate`、PowerShell では
`. .\activate.ps1`）。シェルをアクティベートせずに同期だけしたい場合は、次を実行します。

```bash
python -m pm.cli install
```

単独で同期したあとは、環境をアクティベートし直し、影響を受けるプロセスを再起動してください。
ツールの診断には `python -m pm.cli doctor`、最新の同期の受領記録の確認には `python -m pm.cli status`
を使います。機能ブランチを更新するためだけに `hermes update` を実行しないでください。
これはアプリの更新であり、ソースのブランチを変えることがあります。

管理対象のツール名と Python の extra 名は、別のインターフェースです。

```bash
python -m pm.cli install chromium
python -c "from pm import sync_venv; sync_venv(['anthropic'], explicit=True)"
```

1つ目のコマンドはツールをインストールします。2つ目は、宣言済みの実行時 extra を、
このインストールの既存の Python の選択に追加します。extras は PM の
同期を通じて積み重なります。`dev` と `test` の依存関係グループは、別のテスト用
環境だけに属し、選択中のアプリの venv には入りません。extras を変えたら、
別の Python プロセスを起動する前にアクティベートし直してください。

### pyproject.toml を編集したあとの同期 {#syncing-after-you-edit-pyprojecttoml}

1. `pyproject.toml` を編集します。すべての依存関係を、
   [Dependency Pinning Policy](https://github.com/NousResearch/hermes-agent/blob/main/pm/AGENTS.md#dependency-pinning-policy)
   の要求どおりに固定します。プラットフォームの制限は PEP 508 のマーカーで表すか、extra 全体を
   `[tool.hermes.extras-platforms]` で制限します。
2. ロックし直します。

   ```bash
   hermes pm lock
   ```

   これは、CI が検査するのと同じ設定で、`pyproject.toml` から `uv.lock` を解決し直します。
   3 日間の `exclude-newer` による公開からの経過日数の検査も含みます。環境は一切変えません。ロックがすでに最新なら、
   その旨を表示して何も書き込みません。（`hermes pm lock --bump NAME VERSION` は別の操作で、
   管理対象ツールを `pm/lock.json` で固定するものです。`uv.lock` には触れません。）
3. アクティベーションスクリプトをもう一度 source して（`source ./activate`、PowerShell では
   `. .\activate.ps1`）、アプリの venv とテスト用
   インタープリターを新しいロックに同期します。アクティベーションは `[all]` を対象にします。`[all]` に含まれない
   オプトインの extra を追加した場合は、`hermes pm lock` がそれをテスト用インタープリターにも入れる
   コマンドを表示します。たとえば
   `source ./activate --test-extras all,NAME` です。
4. `pyproject.toml` と `uv.lock` を一緒にコミットします。

JS の依存関係は、それを持つパッケージのマニフェストとロックを更新します。
PM の facts や生成されたワークスペースは編集せず、選択中の世代にパッケージを直接インストールすることもしないでください。

### テスト環境とエディター環境 {#test-and-editor-environments}

`source ./activate`（PowerShell では `. .\activate.ps1`）と、2つの直接実行用
`setup-hermes` スクリプトはどちらも、ロック済みの
`dev` と `test` の依存関係グループから、分離されたテスト用インタープリターを用意します。`scripts/run_tests.sh` はそのインタープリターを使い、
チェックアウトやその依存関係の入力が変わっていれば、アクティベートし直します。アプリの
venv、インストーラー、バンドルは、どちらのグループも選びません。開発者向けの既定は
`[all]` を対象にします。テストの対象範囲を変えるには、POSIX のアクティベーションに `--test-extras=anthropic` を、
PowerShell に `-TestExtras anthropic` を渡します。
これらの引数は、*テスト用インタープリターの中だけで*実行時 extras を選びます。

アクティベーションが使えない分離環境（たとえば Nix の
開発シェル）では、呼び出し側が pytest の入った `HERMES_PYTHON` を明示的に渡すか、
独立した使い捨ての環境をビルドできます。

```bash
python -m pm.build_env --source . --out .venv --group dev --group test
```

出力先がすでに存在していてはいけません。作り直すときは、そのプロセスを止め、
その使い捨て環境だけを意図して先に削除してください。そのあと `scripts/run_tests.sh`
を実行します（Windows では Bash 経由）。テスト用の依存関係グループには、ネイティブのランチャーの
テストが含まれ、パッケージ版の実行環境に入ることはありません。

エディターでデバッグするときは、その独立したインタープリターを選び、作業
ディレクトリをこのチェックアウトにして、スクリプトとして `hermes` を起動します。その
`HERMES_HOME` は本番用とは分けておいてください。ターミナルのアクティベーションは、すでに動いている
エディターの設定を変えません。エディターを、一時的な PM の
世代や、署名済みアプリの Python 実行ファイルに向けないでください。

### Python の操作インターフェース {#python-operation-interfaces}

Python の依存関係の作業には、公開されている `pm` モジュールを使います。

| 操作 | 担う内容 |
|---|---|
| `pm.sync_venv(extras, explicit=True)` | 有効なプラグインを含む、アプリの依存関係全体を用意して選択します。 |
| `pm.sync_venv(repair=True, explicit=True)` | 記録済みの依存関係セットを、アプリの新しい世代で再現します。 |
| `pm.build_environment(source=..., out=..., explicit=True)` | 呼び出し側が所有する新しい出力をビルドして検証します。プラグインの検出やアプリの選択は行いません。 |
| `pm.lock_project(source, explicit=True)` | 環境を選択せずに、明示したプロジェクトのロックを更新します。 |
| `pm.ensure_environment(name, requirements, explicit=True)` | 分離された依存関係の世代を用意して選択し、その Python のパスを返します。 |
| `pm.ensure_python_tool(name, requirements, executable, explicit=True)` | 分離されたツールを用意し、その実行ファイルのパスを返します。 |
| `pm.environment_python(name)` / `pm.python_tool(name, executable)` | 何もインストールせずに、選択中のパスを読み取ります。 |
| `pm.venv_is_current()` | アプリの依存関係が最新かを、準備済みの PM ワーカーに問い合わせます。マネージャーの実行環境が使えない場合は false を返します。 |

`pm.stage_manager_runtime(...)` は、ブートストラップのための例外です。PM 自身の
ロック済み実行環境を、内部エンジンを直接使って配置します。この実行環境は、自分のワーカーを通じて
自分自身をビルドできないためです。呼び出し側に uv を見せることはありません。

`pm.build_env` は、明示的なビルドとロック作業のためのコマンドラインインターフェースです。
対応するオプションは `python -m pm.build_env --help` で確認してください。既定では、プロジェクトの
ビルドはコミット済みのロックを使います。`--resolve` はビルド前に解決します。`--python`
はビルドに使うインタープリターを明示します。`--sealed` はビルド時の `.pth`
参照を取り除きます。`--offline` と `--cache` は依存関係の取得方法を制御します。

アプリの環境をビルドするには、呼び出し元の Python で PM がすでに起動できる状態になっている必要があります。
これらのビルドはインタープリターのブートストラップではありません。稼働中のアプリの
インポートを変えたり、選択中の環境を置き換えたりはしません。Nix の宣言的な uv2nix によるビルドは、
引き続き Nix が所有します。関係のないプロジェクトやエージェントの
サンドボックス向けのパッケージマネージャーのコマンドは、Hermes 自体を管理しません。

## コマンド {#commands}

```bash
hermes pm --help
hermes pm doctor
hermes pm status
hermes pm install
hermes pm install chromium
```

| コマンド | 効果 |
|---|---|
| `pm install [names...]` | 名前を指定したパッケージをインストールします。名前を指定しない場合は、必要なツールと Python を用意し、そのツールを PATH に置いてから、`all` extra を同期します。名前なしのインストールでは、既定のオプションツール（`agent-browser` と Chromium、`cua-driver`）もインストールします。これらのダウンロードに失敗しても警告が出るだけで、インストール自体は失敗しません。以前に断ったパッケージの名前を指定すると、その選択を取り消せます。 |
| `pm install --without NAME` | 既定のオプションパッケージ `NAME`（`agent-browser` か `cua-driver`）を除いて名前なしのインストールを行い、その選択を記録します。以降の名前なしのインストールと `hermes update` でも除外されます。インストーラーの `--skip-browser` / `-SkipBrowser` と `--skip-computer-use` / `-SkipComputerUse` はこれを使っています。 |
| `pm install --tools-only` | そのツール一式をインストールして PATH に置き、そこで止めます。venv の同期は行いません。 |
| `pm env [names...]` | インストール済みパッケージについて、PM が追加する環境変数の値を JSON で出力します。足りないパッケージはインストールしませんが、Hermes をコールドスタートした場合は、先に自分用の Python 実行環境を用意することがあります。 |
| `pm doctor` | インストール済みツールの識別情報、ファイル、ダイジェストをロックと照合します。 |
| `pm repair` | 記録済みの Python 依存関係セットを新しい世代で作り直し、検証してから選択します。固定バージョン、機能、プラグインの設定は更新しません。 |
| `pm status` | 最新の同期・更新の受領記録を JSON で出力します。受領記録が無ければ、その旨を表示します。 |
| `pm gc` | 参照されていないツールストアのエントリ、削除できるダウンロードの部分ファイル、使われていないリース管理下の Python の世代、そして削除されたチェックアウトの `installs/INSTALL_KEY/` の状態を削除します（対象は、まだ存在する `.worktrees/` ディレクトリから取り除かれた worktree と、データのルートの下にあるクローンです。このプロセスから見えないチェックアウト、たとえばデータのルートを共有するコンテナから見たホスト側のインストールは残します。インストールのロックや世代のリースがまだ保持されている状態も残します）。起動時に走る worktree の掃除役も、そうして孤立した状態のディレクトリを回収します。 |

`pm env` は、認証情報を含め、親プロセスから引き継いだ変数を出力しません。それでも
出力にはローカルのインストールパスが含まれることがあるので、共有する前に内容を確認してください。

### メンテナー向けコマンド {#maintainer-commands}

これらのコマンドは、依存関係の入力を変えたり、ビルドの成果物を配置したりします。
インストール済みアプリの更新の仕組みの代わりにはなりません。

| コマンド | 効果 |
|---|---|
| `pm lock` | `pyproject.toml` から `uv.lock` をロックし直します。環境は変えず、ロックが最新なら何も書き込みません。 |
| `pm lock --bump NAME VERSION` | 対応するターゲットの成果物を解決してハッシュを取り、ツールの固定版を `pm/lock.json` に書き込みます。 |
| `pm update [names...]` | 上流のバージョンを問い合わせ、ツールの固定版を変更し、変わったツールをインストールします。 |
| `pm update --check` | 書き込みをせずに問い合わせだけを行います。終了コード 1 は更新があることを意味する場合があります。エラーと区別するには出力を確認してください。 |
| `pm update --target TARGET` | 指定したターゲット向けにバージョンを解決します。 |
| `pm update --uv` / `--npm` | Python または npm の依存関係の解決結果も更新します。 |
| `pm update --termux [--check]` | ローリング方式のプールから外された termux プールのアーカイブ（ランタイムライブラリの固定表と bionic のロック行）を固定し直します。`--check` は書き込みをせずに報告し、外された固定版があれば終了コード 1 を返します。 |
| `pm install --target TARGET NAME...` | 明示したクロスターゲットのパッケージを、ホストのインストール済み実行環境として記録せずに配置します。win32 の `git` ターゲットは自己展開形式の PortableGit アーカイブに固定されています。配置するときは提供元の展開プログラムを実行するため、Windows のホストが必要です。 |
| `pm bundle --out DIR [--ref REF]` | ソースのスナップショット、ネイティブツール、facts、Python の依存関係を配置します。署名済みのデスクトップインストーラーは作りません。 |

完全なデスクトップビルダーは、JavaScript の画面もビルドし、ランチャーを生成して、
ネイティブのパッケージ化を呼び出します。メンテナーは
[Building the Desktop Installers](https://github.com/NousResearch/hermes-agent/blob/main/apps/desktop/BUILDING.md) を参照できます。

## ネットワークの再試行 {#network-retries}

PM は、ツールのダウンロード、成果物のハッシュ計算、
バージョンの参照で起きる一時的な HTTP の失敗を再試行します。1回の確認や転送につき、試行は最大4回です。待ち時間は
1秒、2秒、4秒と延びます。`Retry-After` ヘッダーがあれば、待ち時間を最大
30秒まで延ばすことがあります。再試行のたびに、原因、待ち時間、次の試行がログに記録されます。

再試行の対象になる HTTP ステータスは 408、429、500、502、503、504 です。接続のリセット、
タイムアウト、一時的な DNS の失敗、途中で途切れたレスポンス本文も再試行します。
範囲指定のダウンロードでは、受信済みのバイトを残します。範囲指定に対応していないサーバーでは、
最初から取り直す必要があります。一時停止すると待機が中断され、部分的なダウンロードは残ります。

PM は、ハッシュの不一致、証明書の失敗、ローカルのファイルシステムのエラー、その他の
恒久的な失敗は再試行しません。確認が成功したあとに範囲指定の GET が 403 や 404 を返した場合は、
CDN へのフォールバックとして、欠けている範囲を1回だけ順番に取り直します。展開、
検証、公開は繰り返しません。Python と npm のパッケージの要求は、
引き続き uv と npm それぞれの再試行ポリシーに従います。

## 公開からの経過日数とパッケージのミラー {#release-age-and-package-mirrors}

Hermes 自身が依存する Python のパッケージは、Hermes がロックする時点で公開から3日以上たっている必要があります
（uv の `exclude-newer` で、CI のロック検査が強制します）。これにより、公開されたばかりで乗っ取られているかもしれないリリースが
`uv.lock` に入り込めないようにしています。利用者はそのロックからインストールします。また、プラグインのインストールや有効化で
日付を検査し直すことはありません。そのため、
アップロード日時を公開していないパッケージのミラーでも動きます。ミラーを設定するには、`pip.conf` の `index-url`（Hermes が uv に渡します）か
`UV_INDEX_URL` を使います。

この検査を行うのは `hermes pm lock` だけです。アップロード日時のないミラーに対して実行すると、
`has no publish time` と表示して止まります。この手順では `https://pypi.org/simple` を使ってください。

## 診断 {#diagnostics}

- **Python の依存関係のビルドが遅い:** PM が逐次出力する uv コマンドでは、詳細出力が有効になっています。バンドルとビルドのログには、失敗したあとだけでなく、ビルド中にもパッケージの動きとビルドバックエンドの stdout/stderr が表示されます。
- **ツールが無い、または古い:** `hermes pm doctor` の結果を確認し、書き込み可能なインストールで PM のインストールを明示的に実行してください。
- **新しい環境には再起動が必要:** 影響を受ける Hermes のプロセスを再起動してください。稼働中のインポートに、2つ目の site-packages ツリーを足さないでください。
- **依存関係の衝突:** `hermes pm status` の結果を確認してください。受け入れを再試行する前に、プラグインの要件を直してください。
- **Python の依存関係が壊れた:** `hermes pm repair` を実行してから、Hermes を再起動してください。修復では、プラグインの設定を読み直さずに、選択中の世代に保存されたワークスペースとロックを再現します。記録が読めない、または保存されたロックが無い場合は、依存関係を減らしたセットを選ぶのではなく、失敗として終わります。世代がまだ無い場合は、同梱またはコミット済みのロックと、記録済みの機能セットを使って修復します。
- **依存関係のインストールが中断した:** 起動時に、依存関係を有効にする前に同じ PM の修復が要求されます。自動の試行回数には上限があります。`pm repair` で明示的に再試行できます。修復に失敗した場合は、以前の選択と再試行のマーカーが残ります。
- **Python の実行ファイルやアプリのソースが壊れた:** パッケージの所有者を通じて修復するか、インストールし直してください。これらのファイルが無いと PM は動けません。依存関係の修復で、署名済みペイロードのファイルが書き換えられることはありません。
- **不明なパッケージや extra:** 宣言された名前を使ってください。`pm install` が受け取るのはパッケージ名で、Python の extra 名や pip の指定ではありません。
