プログラミング
エージェント向けにローカルおよびリモートのメモリシステムを構築しました
I've built a free, open-source local and remote memory system for agentw and CL (lorekit.io)
要約
このシステムは、エージェントが過去のセッションの情報を記憶できるようにする、ローカルで実行可能なメモリシステムです。アカウント登録やネットワーク接続は不要で、ユーザーが所有するプレーンファイルとしてデータを保存します。ローカルからリモートへのスケーリングも容易で、既存のセットアップに統合できます。
全文翻訳
すべての投稿
あなた(エージェント)は昨日、この問題を解決しました。
昨日、あなた(エージェント)は、統合テストを実行する前にPostgresコンテナを起動する必要があることを突き止めました。今日、それはECONNREFUSED 5432に遭遇し、コネクションプールが誤設定されていると判断し、問題のないファイルを書き換えるのに9分を費やしました。同じ壁、同じ登り、登った記録は何もありません。セッションごとに、それは記憶喪失で目覚めます。
通常のピッチは、あなたが採用するプラットフォームです。これはそうではありません。それは1つのコマンドとあなたが所有する1つのフォルダです — ディスク上のプレーンファイル、アカウントなし、ネットワークなし、サインアップするものなし。そして、これが単なるスターターおもちゃ以上のものにする部分です:同じ読み取りパスがローカルディレクトリまたはホストされたPostgres上で実行されます — ローカルからリモートへのスケーリングは純粋に加算であり、移行ではありません。あなたのファイルはそのまま残り、lorekit list は両方のストアを並べて表示し続け、何もエクスポートされることはありません。あなたはフォルダから始めます。あなたはそれを決して置き去りにすることはありません。
2分でメモリにアクセス
1つのコマンドで、lorekit-memory、lorekit-setup、lorekit-groom スキル、MCPサーバーエントリ、および .claude/ (プロジェクト) または ~/.claude/ (グローバル) へのライフサイクルフックがスキャフォールディングされます。
npx @lorekit/cli install
これは3つのことを尋ねます:プロジェクトかグローバルか、トークン、そしてどのフックを接続するか(すべて、読み取り専用、またはなし)。トークンを空白のままにし、フックにはすべてを選択してください。2つの小さなファイルが作業を完了します。
まず、リポジトリのルートに .lorekit.json があります — コミットしても安全です。秘密情報は含まれていません — これはストアをディスクにピン留めします:
{
"mode": "local"
}
次に、MCPサーバーをホストされたもののではなく、あなた自身のマシンに向けます。
install は、lorekit エントリを .mcp.json にマージします — 他のサーバーはそのままにしておきます — そしてデフォルトでは、そのエントリはホストされたエンドポイントを指します。そのエントリをCLIのローカル stdio サーバーに置き換えるだけです:
// .mcp.json → mcpServers — このエントリを編集してください、他のエントリはそのままにしておいてください
"lorekit": {
"command": "npx",
"args": ["-y", "@lorekit/cli", "mcp"]
}
それがセットアップ全体であり、npx @lorekit/cli doctor は解決されたモードとそれを決定したファイルを教えてくれます。
これで障害を発生させてください。あなた(エージェント)はテストを実行し、それらは失敗し、PostToolUseFailure フックは1つのことを言います。以下は、これを書いている間に私が設定したリポジトリからの実際の出力です — 実行されていなかったデータベースに対する実際の pnpm test:
LoreKit: the last Bash call failed. If it's recurring or non-obvious, memory.write to repo::acme/checkout with the fix so the next run avoids it.
これは促しであり、書き込みではありません。書き込みは、モデルが memory.write を呼び出すことです — LoreKit はあなたの背後で何も記録しません。そして、それが記録するものは、誰かのデータベースの行ではありません。それはファイルです:
cat ~/.lorekit/repo/acme/checkout/tests-need-local-postgres.md
---
scope: "repo::acme/checkout"
key: "tests-need-local-postgres"
created: "2026-08-15T17:00:18.477Z"
updated: "2026-08-15T17:00:18.477Z"
seen_count: 1
---
Integration tests need the local Postgres up first: docker compose up -d db. Without it every test fails with ECONNREFUSED 5432, which reads like a code bug and isn't. (Trimmed — the real frontmatter carries a few more fields, tags and provenance among them.)
それを cat してください。それを grep してください。それをコミットするか、それを rm してください。それはあなたのものです。
そして次のセッションを開始すると、ループが閉じます:
LoreKit: 1 memory loaded · repo::acme/checkout — considerations, not rules; read any in full with memory.read. - (repo::acme/checkout) tests-need-local-postgres — Integration tests need the local Postgres up first: docker compose up -d db.…
そして、同じ障害がタスクの途中で再び発生した場合、障害フックは今や単なる促しではなく、教訓そのもので始まります — 1 related memory — あなたは以前にこのようなことに遭遇したことがあります。それがすべてです。それが aha です。一度失敗し、あなた自身のディスク上で、次のタスクはすでに知っている状態で開始されます。
インストール、失敗、記憶。中間にサービスなし — 全てのループはあなたが所有するディレクトリ内のファイルで閉じます。
既存のセットアップに、メモリを追加
おそらくあなたはすでに何かを構築しているでしょう — スキル、サブエージェント、レビューワークフロー。あなたはそれを再構築しません。lorekit-setup は、読み取り-失敗-書き込みループをあなたがすでに持っているホストに配線します:それは教訓バケット(タグとキーの名前空間)、スコープ、そして「行動する前に読む」/「摩擦時に書く」ポイントを選択します。あなた(エージェント)にそれを実行させ、ホストに名前を付けさせます。
人々がここで間違える2つのこと。
教訓は勧告的な観察であり、ルールではありません。それはマーケティング上の柔らかさではありません — それは注入されたブロックが文字通り使用する言葉です:considerations, not rules。教訓は、あなた(エージェント)が将来の自分自身のために残したメモであり、それが間違っている場合は無視できます。これはまさに、これがあなたの CLAUDE.md と競合しない理由です。CLAUDE.md は、あなたが決定したルール — レビュー済み、慎重、バージョン管理された — を配置する場所です。Lore はその下のレイヤーです:まだルールを獲得していない「あれ、またあの部分か」という蓄積された山。そのうちのいくつかは最終的にはそうなるべきであり、それを昇格させるのは人間の編集です。そのほとんどはそうならないでしょう、そしてそれは大丈夫です — それでも再学習しない価値はあります。
それがその価値を発揮する3つの実際のケース
それが再発見し続ける落とし穴。上記のPostgresの例は本物であり、それは単独のケース全体です。繰り返される環境的事実 — 起動する必要があるサービス、ビルドが必要とするフラグ、READMEにあるものとは異なるパッケージマネージャー — は一度書き込まれ、タスクごとに読み取られます。seen_count は、同じ教訓が再学習されるたびに増加し、繰り返される教訓はブロック内でより高くランク付けされます。
スパイクに留まるスパイクの教訓。スコープはグローバル、project::{name}、repo::{owner}/{repo}、および branch::{owner}/{repo}::{branch} であり、最も具体的なものから順に読み取られます。ブランチスコープに実験の結果を書き込むと、それらはそのブランチにのみ表示され、他には表示されません:
memory.write {
scope: "branch::acme/checkout::feat/new-cache",
key: "cache-invalidation-strategy",
value: "Write-through for the session store; write-behind for aggregates.",
tags: ["wip"]
}
ブランチが死ねば、教訓も死にます。それがマージされたら、repo::acme/checkout でキーを書き直し、ブランチのコピーを削除します。main は混乱を見ることはありません。npx @lorekit/cli tree を実行して、タスクが開始される前に重複したキーがどのスコープで勝つかを確認してください。
有効期限付きのメモ。一部の事実は1週間有効です。ttl_days を渡すと、エントリは自動的に非表示になります:
memory.write {
scope: "repo::acme/checkout",
key: "skip-flaky-checkout-test",
value: "checkout.spec is flaky on CI — backend ships the fix Friday. Don't chase it.",
ttl_days: 5
}
クリーンアップタスクなし、11月にあなた(エージェント)を誤った方向に導く古いメモなし。
共有する準備ができたとき
上記は何のアカウントも必要としませんでした。ラップトップ、デスクトップ、そしてチームメイトのマシンで同じメモリを共有したい場合、何も移動する必要はありません — CLIをホストされたストアに向けます。3つのステップ。
lorekit.io で無料アカウントを作成し、Settings → API keys を開き、読み取り/書き込みキー (lk_rw_…) を生成します。これは一度だけ表示されるので、コピーしてください。次に、すでに実行したのと同じインストーラーにそれを渡します:
npx @lorekit/cli install --force
キーを求められたら貼り付けます。それがスイッチ全体です。
install は、.mcp.json の lorekit エントリをトークン付きのホストされたエンドポイントに再設定し、リモートがデフォルトモードになります — なので、他に設定することはありません。(ローカルセットアップで "mode": "local" をピン留めした場合、その行を削除するとデフォルトが有効になります。)
あなたのファイルは移動しません。npx @lorekit/cli list は、両方のストアを読み取り、それらを並べて表示します — ローカルファイルからのオフラインセクション、ホストされたストアからのリモートセクション — なので、スイッチの前にあなたが書いたものは何も失われません。そのサイドバイサイドビューはあなたのためです。
すでに持っている教訓をホストされたストア自体(チームメイトのエージェントやCI実行が読み取る場所)に入れるには、一度アップロードします:
npx @lorekit/cli migrate --from ~/.lorekit --to remote # preview
npx @lorekit/cli migrate --from ~/.lorekit --to remote --yes # push it
--yes を追加するまで、これはドライランです。トークンを最初にチェックします(読み取り専用キーは拒否され、半分完了することはありません)、そしてそれは冪等です — より多くのことをオフラインで学んだら、いつでも再度実行してください。作成日は引き継がれるため、新しさによるランキングは引き続き機能します。最終更新日時と表示回数はサーバー側で再計算されます。アーカイブまたは期限切れにしたものはスキップされ、復活することはありません。