セッション
目次
- セッションのしくみ
- 認証されたゲートウェイでのセッションへのアクセスと記録上の帰属
- 文脈に数えられるもの
- セッションの送信元
- CLI でのセッション再開
- 直前のセッションを続ける
- 名前で再開する
- 特定のセッションを再開する
- 特定のディレクトリで再開する
- 再開すると作業ディレクトリも戻ります
- 作業場所でセッションを絞り込む
- 再開したときの会話の振り返り
- プラットフォームをまたいだ引き継ぎ
- セッションの名前付け
- 自動で付くタイトル
- 自分でタイトルを付ける
- タイトルの決まり
- 圧縮したときの自動の枝分かれ
- メッセージングプラットフォームでの /title
- セッション管理のコマンド
- セッションの一覧
- セッションの書き出し
- セッションを消す
- セッションの名前を変える
- ゲートウェイのクラッシュで失われたターンを破棄する
- セッションを固定する
- 古いセッションを整理する
- セッションをまとめてアーカイブする
- セッションの統計
- 迷子になったゲートウェイのセッションを直す
- 傷んだ保存済みプロンプトを直す
- プロファイルをまたいで混ざった状態を直す
- ストアのジャーナルモードを WAL と DELETE の間で切り替える
- Claude Code や Codex CLI からセッションを取り込む
- セッション検索のツール
- 4 つの呼び出し方
- FTS5 の検索の書き方
- 任意の引数
- いつ使われるか
- プラットフォームごとのセッションの追い方
- ゲートウェイのセッション
- グループのセッションを共有するか分けるか
- セッションの続き方
- セッションの手入れ:それでも /new を使うべき理由
- 落ちたときや再起動したあとの続き方
- 保存場所
- データベースの構造
- セッションの期限と後片付け
- 自動の後片付け
- 大きすぎる会話記録への備え
- 手動の後片付け
Hermes Agent は、すべての会話を自動でセッションとして保存します。セッションがあるおかげで、会話の再開、セッションをまたいだ検索、会話履歴の管理ができます。
セッションのしくみ
CLI、Telegram、Discord、Slack、WhatsApp、Signal、Matrix、Teams、その他どのメッセージングプラットフォームからの会話でも、すべてメッセージ履歴を丸ごと持つセッションとして保存されます。セッションは次の場所で管理されます。
- SQLite データベース(
~/.hermes/state.db)— 構造化されたセッションの情報と FTS5 の全文検索、それにメッセージ履歴の全体
SQLite データベースには次のものが入っています。
- セッション ID、送信元プラットフォーム、ユーザー ID
- セッションのタイトル(重複しない、人が読める名前)
- モデル名と設定
- システムプロンプトのその時点の内容
- メッセージ履歴の全体(役割、本文、ツール呼び出し、ツールの結果)
- トークン数(入力・出力)
- 時刻(started_at、ended_at)
- 親セッションの ID(圧縮によってセッションが分かれたとき用)
認証されたゲートウェイでのセッションへのアクセスと記録上の帰属
実行を持っているのはゲートウェイで、クライアントが動いているエージェントを持つわけではありません。同じゲートウェイのプロファイルの、 確認済みのオペレーターは、別の認証方法で作られた正規のローカルの CLI、TUI、 Desktop のセッションにもつなげます。たとえば、ローカルの本来のオペレーターと、認証済みのダッシュボードのオペレーターが、 実行環境をもう一つ作ることなく同じ会話にアクセスできます。クライアントの接続を閉じると、 そのクライアントが外れるだけで、受け付け済みの作業はゲートウェイに残ります。
これは、確認済みのオペレーターについて「作った本人だけがアクセスできる」形を意図して置き換えたもので、 ダッシュボードにある既存のオペレーター権限はそのまま保たれます。パスワードと OAuth の身元は 区別されたままですが、どちらの接続もそのプロファイルへのオペレーター権限を持っていれば、 正規のローカルのセッションへのアクセスを分け隔てる壁にはなりません。信頼されるサーバー側の経路には、 本来の対話的な起動、認証済みのダッシュボードのチケット、 サーバーが起動した PTY のクライアントが使う内部の資格情報、そして確認済みの従来の ダッシュボードのトークンが含まれます。HTTP でのセッションの変更は、確認済みの本来の HTTP の持ち主の 許可も受け付けます。これによって、制限付きのワーカー、メッセージング、 ルーム、サービスの資格情報にオペレーター権限が与えられることはなく、プロファイルごと・操作ごとの確認がなくなることもありません。
記録上の帰属は、身元ごとに分かれたままです。ダッシュボードの身元には、提供元、 確認済みの OAuth の発行者(あれば)、主体(subject)が含まれます。作成の受領には もとの身元が残り、送信や変更のやり直しには実際に操作した身元が残ります。 オペレーターがセッションに加わっても、記録された持ち主が置き換わったり、やり直しの身元がまとめられたりはしません。 本来の起動での持ち主の鍵とセッション ID は変わりません。
受領に主体(subject)しか入っていない古いリモートのセッションは、 どの提供元が持っていたかを確かめられません。そうしたセッションは保存されたままですが、 最初にそれを求めた認証済みのアカウントに自動で割り当てられることはありません。オペレーター権限があっても、 持ち主のいない過去の記録を、リモートから早い者勝ちで引き取ることはできません。
別の端末からつなぐには、同じゲートウェイへの、対応していて認証された経路も必要です。 オペレーターのアクセスを共有しても、それだけでリモート向けの待ち受けが公開されたり、 ローカルのセッションを OpenAI 互換の API で続けられるようになったりはしません。ゲートウェイのクラッシュは、 クライアントの切断とは違います。中断された作業は自動でやり直されるのではなく unknown になり、 後ろに並んだ作業が進む前に解決が要ることがあります。
文脈に数えられるもの
Hermes は会話を再開できるようセッション履歴を保存しますが、これまで扱った すべてのバイトを毎回送り直すわけではありません。各ターンでモデルが見るのは、 選ばれたシステムプロンプト、いまの会話の窓、そしてそのターンのために Hermes が明示的に差し込んだ内容だけです。
添付されたメディアは、そのターン限りの入力として扱われます。
- 画像は、次のモデル呼び出しにそのまま添付されることもあれば、使っている
モデルが画像入力に対応していない場合はあらかじめ文章での説明に変換されます。
- 音声は、音声認識を設定していれば文字起こしされます。
- テキスト文書は抽出した文章を含められます。それ以外の種類の文書はたいてい、
保存したローカルのパスと短いメモで表されます。
- 添付ファイルのパスや、抽出・変換されたテキストは会話の記録に残りますが、
画像・音声・バイナリファイルそのもののバイト列が、その後のプロンプトへ 繰り返し複製されることはありません。
たとえば画像を送って「これでミームを作って」と頼んだ場合、Hermes はその画像を 一度だけ画像認識で確かめ、画像処理のスクリプトを走らせるかもしれません。 以降のターンが、もとの JPEG を自動的に文脈へ持ち込むことはありません。 残るのは会話に書き込まれたもの、つまり依頼の文面、短い画像の説明、 ローカルのキャッシュのパス、最後のアシスタントの応答だけです。
文脈が膨らむいちばんの原因は、メディアファイルそのものではありません。 文字数の多いテキストです。貼り付けた会話記録、ログの全文、大きなツール出力、 長い差分、繰り返される状況報告、細かい証拠の書き出し。大きな成果物を チャットへ丸ごと写すより、要約・ファイルのパス・必要な部分の抜粋・ ツールを使った参照を選んでください。
セッションの送信元
セッションには、それぞれ送信元のプラットフォームの印が付きます。
| 送信元 | 説明 |
|---|---|
cli |
対話形式の CLI(hermes または hermes chat) |
oneshot |
終わりの決まった、対話形式でない実行です。hermes chat --oneshot -q、-Q、hermes -z、そして端末に繋がっていない標準入出力での -q が該当します。TUI・デスクトップアプリ・ダッシュボードのセッション選択画面には出てきません(kanban や tool と同じ扱いです)。TUI やデスクトップアプリのセッションの中から起動した場合も同じで、その実行は起動元の環境を引き継ぎますが、その会話そのものではないからです。ただし CLI の履歴としては残ります。hermes -c や --resume latest は直前の一回きりの実行を続けますし、hermes sessions list にも出てきます。--source <tag> を明示した場合は、そちらが常に優先されます(hermes chat -q --source tui は tui として保存されます)。 |
telegram |
Telegram |
discord |
Discord のサーバーや DM |
slack |
Slack のワークスペース |
whatsapp |
|
signal |
Signal |
matrix |
Matrix のルームと DM |
mattermost |
Mattermost のチャンネル |
email |
メール(IMAP / SMTP) |
sms |
Twilio 経由の SMS |
dingtalk |
DingTalk |
feishu |
Feishu / Lark |
wecom |
WeCom(WeChat Work) |
weixin |
Weixin(個人向け WeChat) |
bluebubbles |
macOS の BlueBubbles サーバー経由の Apple iMessage |
qqbot |
公式 API v2 経由の QQ Bot(Tencent QQ) |
homeassistant |
Home Assistant のイベント(プラグイン) |
webhook |
受信した webhook |
api-server |
API サーバーへのリクエスト |
acp |
ACP のエディター連携 |
cron |
定期実行の cron |
batch |
まとめて処理する実行 |
kanban |
かんばんの割り振り役が動かすワーカー(盤の上では読めますが、セッション選択画面には出てきません) |
tool |
外部サービスとの連携(--source tool)。セッション選択画面には出てきません |
会話の途中で圧縮されたセッションは、同じ送信元のまま続きます。--source tool や oneshot の実行から生まれた圧縮後のセッションにも同じ印が付くので、選択画面に出るかどうかの扱いもそのまま引き継がれます。
CLI でのセッション再開
CLI では --continue か --resume で前の会話を再開します。
直前のセッションを続ける
# Resume the most recent CLI session
hermes --continue
hermes -c
# Or with the chat subcommand
hermes chat --continue
hermes chat -cこれは SQLite データベースからいちばん新しい cli セッションを探し、その会話履歴を丸ごと読み込みます。
端末ごとに続ける
引数なしの -c は、どの端末で動いているかを見ます。CLI のセッションは、実行中の端末(tty デバイス、tmux のペイン、kitty のウィンドウ、wezterm のペイン、Zellij のペイン、Windows Terminal のセッションなど)をキーにした小さな目印ファイルを ~/.hermes/terminal-sessions/ に置きます。*同じ*端末でもう一度 hermes -c を実行すると、Hermes はその端末自身のセッションを再開します。つまり 2 つのペインを並べていても、両方が全体でいちばん新しいセッションを取り合うのではなく、それぞれ自分の会話を続けられます。その端末の目印がない場合(初回、セッションを消したあと、30 日より古い目印)は、-c はいちばん新しいセッションを使う動きに戻ります。-c "name" と --resume はこの影響を受けません。config.yaml の session.terminal_continue: false で無効にできます。
名前で再開する
セッションにタイトルを付けていれば(後述のセッションの名前付けを参照)、名前で再開できます。
# Resume a named session
hermes -c "my project"
# If there are lineage variants (my project, my project #2, my project #3),
# this automatically resumes the most recent one
hermes -c "my project" # → resumes "my project #3"特定のセッションを再開する
# Resume a specific session by ID
hermes --resume 20250305_091523_a1b2c3d4
hermes -r 20250305_091523_a1b2c3d4
# Resume by title
hermes --resume "refactoring auth"
# Resume the most recent session — same lookup as -c
hermes --resume latest
# Or with the chat subcommand
hermes chat --resume 20250305_091523_a1b2c3d4セッション ID は CLI セッションを抜けるときに表示され、hermes sessions list でも確かめられます。
特定のディレクトリで再開する
--in <dir> を渡すと、開始または再開の前にそのディレクトリへ移動します。--resume latest(または -c)と組み合わせると、そのディレクトリの作業場所に属するいちばん新しいセッションが選ばれます。先に cd する必要も、セッション ID を覚えておく必要もありません。
# Resume the latest session that belongs to ./my-project
hermes --resume latest --in ./my-project
# Works with the TUI too
hermes --tui --resume latest --in ./my-project--in は、そのセッションをそのディレクトリに固定もします。再開したセッションに記録されていた作業ディレクトリは復元されません(--no-restore-cwd を渡したときと同じです)。
再開すると作業ディレクトリも戻ります
CLI セッションを再開すると、そのセッションに記録された作業ディレクトリ(git リポジトリのルートやプロジェクトのディレクトリ)へ cd も行われるので、会話は元の作業場所から続きます。いまの場所にとどまりたいときは --no-restore-cwd を渡します。
hermes --resume 20250305_091523_a1b2c3 --no-restore-cwd移動したことは ↪ restored workspace dir: … の行で分かります。復元に失敗しても、再開そのものが壊れることはありません。
アイドル状態のセッションを再開すると、プロファイルのいまの設定が読み込まれます。対象はツールセット、MCP サーバー、terminal の設定、max_turns、チェックポイント、既定の推論の強さです。セッションのモデル、起動時のフラグ、/reasoning や作業場所に加えた変更はそのまま残ります。違いが1つでもあるとプロンプトキャッシュの先頭部分が新しく作り直されるので、再開後の最初のターンは割高になります。terminal の設定を変えると、terminal.timeout のような関係のなさそうな項目でも、それまでの cd がセッションのディレクトリに戻されます。
作業場所でセッションを絞り込む
hermes sessions list は --workspace <needle> を受け取り、作業場所のキー(git リポジトリのルート、なければカレントディレクトリ)が一致するセッションだけを表示します。照合はパスの部分一致か、ディレクトリ名そのものの一致です。
hermes sessions list --workspace my-project
hermes sessions list --workspace ~/code/hermes-agent再開したときの会話の振り返り
セッションを再開すると、入力を求める前に、Hermes が直前までの会話の要点を整った枠の中にまとめて表示します。
*再開したときは、直近のユーザーとアシスタントのやり取りをまとめた枠を出してから、入力できる状態に戻します。*
この振り返りは次のように表示されます。
- ユーザーのメッセージ(金色の
●)とアシスタントの応答(緑の◆)を出します - 長いメッセージは切り詰めます(ユーザーは 300 文字、アシスタントは 200 文字 / 3 行)
- ツール呼び出しは、件数とツール名にまとめます(例:
[3 tool calls: terminal, web_search]) - システムメッセージ、ツールの結果、内部の思考は隠します
- 直近 10 往復を上限とし、それより前は「... N earlier messages ...」と示します
- いま進行中の会話と見分けが付くよう、淡い表示にします
この振り返りをやめて、1 行だけの簡素な表示に戻すには ~/.hermes/config.yaml に次を書きます。
display:
resume_display: minimal # default: fullプラットフォームをまたいだ引き継ぎ
CLI のセッションで /handoff <platform> を使うと、進行中の会話をメッセージングプラットフォームのホームチャンネルへ移せます。エージェントは CLI で止まったところからそのまま続けます。セッション ID も同じ、役割付きの会話記録もツール呼び出しもすべて引き継がれます。
# Inside a CLI session
/handoff telegramこのとき起きることは次のとおりです。
- CLI が、
<platform>が有効でホームチャンネルが設定済みかを確かめます(設定は移動先のチャットで一度/sethomeを実行します)。 - CLI はセッションを引き継ぎ待ちにして、ゲートウェイの応答を待ちます。エージェントがターンの途中なら断られるので、いまの応答が終わるのを待ってください。
- ゲートウェイの監視役が引き継ぎを引き受け、移動先のアダプターに新しいスレッドを作らせます。
- Telegram — 新しいフォーラムのトピックを開きます(ボットの持ち主が BotFather で Threaded Mode を有効にしていれば DM のトピック、そうでなければフォーラム型スーパーグループのトピック)。
- Discord — ホームのテキストチャンネルの下に、1440 分で自動アーカイブされるスレッドを作ります。
- Slack — 起点となるメッセージを投稿し、その
tsをスレッドの軸にします。 - Matrix — 起点となるメッセージを投稿し、そのイベント ID をスレッドの軸にします(
m.threadの関連付け)。 - WhatsApp / Signal / SMS — スレッドのしくみがないので、ホームチャンネルへ直接送ります。
- ゲートウェイは移動先のキーを、いまの CLI のセッション ID に結び直し、エージェントに確認と要約を求める合成のユーザーターンを作ります。その返答が新しいスレッドに届きます。
- ゲートウェイが成功を知らせると、CLI は
/resumeの使い方を示して静かに終了します。
↻ Handoff complete. The session is now active on telegram.
Resume it on this CLI later with: /resume my-session-title- これ以降、会話はそのプラットフォーム側にあります。新しいスレッドで返信してください。そのチャンネルで許可された人は同じセッションを共有し、あとから実際のユーザーがスレッドへ書き込んでも自然に合流できます。スレッドのセッションは
user_idを含めずにキーを作るからです。
CLI へ戻す: デスクトップへ戻りたくなったら、/resume <title>(シェルからなら hermes -r "<title>")を実行すれば、プラットフォーム側で止まったところから続けられます。
うまくいかない場合:
- ホームチャンネルが未設定 → CLI が
/sethomeを促して断ります。 - ゲートウェイが動いていない(誰も要求を引き受けない) → CLI が 60 秒で分かりやすいメッセージとともに待つのをやめ、CLI のセッションはそのまま残ります。
- 移送に時間がかかる場合: ゲートウェイが引き継ぎを引き受けたあと、実際のエージェントのターンとしてセッション全体を流し直すため、長いセッションでは数分かかることがあります。CLI は「Still transferring...」の合図を出しながら最大 15 分待ちます。時間のかかる移送を「ゲートウェイが動いていない」と誤って報告することはありません。
- スレッドの作成に失敗する(権限不足、Topics モードが無効) → ホームチャンネルへ直接送る形になり、引き継ぎ自体は完了します。スレッドで分けられないだけです。
adapter.sendが失敗する(流量制限、一時的な API のエラー) → 引き継ぎは理由付きで失敗として記録されます。行は消えるので、もう一度試せます。
知っておきたい制限: スレッドに対応していないプラットフォームで、ホームチャンネルが複数人のグループになっている場合、合成のターンは DM 形式のセッションとしてキーが作られます。自分だけの DM をホームチャンネルにする一般的な使い方では問題ありませんが、本当に共有しているグループチャットには向きません。スレッドが使えるのは Telegram / Discord / Slack / Matrix で、これがほとんどの場合に当たるため、この制限に触れることはまずありません。
セッションの名前付け
セッションに人が読めるタイトルを付けておくと、探すのも再開するのも楽になります。
自動で付くタイトル
Hermes は最初のやり取りのあと、セッションごとに短い説明的なタイトル(3〜7 語)を自動で作ります。これは軽い補助モデルを使ってバックグラウンドで動くので、待ち時間は増えません。hermes sessions list や hermes sessions browse でセッションを眺めると、自動で付いたタイトルが見えます。
自動のタイトル付けはセッションごとに一度だけ動き、自分でタイトルを付けていた場合は飛ばされます。
自分でタイトルを付ける
チャットのセッション(CLI でもゲートウェイでも)の中で /title コマンドを使います。
/title my research projectタイトルはその場で反映されます。まだデータベースにセッションが作られていない場合(最初のメッセージを送る前に /title を実行した場合など)は、順番待ちにしてセッションの開始時に反映します。
既存のセッションはコマンドラインからも名前を変えられます。
hermes sessions rename 20250305_091523_a1b2c3d4 "refactoring auth module"タイトルの決まり
- 重複しない — 同じタイトルのセッションを 2 つ作ることはできません
- 最大 100 文字 — 一覧の表示を読みやすく保つためです
- 無害化される — 制御文字、幅ゼロの文字、書字方向の上書きは自動で取り除かれます
- 普通の Unicode は問題なし — 絵文字、日本語や中国語の文字、アクセント付き文字はどれも使えます
圧縮したときの自動の枝分かれ
セッションの文脈が圧縮されると(/compress で手動、または自動)、Hermes は続きのセッションを新しく作ります。もとのセッションにタイトルがあれば、新しいセッションには番号付きのタイトルが自動で付きます。
"my project" → "my project #2" → "my project #3"名前で再開すると(hermes -c "my project")、その系列でいちばん新しいセッションが自動で選ばれます。
メッセージングプラットフォームでの /title
/title コマンドは、ゲートウェイのすべてのプラットフォーム(Telegram、Discord、Slack、WhatsApp)で使えます。
/title My Research— セッションのタイトルを設定します/title— いまのタイトルを表示します
セッション管理のコマンド
Hermes には hermes sessions として、セッションを管理するコマンドがひととおりそろっています。
セッションの一覧
# List recent sessions (default: last 20)
hermes sessions list
# Filter by platform
hermes sessions list --source telegram
# Show more sessions
hermes sessions list --limit 50セッションが --limit の件数より多いときは、一覧の最後に … more not shown (use --limit N to see more) という行が付きます。件数で切った一覧を、全件の一覧と取り違えずに済みます。
セッションにタイトルが付いていると、タイトル・冒頭の抜粋・相対的な時刻が表示されます。
Title Preview Last Active ID
────────────────────────────────────────────────────────────────────────────────────────────────
refactoring auth Help me refactor the auth module please 2h ago 20250305_091523_a
my project #3 Can you check the test failures? yesterday 20250304_143022_e
— What's the weather in Las Vegas? 3d ago 20250303_101500_fどのセッションにもタイトルがない場合は、簡素な形になります。
Preview Last Active Src ID
──────────────────────────────────────────────────────────────────────────────────────
Help me refactor the auth module please 2h ago cli 20250305_091523_a
What's the weather in Las Vegas? 3d ago tele 20250303_101500_fセッションの書き出し
hermes sessions export は、書き出しのすべての形式をまとめて扱う入口で、--format で選びます。
| 形式 | 出力 | 向いている用途 |
|---|---|---|
jsonl(既定) |
セッションごとに JSON オブジェクト 1 つ | バックアップ、機械での読み書き |
md / qmd |
セッションごとに Markdown / Quarto のファイル 1 つ + 目録 | 読める形での保管、メモ |
html |
単体で完結する 1 ページ(複数セッションなら横に一覧が付きます) | 共有、閲覧 |
trace |
Claude Code の JSONL | HF Agent Trace Viewer、--upload |
さらに --only user-prompts を付けると、プロンプトだけを見る形にできます(jsonl か md)。
どの形式でも選び方の指定は共通です。1 つのセッションなら --session-id、まとめて扱うなら prune / archive と同じ絞り込み一式が使えます。--older-than / --newer-than / --before / --after(5h・2d・1w のような期間、数字だけなら日数、または ISO 形式の時刻)、--source、--title、--model、--provider、--cwd、--min/--max-messages、--min/--max-tokens、--min/--max-cost、--min/--max-tool-calls、--user、--chat-id、--chat-type、--branch、--end-reason です。--dry-run は書き出さずに対象だけを確かめます。--redact は、どの形式でも書き出す内容から秘密の値(API キー、トークン、認証情報)を伏せます。誰かに渡す予定のものには必ず付けてください。なお、まとめて扱う絞り込みが対象にするのは*終了した*セッションです。絞り込みなしの export は、動いているものも含めてすべてを書き出します。
JSONL(既定)
# Export all sessions to a JSONL file
hermes sessions export backup.jsonl
# Export sessions from a specific platform
hermes sessions export telegram-history.jsonl --source telegram
# Export a single session
hermes sessions export session.jsonl --session-id 20250305_091523_a1b2c3d4
# Point at a directory (existing, or ending in /) and the file is named for you:
# ~/exports/hermes_session_20250305_091523_a1b2c3d4.jsonl
hermes sessions export ~/exports/ --session-id 20250305_091523_a1b2c3d4
# Redact API keys/tokens/credentials from the exported content
hermes sessions export backup.jsonl --redact書き出したファイルは 1 行が 1 つの JSON オブジェクトで、セッションの情報一式と、保存されているすべてのメッセージが入っています。各メッセージには active/compacted の印が付いています。その場での圧縮でアーカイブされたターンや、巻き戻しや編集で取り除かれたメッセージも含まれます。このファイルを取り込むと(ダッシュボードのセッション取り込み)、それらの行はアーカイブされた履歴として戻り、モデルが使う現在の文脈としては戻りません。/save json のスナップショット(CLI、メッセージング、TUI、Desktop)にも同じ行が入ります。バックアップには、そのセッションにかつて含まれていたものが全部入っていると考えてください。会話を人に渡すときは、表示用の形式(--format md か html。セッションで表示される履歴だけが入ります)で --redact を付けて書き出してください。セッションごとのバックアップはメモリ上で組み立てるので、保存されている行が sessions.max_export_messages より多いセッションは断られます(大きすぎる会話記録への備えを参照)。
絞り込んで書き出すときは、条件に合う固定済みのセッションやアーカイブ済みのセッションも含まれます。固定は自動整理から守るためのもので、バックアップから外すためのものではありません。明示した --session-id が見つからない場合、書き出しは 0 以外の終了コードで終わり、出力ファイルは作られません。
各レコードには、メッセージの時刻から組み立てた timings のまとまりも入っています。これがあるので、バグ報告に添付された書き出しを読む人は、モデルの応答を長く 1 回待ったのか、ツールとの小さな往復がたくさんあったのかを、手で組み立て直さずに見分けられます。中身は ID、役割、件数、所要時間だけで(wall_clock_ms、largest_gap_ms、role_counts、tool_calls_emitted、メッセージごとの intervals)、プロンプトの文面、ツールの引数や結果は一切含みません。そのため --redact を付けてもそのまま残ります。Hermes はモデルやツールの所要時間を計るストップウォッチを保存していないので、complete は常に false です。時刻付きのメッセージがないセッションでは available が false になり、unavailable_reason にその理由が入ります。このまとまりは書き出しのたびに作り直され、取り込みのときは無視されます(サイズの上限にも数えません)。
HTML
--format html は、外部に依存しない単体で完結した HTML ファイルを 1 つ書き出します。メッセージは吹き出し風に整えられ、ツールの出力は折りたたまれ、複数セッションを書き出したときは切り替え用の一覧が横に付きます。
# One session as a standalone HTML page
hermes sessions export --format html --session-id 20250305_091523_a1b2c3d4 transcript.html
# All Telegram sessions from the last week in one file, secrets redacted
hermes sessions export --format html --newer-than 1w --source telegram --redact archive.htmlプロンプトだけ
--only user-prompts は、自分が書いたプロンプトだけを書き出します。アシスタントの返答、ツールの出力、システム側の文脈は含みません。プロンプトを貯めておきたいときや、何を頼んだかを見直すときに便利です。
# One JSONL record per prompt (session id, index, timestamp, text)
hermes sessions export prompts.jsonl --session-id 20250305_091523_a1b2c3d4 --only user-prompts
# Markdown, straight to stdout
hermes sessions export - --session-id 20250305_091523_a1b2c3d4 --only user-prompts --format md--format jsonl(既定)と md で使え、まとめて書き出すときの絞り込みも同じように効き、--redact とも組み合わせられます。
トレース(HF Agent Trace Viewer)
--format trace は Claude Code の JSONL を出します。これは Hugging Face Hub が Agent Trace Viewer 用に自動で見分ける形式です。手元に書き出すこともできますし、--upload を付ければ自分の非公開の hermes-traces データセットへ送れます(HF_TOKEN を読みます)。
# Trace of the most recent session, to stdout
hermes sessions export --format trace
# One session to a local trace file
hermes sessions export --format trace --session-id 20250305_091523_a1b2c3d4 trace.jsonl
# Upload straight to your private HF traces dataset
hermes sessions export --format trace --session-id 20250305_091523_a1b2c3d4 --uploadトレースの書き出しは、既定で秘密の値を伏せます(端末の外へ出ていく前提のものだからです)。自分で中身を確かめたうえで --no-redact を付ければ、伏せずに出せます。--upload は --public を付けない限り非公開です。絞り込みを付けてまとめて書き出すと、セッションごとに <id>.trace.jsonl が作られます。
Markdown / QMD
古いセッションを隠したり消したりする前に、読める形でファイルに残しておきたいときは --format md か --format qmd を使います。Markdown / QMD の書き出しは、セッションごとに 1 ファイルをディレクトリ(既定は ~/.hermes/session-exports)へ書きます。
# Export one session to Markdown
hermes sessions export --format md --session-id 20250305_091523_a1b2c3d4
# Export a compression lineage as one logical document
hermes sessions export --format md --session-id 20250305_091523_a1b2c3d4 --lineage logical
# Preview ended sessions older than 90 days without writing files
hermes sessions export --format md --older-than 90 --dry-run
# Export ended Telegram sessions older than 2 weeks to QMD files
hermes sessions export --format qmd --older-than 2w --source telegram
# Export long Claude sessions, secrets redacted
hermes sessions export --format md --model sonnet --min-messages 50 --redact
# Only after verification, export and delete one explicitly named session
hermes sessions export --format md --session-id 20250305_091523_a1b2c3d4 --delete-after-verified --yesMarkdown / QMD の書き出しは、書き出したセッションごとに .md または .qmd を 1 ファイル作り、加えてファイルのパス・メッセージ数・系列の ID・SHA-256 を記した manifest.jsonl を作ります。まとめて書き出すには絞り込みが少なくとも 1 つ必要で、条件なしのまとめ書き出しは断られます。--delete-after-verified は意図的に --session-id のときだけに限られ、--yes も必要です。親セッションを消すと、その委任先や下位エージェントのセッションも消えるため、このモードでは委任先を 1 つずつ別ファイルに書き出して確かめてから削除に進みます。Markdown / QMD のファイルには、そのセッションで表示される履歴がすべて入ります。その場での圧縮によってアーカイブされたターンも含まれます。削除の際は、削除を実行するのと同じデータベースのトランザクションの中で、その表示用の記録そのものと委任先の顔ぶれをもう一度照らし合わせます。その間に追記・書き換え・巻き戻し・圧縮・委任先の変化が 1 つでもあれば、削除は行われません。この表示履歴の決まりは、--format html、--only user-prompts(Markdown と JSONL のどちらで出力する場合も)、/save md|html にも同じく当てはまります。一方、セッション全体の JSON / JSONL の書き出し(--only を付けない hermes sessions export)と /save json(CLI、メッセージング、TUI、Desktop)は、アーカイブ済みの行も含めて、保存されているすべての行のバックアップです(セッションを書き出すを参照)。--redact は、書き出す前にメッセージ本文とツールの出力から秘密の値(API キー、トークン、認証情報)を伏せます。誰かに渡す予定の書き出しには必ず付けてください。
セッションを消す
# Delete a specific session (with confirmation)
hermes sessions delete 20250305_091523_a1b2c3d4
# Delete without confirmation
hermes sessions delete 20250305_091523_a1b2c3d4 --yes動いているチャットで開いたままのセッションを削除しても、そのチャットは止まりません。次の保存のときに、メモリ上の会話記録を丸ごと使って、同じ ID でセッションが作り直されます。セッションを消したいなら、先にチャットを閉じてください。
ターンを実行している最中や圧縮している最中にセッションを削除しようとすると、断られます(終了コード 1 で終わります)。動いているエージェントの下で会話記録が失われるのを防ぐためです。実行中のターンや圧縮が終わるのを待ってから削除してください。
セッションの名前を変える
# Set or change a session's title
hermes sessions rename 20250305_091523_a1b2c3d4 "debugging auth flow"
# Multi-word titles don't need quotes in the CLI
hermes sessions rename 20250305_091523_a1b2c3d4 debugging auth flowそのタイトルを別のセッションが使っている場合は、エラーが表示されます。
ゲートウェイのクラッシュで失われたターンを破棄する
ゲートウェイがターンの途中で止まると、そのターンの結果は分からなくなり、繰り返し実行されることもありません。確認するまで、 そのターンがセッションをふさぎます。対話的な hermes chat --resume <id> はそれを一覧に出し、 /discard <admission_id> を受け付けます。スクリプトからの hermes chat --resume <id> -q は終了コード 3 で断り、何も送りません。 スクリプトから片付けるには、次のようにします。
# Acknowledge every unknown (lost) turn on the session, then continue it
hermes sessions discard 20250305_091523_a1b2c3d4 --yes
hermes chat --resume 20250305_091523_a1b2c3d4 -q "next question"
# Only one specific admission (repeatable); the session may also be named by title
hermes sessions discard "debugging auth flow" --admission a9b59ad3ee914d75967def2a33435c88 --yes--yes がないとコマンドは確認を求め、標準入力が端末でないときは断ります(終了コード 2)。 失われた入力は記録に残ります。その操作の一部はすでに実行されているかもしれないので、送り直す前に その影響を確かめてください。後ろに並んでいた入力は、破棄したあとに実行されます。
セッションを固定する
固定すると「残す」という印が付きます。固定したセッションは sessions.auto_archive による自動整理の対象外になり、常に一覧に出ます。 これは Desktop の横一覧の Pinned で使われるのと同じ印なので、どちらで 固定しても両方に反映されます。
セッションの書き出しを復元するとき(ダッシュボードでの取り込みや、取り残された セッションをプロファイルが引き取るとき)は、固定・アーカイブ・非表示の印と、 そのアーカイブが sessions.auto_archive の整理によるものかどうかが保たれます。 復元した固定済みのセッションは引き続き保持期間の後片付けの対象外になり、 引き取った Bot Mode のチャットは非表示のままです。整理でアーカイブされたものを 復元した場合も、再開すれば元に戻ります。これらの印ができる前の書き出しは、 固定なし・表示ありの普通のセッションとして復元されます。
# Pin one or more sessions (unique ID prefixes work)
hermes sessions pin 20250305_091523_a1b2c3d4
hermes sessions pin 20250305 20250306
# Remove the pin
hermes sessions unpin 20250305_091523_a1b2c3d4
# List pinned sessions
hermes sessions pinned
# Machine-readable output, e.g. for a nightly backup of your pin set
hermes sessions pinned --json > pinned-sessions.json古いセッションを整理する
# Delete ended sessions inactive for 90 days (default)
hermes sessions prune
# Custom age threshold — bare numbers are days
hermes sessions prune --older-than 30
# Durations work too: 5h, 30m, 2d, 1w
hermes sessions prune --older-than 12h
# Delete only a specific time window (e.g. a batch of test sessions
# created in the last 5 hours)
hermes sessions prune --newer-than 5h
# Explicit window with absolute timestamps
hermes sessions prune --after "2026-07-05 09:00" --before "2026-07-05 14:30"
# Only prune sessions from a specific platform (all ages — any filter
# disables the implicit 90-day default)
hermes sessions prune --source telegram
hermes sessions prune --source cron --older-than 60 # add a time flag to narrow
# More filters — all AND together
hermes sessions prune --newer-than 5h --title "smoke test" # title substring
hermes sessions prune --older-than 30 --max-messages 3 # tiny sessions
hermes sessions prune --cwd ~/scratch --end-reason done # by cwd / end reason
hermes sessions prune --model gpt-5 --older-than 1w # by model (substring)
hermes sessions prune --provider openrouter --older-than 60 # by billing provider
hermes sessions prune --branch feature/old-experiment # by git branch
hermes sessions prune --user 12345678 --chat-type group # by messaging origin
hermes sessions prune --max-tokens 500 --older-than 7 # by token usage
hermes sessions prune --max-cost 0.01 --max-tool-calls 0 # cheap, tool-less runs
# Preview what would be deleted, without deleting anything
hermes sessions prune --newer-than 5h --dry-run
# Skip confirmation
hermes sessions prune --older-than 30 --yes時間の指定(--older-than、--newer-than、--before、--after)には、 期間(5h、30m、2d、1w)、日数だけの数字、または ISO 形式の時刻 (2026-07-05、2026-07-05 14:30)を渡せます。--older-than と --before が 上限、--newer-than と --after が下限を決めます。 --older-than / --newer-than の組は最後のメッセージの時刻を見ます (メッセージのないセッションではセッションの開始時刻を使います)。 --before / --after は必ずセッションの開始時刻を見ます。どちらの組も、 2 つ合わせれば期間として使えます。
属性での絞り込みは次のとおりです。--source(プラットフォーム、完全一致)、 --title / --model / --branch(大文字小文字を区別しない部分一致)、 --provider(課金の提供元、完全一致)、--end-reason、--user、--chat-id、 --chat-type(完全一致)、--cwd(パスの先頭一致)、それに数値の範囲として --min/--max-messages、--min/--max-tokens(入力 + 出力)、 --min/--max-cost(米ドル。実績値があればそれ、なければ見積り)、 --min/--max-tool-calls。何か 1 つでも絞り込みを使うと、暗黙の 90 日の既定は 効かなくなるので、hermes sessions prune --source cron や --model gpt-4o は すべての期間が対象になります。狭めたいときは時間の指定を足してください。 90 日の区切りが残るのは、何も付けない hermes sessions prune だけです。 --yes を付けない実行では、確認を求める前に、一致した件数といちばん古い セッション・いちばん新しいセッションが表示されます。
アーカイブ済みのセッションは既定で対象外です。まとめて消したいときは --include-archived を渡します。
セッションをまとめてアーカイブする
消さずに一覧から外したいだけなら、hermes sessions archive が使えます。 prune と同じ絞り込みを受け取り、一致したセッションをそっと隠します (Desktop やダッシュボードの画面から 1 件ずつアーカイブするのと同じ印を 付けるだけで、メッセージも検索も残ります)。
# Archive everything from the last 5 hours (e.g. 75 CI smoke-test sessions)
hermes sessions archive --newer-than 5h
# Archive by title substring, preview first
hermes sessions archive --title "dry run" --dry-run
hermes sessions archive --title "dry run" --yesアーカイブの対象は、既定では終了したセッションです。Desktop など、ゲートウェイが 持つローカルのセッションは「終了」にならないので、コマンドは条件に合ったのに 開いたままのため飛ばしたセッションの数を知らせます。それらもアーカイブするには --include-open を付けます(prune が開いているセッションを消すことはありません)。
hermes sessions archive --title "Review Hermes" --include-open --yes絞り込みは少なくとも 1 つ必要です。条件なしの hermes sessions archive は、 履歴の全体をアーカイブすることを断ります。圧縮された会話は、いま生きている先端を 通してひとまとまりとしてアーカイブされます。古い圧縮の区切りだけが単独で古さの 条件に当てはまることはないので、まだ使っている会話が、履歴が長いというだけで 見えなくなることはありません。アーカイブしたセッションは hermes sessions list と /resume から見えなくなりますが、データベースには 残っていて、Desktop やダッシュボードのセッション一覧から戻せます。
sessions.auto_archive による、しばらく使っていないセッションの一掃で隠れた会話は、 また動き出せば自然に戻ってきます。再開したときや、新しいやり取りで圧縮されて 新しい続きになったときです。自分でアーカイブした会話(サイドバー、API、 hermes sessions archive)は、戻すまでアーカイブされたままです。
セッションの統計
hermes sessions stats出力は次のようになります。
Total sessions: 142
Total messages: 3847
cli: 89 sessions
telegram: 38 sessions
discord: 15 sessions
Database size: 12.4 MBトークンの使用量、費用の見積り、ツールごとの内訳、使い方の傾向といったもっと踏み込んだ分析には hermes insights を使います。
迷子になったゲートウェイのセッションを直す
再起動のあとにゲートウェイの会話が「時間をさかのぼる」ように見えたら ——最近のやり取りがなかったかのように何日も前の話題を続けたら—— その会話は、行き先の情報を失ったセッションの行に取り残されているかもしれません (v0.21 のセッション継続性の改修で直された種類の問題です。いまの版は そもそも起きない作りになっていて、動作中に自分で直します)。
hermes sessions repair-routing は、メッセージを持つのに行き先の情報がない セッションの行を見つけ、それぞれを続きであるはずの会話へつなぎ直します。 ただし、根拠に迷いがないときだけです。
# Report only — shows each orphan, the proposed adoption, and the evidence
hermes sessions repair-routing
# Perform the adoptions (stop the gateway first — a running gateway holds
# the old routing in memory and would write it back over the repair)
hermes sessions repair-routing --apply
# Widen/narrow the contiguity window (default 900 seconds)
hermes sessions repair-routing --max-gap-seconds 300根拠として認めるのは次の 2 つです。
- 系列 — 迷子の行の
parent_session_idが、同じプラットフォームの
行き先付きの行を指している(記録された事実なので、時間の窓は関係ありません)
- 前後の連続性 — 同じプラットフォームで行き先付きの行がちょうど 1 つだけ、
迷子の行が始まった時刻の窓の中で静かになっている
あいまいなもの(候補となる先行の行が 2 つある、2 つの迷子が同じ先行の行を 指している)は理由付きで報告するだけで、手は付けません。つなぎ先を間違えると、 ある会話を別のチャットへ継ぎ足してしまうからです。置き換えられた行は superseded_by_repair として退役するので、再起動時の復旧でよみがえることは ありません。
この修復はあえて自動ではありません。そのチャットにすでに 2 本目の履歴が できている場合、どちらの流れの続きにするかを決めるのはあなたです。取り残された 会話はどちらにしても /resume とセッション検索から読めます。修復が変えるのは 行き先だけです。先にバックアップを取ってください (cp ~/.hermes/state.db ~/.hermes/state.db.bak)。
傷んだ保存済みプロンプトを直す
#122822 の影響を受ける古いビルドでは、ゲートウェイの定期の手入れやゲートウェイの /compress が、 切り離された保守用エージェントの、ツールを絞ったシステムプロンプトを、 動いているセッションの上に保存してしまうことがありました。PR #122825 の根本修正を入れたあとは、 hermes sessions repair-prompts で、すでに傷んでいる行を探せます。
この走査は慎重です。修復を提案するのは、保存されたプロンプトに ## Skill Safety の案内がなく、しかも保存されている tools[] の固定に skill_manage(これがあれば必ずその案内が出ます)が含まれているときだけです。読める固定が ない行や、memory だけの固定(これは正当な toolsets: [memory] の設定でもあります)の行は、 確かめられないものとして報告され、この走査では変更されません。必要なら SESSION_ID を指定してはっきり消してください。 memory だけの行も、ひとりでに直せる状態になります。セッションを再開すると、その tools[] の固定がツール全体を固定し直すので、そのあとの走査では Skill Safety の案内がないまま skill_manage があることが分かり、消されます。
# Report verified candidates and unverifiable rows; writes nothing
hermes sessions repair-prompts
# Clear verified degraded prompts after confirmation
hermes sessions repair-prompts --apply
# Machine-readable report
hermes sessions repair-prompts --json
# Non-interactive automation: apply and report the ids actually cleared
hermes sessions repair-prompts --apply --json
# Explicit destructive override for one session (id or unique prefix).
# This clears the stored prompt even when it is healthy.
hermes sessions repair-prompts SESSION_ID --applyプロンプトを消すと、わざと NULL が保存されます。次のターンで健全な中身が作り直されて保存されるので、 修復したセッションごとに、予想どおりの Stored system prompt ... is null; rebuilding from scratch という警告が 1 回ずつ出ます。 この警告は明示的に修復した結果であって、新たに壊れた証拠ではありません。
修復は、#122822 の根本修正が入ってから行ってください。そうでないと、あとの 保守用の圧縮で、その行がまた傷むことがあります。
動いているゲートウェイは、キャッシュしている各セッションの古いプロンプトをメモリに持っているので、 修復した行を反映させるには、--apply のあとにゲートウェイを再起動してください(hermes gateway restart)。
プロファイルをまたいで混ざった状態を直す
プロファイルは 1 つにつき state.db を 1 つ持ち、ゲートウェイのセッション キーには、その会話を持っているプロファイルの名前が入ります(既定の プロファイルなら agent:main:…、名前付きなら agent:<name>:…)。古い版では この 2 つが食い違ったまま残ることがありました。名前付きプロファイルの行が 既定のストアに書かれている、子セッションが別のプロファイルの行を引き継いで いる、ルーティングの行が違うストアにコピーされている、Telegram のトピックや /voice の設定がボットのプロファイル抜きで保存されている、といった具合です。 今の版は新しい状態を正しい場所に置きます。すでに混ざっているものは hermes sessions repair-profiles で片を付けます。
# Report only — every store is scanned, nothing is written
hermes sessions repair-profiles
# Perform the repairs (stop the gateway first; a snapshot of every store is taken)
hermes sessions repair-profiles --apply
# Machine-readable report
hermes sessions repair-profiles --json何を見つけて、何をするか。
| 見つかるもの | 直し方 |
|---|---|
profile_name が、その行自身のセッションキーと食い違っている |
キーに合わせて付け直します |
| 別のプロファイルのストアに置かれている行 | メッセージごと、持ち主のプロファイルのストアへ移します |
parent_session_id が別のプロファイルの行を指している |
つながりを切ります。その行自身の素性はそのまま残します |
| (多重化しているときに)既定のストアの外にあるルーティングの行 | 既定のストアへ移します。そこにすでに行があれば、そちらを残します |
すでに無いプロファイルのルーティングの行や sessions.json の項目 |
削除します |
| ボットのプロファイルが抜けている Telegram のトピックの結び付けと、音声モードの項目 | そのチャットを持っているセッションから付け直します |
報告はするものの、どちらなのかを教えないかぎり直さないものが 2 つあります。 存在しないプロファイルにひも付いた行(そのプロファイルを作るか、hermes profile migrate-identity <old> <new> を使ってください)と、名前付き プロファイルのストアの中にある agent:main:… の行です。後者は、そのプロ ファイル用にゲートウェイが単独で動いていたころの履歴(--legacy-main rekey でそのプロファイルの名前空間に移せます)か、スコープを絞った書き込みで 紛れ込んだ既定プロファイルのチャット(--legacy-main move で既定のストアへ 送ります)のどちらかで、行そのものからは見分けが付きません。
--apply は、どれかのストアをゲートウェイが掴んでいる間は実行を断ります (ルーティングの索引をメモリに持っていて、あとで書き戻してしまうためです)。 また、繰り返し実行しても安全です。2 回目は何も見つかりません。
ストアのジャーナルモードを WAL と DELETE の間で切り替える
database.journal_mode: delete が効くのは、Hermes が新しく作るデータベースだけです。 すでに WAL モードになっている既存の state.db は、開くときに稼働中のまま 格下げされることは決してありません。ほかのゲートウェイ、ダッシュボード、cron のプロセスが まだチェックポイントしていない WAL のコミットを持っているかもしれず、その下で格下げすると それらのコミットが失われるからです。そのため Hermes は WAL のまま動き、設定した delete が 効かなかったことを知らせる ERROR をプロセスごとに 1 回ログに出します。自分で切り替える手順は次のとおりです。
# stop every process using the profile's store first (gateway, dashboard, CLIs, cron)
hermes sessions set-journal-mode delete # WAL -> rollback journal
hermes sessions set-journal-mode wal # back to WAL
hermes sessions set-journal-mode delete --db ~/.hermes/kanban.db # another Hermes storeこのコマンドは、ファイル本体か、その -wal/-shm の付随ファイルをどれかのプロセスが まだ掴んでいる間は、それぞれの PID とコマンドを示して実行を断ります。開いているプロセスが いなくなるのを待たずにモードを切り替え(途中で掴むプロセスが現れた場合は、競合させずに SQLite が拒否します)、ファイルのヘッダーが新しいモードになったことを確かめます。 設定と食い違うときは、database.journal_mode を同じ値にするよう促します。次に開くときに 設定したモードがもう一度適用されるためです。掴んでいるプロセスの確認はローカルで行われる (Linux/macOS では開いているファイルの一覧、Windows では Restart Manager を使います)ため、 同じボリュームを共有する別のコンテナや VM のプロセスは見えません。確認そのものが失敗した場合は、 ストアが静かな状態だと証明できないので、コマンドは実行を断ります。--force が免除するのは この場合だけで、Hermes のプロセスをすべて自分で止めたあとに使います。確認で見つかったプロセスが あるときは、どんな場合でも断られます。ストアが VM をまたぐ ファイルシステム(virtiofs/9p)にある場合も、WAL の有効化は断られます。そこでは WAL の 共有メモリが気づかないうちに壊れるためです。
Claude Code や Codex CLI からセッションを取り込む
別のエージェント CLI で始めた会話も、Hermes に取り込んでここで続けられます。 Hermes は Claude Code のセッションログ(~/.claude/projects/。Claude Code の設定ディレクトリを 移しているときは $CLAUDE_CONFIG_DIR/projects/)と Codex CLI の rollout(~/.codex/sessions/、 または $CODEX_HOME/sessions/)を読みます。外部のファイルは読むだけで、 書き換えることはありません。
# Interactive picker across both tools, newest first
hermes sessions import
# Limit to one tool, or point at a specific file
hermes sessions import --from claude
hermes sessions import --from codex ~/.codex/sessions/2026/08/15/rollout-....jsonl
# Import-and-resume in one step
hermes --resume @claude
hermes --resume @codexhermes sessions import は Imported from Claude Code: <first user message> (Codex CLI ならそちらの名前)というタイトルで新しい Hermes のセッションを作り、 その ID と、そのまま貼り付けられる hermes --resume <id> を表示します。 --resume @claude / --resume @codex は同じ選択画面を出し、取り込んだ会話へ そのまま入ります。
Hermes Desktop にも同じ取り込み機能があり、横一覧の Import session (コマンドパレットからも)で使えます。一覧に出るのは、アプリを動かしている パソコンではなく、つながっているバックエンドが動いている端末にあるログです。 読むだけのプレビューが出て、Continue in Hermes で会話が選んだプロファイルへ 写されます。一覧を眺めてもセッションの保存領域には何も書かれず、取り込んでも 元のファイルには触れません。同じログを 2 回取り込もうとすると、新しく作らずに すでにある写しを開きます。
引き継がれるのは、順番どおりのユーザーとアシスタントの会話です。ツールの動きは、 アシスタントのターンの中に [ran tool: …] という短いメモとしてまとめられます。 システムプロンプト、差し込まれた文脈、思考の記録、ツールの生の出力は残りません。 取り込みは読みやすい会話記録であって、1 バイトも違わない再現ではありません。
セッション検索のツール
エージェントには session_search というツールが最初から備わっていて、SQLite の FTS5 を使って過去のすべての会話を全文検索します。見つけたセッションの中を前後にたどることもできます。LLM は一切呼ばず、要約を作るのではなく、データベースにある実際のメッセージをそのまま見せます。
4 つの呼び出し方
このツールは、どの引数を渡したかで何をしたいのかを判断します。mode のような指定はありません。
1. 探す — query を渡す:
session_search(query="auth refactor", limit=3)FTS5 で検索し、セッションの系列ごとに重複を除いて、上位 N 件のセッションを返します。探すときの詳しさは既定で相手に合わせて変わります。いちばん順位の高い結果はその前後の文脈と会話の始まり・終わりまで含み、それより下の結果は簡素なままです。すべての結果を詳しく出したいときは detail="full" を渡します。
それぞれの結果には次のものが入っています。
session_id、title、when、sourcesnippet— FTS5 が一致箇所を強調した抜粋detail—fullまたはcompactbookend_start/bookend_end— 詳しい結果では最初と最後の 3 往復。簡素な結果では空のリストmessages— 詳しい結果では FTS5 の一致箇所の前後 5 件。簡素な結果では印の付いた 1 件だけmatch_message_id、messages_before、messages_after
いちばん上の結果を見れば、目的 → 一致箇所 → 決着の流れがすぐ分かります。簡素な結果のほうが有望に見えたら、そのセッションとメッセージの ID を使って、前後にたどる呼び方に移ります。実際のセッションのデータベースでは、たいてい数十ミリ秒で返ります。
2. たどる — session_id と around_message_id を渡す:
session_search(session_id="20260510_174648_805cc2", around_message_id=590803, window=10)指定したメッセージを中心に、前後 window 件を返します。FTS5 も会話の始まり・終わりもなく、その範囲だけです。既定の前後 5 件より広く見たいときに、探したあとで使います。
- 先へ進むには、
messages[-1].idをaround_message_idとして渡します - 前へ戻るには、
messages[0].idをaround_message_idとして渡します - 境目のメッセージは両方の範囲に現れ、位置の目印になります
messages_beforeまたはmessages_afterがwindowより小さければ、セッションの先頭か末尾に来ています
1 回あたりの所要時間は、たいてい 1〜2 ミリ秒です。
3. 読む — 中心を指定せず session_id だけ渡す:
session_search(session_id="20260510_174648_805cc2")セッション全体を返します。大きなセッションでは、先頭と末尾を切り出した形になります。この呼び方は @session:<profile>/<id> のリンクを開くときにも使われます。
4. 眺める — 引数なし:
session_search()最近のセッションを時系列で返します(タイトル、冒頭の抜粋、時刻)。話題を挙げずに「何をやっていたっけ」と聞かれたときに便利です。
FTS5 の検索の書き方
キーワードでの検索は、FTS5 の標準的な書き方に対応しています。
- 単純なキーワード:
docker deployment(FTS5 は既定で AND です) - 語句:
"exact phrase" - 論理演算:
docker OR kubernetes、python NOT java - 前方一致:
deploy*
任意の引数
sort— FTS5 の関連度に重ねてnewestかoldestを指定します。省くと関連度だけの順になります(既定。あちこち探るときはこれが向きます)。「あの件はどこで止まっていたか」にはnewest、「あれはどう始まったか」にはoldestを使います。detail—adaptive(既定)は探した結果の上位 1 件だけを詳しく出し、fullはすべての結果を詳しく出します。role_filter— 含める役割をカンマ区切りで指定します。探すときは既定でuser,assistantです(ツールの出力はたいてい雑音になります)。ツールの出力も含めたい(ツールの挙動を調べる)ときはuser,assistant,tool、ツールの出力だけを検索したいときはtoolを渡します。
いつ使われるか
エージェントは、セッション検索を自分から使うよう促されています。
> *「利用者が過去の会話に触れたときや、関係のある以前のやり取りがありそうだと思ったときは、聞き直す前に session_search で思い出すこと。」*
よくあるきっかけは「前にもやった」「あのときの」「この前」「さっき言ったけど」、あるいはいまの会話の窓に出てこないプロジェクト・人・概念への言及です。
プラットフォームごとのセッションの追い方
ゲートウェイのセッション
メッセージングプラットフォームでは、メッセージの送信元から決まった規則で作ったセッションキーでセッションを見分けます。
| チャットの種類 | 既定のキーの形 | 挙動 |
|---|---|---|
| Telegram の DM | agent:main:telegram:dm:<chat_id> |
DM のチャットごとに 1 セッション |
| Discord の DM | agent:main:discord:dm:<chat_id> |
DM のチャットごとに 1 セッション |
| WhatsApp の DM | agent:main:whatsapp:dm:<canonical_identifier> |
DM の相手ごとに 1 セッション(対応関係が分かるとき、LID と電話番号の別名は 1 つの身元にまとまります) |
| グループチャット | agent:main:<platform>:group:<chat_id>:<user_id> |
プラットフォームがユーザー ID を出す場合、グループの中で人ごとに分かれます |
| グループのスレッド / トピック | agent:main:<platform>:group:<chat_id>:<thread_id> |
そのスレッドの参加者全員で 1 つのセッションを共有します(既定)。thread_sessions_per_user: true にすると人ごとに分かれます。 |
| チャンネル | agent:main:<platform>:channel:<chat_id>:<user_id> |
プラットフォームがユーザー ID を出す場合、チャンネルの中で人ごとに分かれます |
共有のチャットで参加者を見分ける手がかりが取れないときは、その部屋で 1 つのセッションを共有する形になります。
グループのセッションを共有するか分けるか
既定では、config.yaml の group_sessions_per_user: true が使われます。つまり次のようになります。
- 同じ Discord のチャンネルで、アリスとボブがそれぞれ Hermes と話しても、会話の記録は混ざりません
- ある人のツールを多用する長い作業が、別の人の文脈の窓を汚しません
- 動作中のターンは、それを始めた送信者のキーに結び付きます。ただし
/stopはそのターンにも届きます。詳しくは下記を参照してください
/stop は「このチャットで動いているものを止める」という意味です。まず呼び出した人自身の セッションキーを試し、次にこのチャットで動いているターン(呼び出した人自身のスレッドにある ほかの参加者の実行も含みます)を対象にします。権限の確認は入りますが、別の部屋や ワークスペース、プロファイルには決して及びません。つまり、何もしていないアリスの /stop が、 同じ部屋でボブ(あるいはボット)が始めたターンを終わらせることがあります。スレッドの*中から* 送った /stop はもう少し狭く、そのスレッドに属する実行と、スレッドの枠を持たない部屋全体の 実行(DM が流れていく形のもの)に届きますが、同じチャンネルの別のスレッドや、ほかの人の 送信者ごとのトップレベルの実行には届きません。
代わりに「部屋ごとに 1 つの頭」にしたい場合は、次のように設定します。
group_sessions_per_user: falseこうするとグループやチャンネルは部屋ごとに 1 つのセッションに戻ります。会話の文脈は全員で共有できますが、トークンの費用、中断の状態、文脈の膨らみ方も共有することになります。
セッションの続き方
ゲートウェイの会話は、しばらく使わなかったからといって、また日付が変わったからといって リセットされることはありません。新しい会話にしたいときは /new か /reset をはっきり使って ください。文脈の圧縮はこれまでどおり自動です。本体は、古い session_reset の設定、リセットの決まりの 上書き、リセットの時間を決める環境変数を、いずれも無視します。設定でまだ session_reset.mode を idle、daily、both のいずれかにしていると、ゲートウェイの起動時と hermes doctor が警告を出します。時間でのリセットを残したいときは、 同じ設定ブロックをそのまま読むカタログのプラグインを入れてください: hermes plugins install hermes-session-reset-policy。資源を取り戻すために、 キャッシュしてあるエージェントが解放されることはありますが、それで永続的な会話が 置き換わるわけではありません。再起動からの復旧における「新しさ」の条件が制限するのは 自動で続けるかどうかであって、メッセージを送ったときに読み込まれる履歴ではありません。
/new が切り替えるのは、それを実行した画面だけです。 1 つのセッションは、同時にいくつもの場所で開けます。 Desktop のウィンドウ、TUI、hermes chat --resume のターミナル、ACP の エディター、Telegram のトピックが、どれもゲートウェイ上の同じ生きた会話につながっている、という形です。 そのどれかで /new(または /reset)を実行すると、新しいセッションが作られ、 *その*ウィンドウやチャットの経路だけがそちらに付け替わります。ほかの閲覧側はもとの セッションに残り、その履歴はそのままで、そこですでに走っているターンも走り続けます。 共有の会話を終えたり片付けたりするのは、別の、はっきりした操作です(止めてから /new、または削除。削除はターンが動いているあいだは断られます)。
セッションの手入れ:それでも /new を使うべき理由
ゲートウェイの会話はひとりでに切れることがないので、ひとつのセッションを何週間も使い続けがちです。 それでも動きはしますが、学習の仕組みが知らないうちに働かなくなり、費用もふくらみます。
- メモリが効くのは区切りのときだけです。
MEMORY.md/USER.mdはセッションの始まりに
差し込まれ、session_search は文脈からこぼれたことを思い出すためにあります。終わらない セッションでは何もかもがまだ文脈の*中*にあるので、エージェントがメモリを見にいく理由がなく、 「自分で学ぶ」仕組みはほとんど動きません。メモリの抽出(リセット前の保存)も、セッションが ほんとうに終わったときにしか起きません。
- 費用は履歴に比例して増えます。 圧縮すれば長いセッションも動き続けますが、1 回ごとの
やりとりに、(圧縮済みとはいえ)大きな前置きが毎回付いてきます。抽出したメモリを持って新しく 始めたセッションのほうが、ひと月続いたスレッドよりもほぼ必ず安く済みます。
実際の目安は、タスクや話題がひと区切りしたらセッションを終えることです。自然な切れ目で /new (名前を付けてもかまいません。例: /new payments-refactor)を実行してください。1 日ごとでも、 プロジェクトごとでもうまくいきます。作業の中で、この先も使える好みや手順が見えてきたなら、 リセットの前にエージェントへ「残しておく価値のあることを覚えておいて」と頼んでください。 終わるセッションからメモリやスキルは自動で保存されますが、はっきり促すと確実です。機械や ゲートウェイを再起動しても区切りにはなりません。同じセッションがそのまま再開します。
区切りをまたいで何が引き継がれるかは、メモリ を見てください。
落ちたときや再起動したあとの続き方
ゲートウェイのチャットは、明示的に /new(または /reset)を実行するまで 1 本の続いたセッションとして扱われ、大きくなるたびに圧縮されていきます。 これはゲートウェイが落ちても、再起動しても、更新しても変わりません。
- セッションの身元(行き先のキー、チャット、送信元)は、セッションの行を作るとき、
どの作り方(/new、最初のメッセージ、/branch の子)でもまとめて一度に 書かれます。その書き込みが失敗しても、次のターンの行き先の更新で自動的に直ります。
- 再起動のあと、ゲートウェイは各チャットを、実際に動きのあった時刻が
いちばん新しいセッションに結び直します。古くて放置された行が、実際に していた会話に勝つことはありません。
- 復旧は
/newの区切りを尊重します。そのチャットのいちばん新しい出来事が
意図的なリセットなら、そのリセットの向こうへ手を伸ばして古いセッションを よみがえらせるのではなく、まっさらな状態から始めます。復旧したセッションは 実際の放置時間も保つので、idle や daily のリセットを有効にしていれば、 すべてを新品扱いせずに正しく効きます。
保存場所
| 対象 | パス | 説明 |
|---|---|---|
| SQLite データベース | ~/.hermes/state.db |
セッションの情報とメッセージの全体、FTS5 付き |
| ゲートウェイのメッセージ | ~/.hermes/state.db |
SQLite。すべてのセッションのメッセージの正本 |
| ゲートウェイの行き先の索引 | ~/.hermes/state.db の gateway_routing テーブル |
セッションキーと、動いているセッション ID の対応(送信元の情報、期限の印) |
| 旧式の行き先の写し | ~/.hermes/sessions/sessions.json |
行き先の索引の後方互換用の写し。gateway.write_sessions_json: true(既定)のときに書かれます |
SQLite データベースは、読み手が同時に何人いても書き手は 1 つ、という WAL モードで動きます。複数のプラットフォームを束ねるゲートウェイの作りによく合っています。
データベースの構造
state.db の主なテーブルは次のとおりです。
- sessions — セッションの情報(id、source、user_id、model、title、時刻、トークン数)。タイトルには重複を許さない索引が付いています(NULL は許され、NULL でないものだけが重複できません)。
- messages — メッセージ履歴の全体(role、content、tool_calls、tool_name、token_count)
- messages_fts — メッセージ本文を全文検索するための FTS5 の仮想テーブル
セッションの期限と後片付け
自動の後片付け
- ゲートウェイの会話は、しばらく使わなくても残ります。区切りたいときは
/newか/resetを使ってください - リセットの前に、エージェントは期限を迎えるセッションから記憶と skill を保存します
- 自動の整理(既定では無効。使うときは自分で有効にします):
sessions.auto_pruneがtrueのとき、終了したセッションのうちsessions.retention_days(既定 90)の間なにも起きていないものが、CLI・ゲートウェイ・cron の起動時に整理されます - ディスクが少ないときの確認。
config.yamlにsessions.auto_pruneのキーがない間、Hermes はセッションの開始時にstate.dbを置いたディスクの空きを調べます(ファイルシステムへの呼び出し 2 回だけで、目に見える負荷はありません)。空きが少ないとき(空きが 2 GB 未満、または残りが 20 GB 未満で空きが 10% 未満)は、一度だけたずねます。従来の CLI は起動時にたずね(空きが少ない状態で最初に起動したときはバックグラウンドで測るだけで、質問は次の起動から出ます。そのため起動がデータベースを待つことはありません)、TUI と Desktop はお知らせを出し、ゲートウェイはホームのチャンネルに質問を投稿します。この確認では、整理するとどれくらいの履歴が消えるかを見積もり(保存されているバイト数で重みを付けるので、古い小さなメッセージがたくさんあっても多めに出ません)、整理してもディスクの問題が*解決しない*ときはそうはっきり伝えます(retention_daysより古いセッションがない場合や、履歴がディスク全体のごく一部でしかない場合)。履歴を消すとstate.dbの中に空きができますが、下で説明する自動のVACUUMは 1 回の整理ではほとんど動かないので、hermes sessions optimizeを実行して空きをディスクに戻してください。答えは/autoprune on、/autoprune off(すべて残し、二度とたずねません)、/autoprune later(1 週間後にもう一度知らせます)のどれかです。/autopruneだけを打つと、いまの状態が表示されます sessions.retention_daysは>= 0の整数の日数でなければなりません。負の値(や、値がないこと)は受け付けられません。起動時の整理処理は、許される範囲を示した警告を記録したうえで、未来の日付を区切りにして「全部」を消しにいくようなことはせず、その回の整理を飛ばします。整理そのものを止めたいときの切り替えはsessions.auto_prune: falseです- 実際に行が消えた整理のあと、
state.dbは次の両方の条件を満たしたときだけVACUUMしてディスクを取り戻します。前回のVACUUMの成功からsessions.min_vacuum_interval_days(既定 30)以上たっていること、かつファイルのページの 25% 以上が取り戻せる状態であること(PRAGMA freelist_count / page_count)。中身の詰まったデータベースが、数 MB のために全体を書き直す代価を払うことはありません(SQLite は普通の DELETE ではファイルを縮めません) - 整理は
sessions.min_interval_hours(既定 24)につき最大 1 回だけ走ります。最後に実行した時刻はstate.db自身に記録されるので、同じHERMES_HOMEを使うすべての Hermes のプロセスで共有されます
整理をしないと state.db は際限なく大きくなります。ゲートウェイと cron を組み合わせた環境で、数週間のうちに数 GB になったという報告があります。大きくなりすぎないようにするには、~/.hermes/config.yaml で有効にしてください(/autoprune on と答えても同じです)。
sessions:
auto_prune: true # default is false — true deletes ended sessions past retention_days
retention_days: 90 # keep ended sessions active within this window
vacuum_after_prune: true # reclaim disk space after a pruning sweep
min_vacuum_interval_days: 30 # don't rewrite the DB more often than this
min_interval_hours: 24 # don't re-run the sweep more often than thisこれらのキーを自分で設定してある環境では、その値がそのまま保たれます。 設定していないキーだけが既定値に従います。
消えるのは終了したセッションだけです。動いているセッションは、どれだけ古くても 自動で整理されることはありません。終了したセッションは最後のメッセージからの 経過で数えるので、始まったのが保持期間より前でも、最近使った長い会話が それだけの理由で消えることはありません。圧縮によって複数のセッションに分かれた会話も 同じです。あとの区切りが残っている間はそれより前の区切りも残り、会話全体が条件を 満たしたときに、まとめて整理されます。
自動処理が残す開きっぱなしのセッション。 cron の処理、かんばんのワーカー、 下位エージェント、1 回きりの CLI 実行といったものは、セッションを終了と 記録しないまま止まることがあります。整理が消すのは*終了した*行だけなので、 そのままでは溜まり続けます。そこで自動の整理は毎回、状態を持つ送信元 (cli、cron、kanban、acp、api_server、subagent、tool、 および hermes sessions recover が迷子のメッセージのために作る recovered の 仮の行)の開きっぱなしのセッションのうち、最後の動きが retention_days より 古いものを*閉じ*ます(end_reason: startup_orphan_reap)。閉じるだけなら何も失われず、 セッションは再開できます。行は閉じた時点から数え直されるので、実際に消えるのは さらに保持期間をまるごと過ぎたあと、*次の*整理のときです。メッセージング プラットフォームのセッション(Telegram、Discord など)、TUI やデスクトップの セッション、固定したセッション、ターンや圧縮が進行中のセッションは、 この整理で閉じられることはありません。
大きすぎる会話記録への備え
暴走した会話記録が一度にメモリへ読み込まれないよう、2 つの上限があります (どちらも既定はメッセージ 20000 件。0 にすると無効になります)。
sessions:
max_resume_messages: 20000 # interactive resume (CLI / TUI / Desktop)
max_export_messages: 20000 # one-shot in-memory export of a single sessionmax_export_messages は、JSON / JSONL のバックアップ(hermes sessions export、 hermes console の中の sessions export、CLI・メッセージング・TUI・Desktop の /save json)にセッションごとに効きます。バックアップにはアーカイブ済みの行も全部入るので、 保存されているすべての行を数えます。何度も圧縮されて、いま動いている先端が小さいセッションでも、この上限を超えることがあります。 ダッシュボードの Sessions ページにある Export 操作は行を少しずつ流して書き出すので、この上限はかかりません。
max_resume_messages が制限するのは再開のときに実際に読み込む量であって、 会話の履歴全体ではありません。
- 普通の対話での再開(CLI の
--resume、TUI)は、圧縮の系列全体
——圧縮された区間のすべてと、いま動いている先端——を組み立てるので、 系列全体で見た量が上限になります。
- Desktop の起動時の再開は REST 経由で会話記録を少しずつ読み、メモリに
持つのはいま動いている先端の区間だけなので、その先端だけが上限になります。 何度も圧縮されてきた長い会話(区間が何十もあり、小さな先端の後ろに何万もの 保管された行がある状態)は、まさに圧縮が生み出そうとしている姿であり、 普通に開けます。画面の下に出るメッセージ数は、いまのプロンプトではなく 保存された系列全体を表しています。
再開が断られると、クライアントにはエラーコード 4130 と、件数、そして どの範囲で数えたか(across its lineage か in its tip segment)が返ります。TUI / Desktop の /save が max_export_messages で断られた場合は、エラーコード 4131 が返ります。 そうしたセッションでも hermes sessions export は使えます。ただしその JSON / JSONL の バックアップでは、各セッションが max_export_messages を下回っている必要があります。
手動の後片付け
# Prune sessions older than 90 days
hermes sessions prune
# Delete a specific session
hermes sessions delete <session_id>
# Export before pruning (backup)
hermes sessions export backup.jsonl
hermes sessions prune --older-than 30 --yes