0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KIOKU v0.5.0 + v0.5.1 — EPUB/DOCX 取り込みと hot cache で「記憶」と「持続」をつなぐ

0
Posted at

Generated Image April 16, 2026 - 10_20PM.jpg

Claude Code / Desktop の記憶 OSS「KIOKU」を同日に 2 リリース (v0.5.0 + v0.5.1、2026-04-23) 出したので、機能面と設計判断をまとめます。

1 行でまとめると:

  • v0.5.0: 外部ドキュメント (PDF / Markdown / EPUB / DOCX) の統一 ingest router
  • v0.5.1: session 間の短期記憶を繋ぐ hot cache + PostCompact hook

外部の知識を取り込む (ingest) → session 間で持続させる (persist)」という連続した一対のリリースです。

前提

KIOKUを初めて見る方向けにご紹介します。

Claude Code は過去のセッションで得た知識をどんどん忘れます。KIOKU はあなたが Claude と話した記憶を自動で Wiki に蓄積し、次のセッションで呼び戻せるようにする OSS です。Obsidian Vault 上に構造化されたナレッジベース (Andrej Karpathy の LLM Wiki パターン がベース) を作って、Git で複数マシン間同期します。

v0.5.0: PDF / MD / EPUB / DOCX の統一 ingest router

変更点

v0.5.0 までは PDF 用・Markdown 用・URL 用で別々の MCP tool が並んでいました。v0.5.0 で kioku_ingest_document(path) という 1 本の入り口を切って、拡張子で dispatch する形にリファクタしました。

kioku_ingest_document("論文.pdf")   → PDF handler
kioku_ingest_document("note.md")   → PDF と同じ extractor (plain text chunk)
kioku_ingest_document("book.epub") → EPUB handler (新規、yauzl ベース)
kioku_ingest_document("spec.docx") → DOCX handler (新規、mammoth ベース)

kioku_ingest_pdfdeprecation alias として v0.5 〜 v0.7 window で残存、v0.8 で削除予定です。新規統合は kioku_ingest_document を使ってください。

使い方 (Claude Desktop / Code から)

# 1. raw-sources/ 配下にファイルを置く
cp 論文.pdf $OBSIDIAN_VAULT/raw-sources/papers/
cp book.epub $OBSIDIAN_VAULT/raw-sources/books/
cp spec.docx $OBSIDIAN_VAULT/raw-sources/specs/

# 2. Claude に頼む
kioku_ingest_document("raw-sources/papers/論文.pdf") で要約して
kioku_ingest_document("raw-sources/books/book.epub") で取り込んで

cron 経由の自動取り込み (auto-ingest.sh) も同じ router を通ります。vault の raw-sources/ 配下を 1 日 3 回スキャンして、未処理のドキュメントを wiki/summaries/ に要約していきます。

EPUB 取り込みの設計: 8 層防御の ZIP 展開

EPUB は実体が ZIP なので、攻撃者ペイロードの典型的な流入経路です。KIOKU では Readability に食わせる前に 8 層の防御を直列に置いています:

防ぐもの
1 zip-slip (../ を含む entry path)
2 symlink entry (vault 外を指すリンク)
3 累積 size cap (爆弾 EPUB、展開後 500 MB まで)
4 entry count cap (10,000 エントリまで)
5 NFKC filename 正規化 (Unicode normalization attack 対策)
6 nested ZIP skip
7 XHTML に対する XXE pre-scan (<!DOCTYPE 拒否)
8 XHTML 内 <script> / on*= sanitize

全層を通過した XHTML だけ Readability + Turndown で Markdown 化、spine 順で .cache/extracted/epub-<subdir>--<stem>-ch<NNN>.md に保存します。2 章以上の EPUB は目次 -index.md も自動生成、後段の auto-ingest cron が LLM 要約時に参照します。

DOCX 取り込みの設計: mammoth + yauzl の二段構え

DOCX は ZIP + XML。mammoth が内部で使う jszip は XXE / zip-slip に無防備なので、yauzl で先に ZIP を開いて 8 層防御を通過させる構造にしました:

  1. yauzl で ZIP を開き、8 層防御 (EPUB と共通) を通す
  2. word/document.xml / docProps/core.xmlassertNoDoctype() で XXE pre-scan
  3. 全通過したら ZIP を閉じて mammoth に Buffer を渡す
  4. Metadata は --- DOCX METADATA --- fence で囲って untrusted 注釈付きで保存

画像 (VULN-D004/D007) と OLE 埋め込み (VULN-D006) は MVP では skip しています。画像対応は EPUB と同じ pattern で将来拡張予定。OLE は threat surface が広いため別 PR で詰めます。

Unicode ファイル名対応

EPUB / DOCX extractor は cron (auto-ingest.sh) から argv でファイル名を受け取るので、raw-sources/<subdir>/<stem>.<ext> を分解する正規表現が必要です。ASCII 前提の \w では日本語・中国語のファイル名を拾えないので、Unicode プロパティ escapes を使いました。

const m = argv[2].match(/raw-sources\/([\p{L}\p{N}_-]+)\/([\p{L}\p{N}_-]+)\.(epub|docx)$/u);
//                                     ^^^^^^^^^^^^^^^^^                   ^^^^^^^^^^^^^^^^^   ^
//                                     Unicode-aware                       Unicode-aware     unicode flag

\p{L} は任意のスクリプトの文字 (Latin / Cyrillic / CJK / Arabic / Devanagari など)、\p{N} は数字、/u flag が必須。これで 論文.epub日本語メモ.docx も cron 経路で正しく拾えます。

v0.5.1: hot cache で session 跨ぎ context を維持

変更点

Claude Code は長い session で context compaction (要約圧縮) が走ると、直前までの作業記憶が大幅に減ります。v0.5.1 では wiki/hot.md という 1 ファイルに「短期記憶」を蓄積し、SessionStart と PostCompact (新 hook event) の両方で注入 する仕組みを入れました。

hot.md のフォーマット

---
type: hot-cache
updated: 2026-04-23
---

## Recent Context

- いま何を作っているか
- 直前の session で決めた設計判断
- 次の session で覚えておきたいコンテキスト

500 word soft limit、hard cap 4000 文字。LLM が session 終わりに書き換える前提の軽量メモです。

注入戦略

Event 注入内容 理由
SessionStart hot.md + index.md の両方 session 冒頭は全 context が必要
PostCompact (新) hot.md のみ index.md は context に残存、token 節約

Stop hook の opt-in prompt

「session 終わりに hot.md を書き換える」提案を Stop hook で出すかどうかは、default opt-out にしました。明示的に KIOKU_HOT_AUTO_PROMPT=1 を set したときだけ提案 prompt が出ます。

# 明示的に opt-in する場合のみ
export KIOKU_HOT_AUTO_PROMPT=1

理由: session-logs/.gitignore 対象でローカル保持ですが、hot.mdGit sync 対象。書き換え内容がそのまま GitHub private repo に commit されるため、マスクされるはずの API key が紛れ込む経路を予防する必要があります。security boundary が違うものを同じ自動化で扱わない、という境界設計です。

Security boundary

  • hot.md 注入前に applyMasks() 適用 (API key / token パターン伏字化、既存 mcp/lib/masking.mjs を共有)
  • scan-secrets.sh の scan 対象に wiki/hot.md を追加
  • realpath で symlink escape (vault 外パス参照) を拒否
  • 4000 文字超過は truncate + WARN log

インストール (新規ユーザー向け)

クイックインストール (Claude Code Max プラン)

# 1. Vault を作成 (Obsidian で新規 Vault、path を OBSIDIAN_VAULT に export)
export OBSIDIAN_VAULT="$HOME/claude-brain/main-claude-brain"

# 2. GitHub private リポジトリを作成して Vault を git init + push
cd "$OBSIDIAN_VAULT"
git init && gh repo create --private --source=. --push

# 3. KIOKU を clone して setup
git clone https://github.com/megaphone-tokyo/kioku.git ~/kioku
cd ~/kioku
bash scripts/setup-vault.sh       # Vault 初期化
bash scripts/install-hooks.sh --apply  # Claude Code Hook を ~/.claude/settings.json にマージ

# 4. 定期実行 (自動 ingest + lint) を登録
bash scripts/install-schedule.sh  # macOS LaunchAgent / Linux cron を自動判別

# 5. qmd 検索 (任意、Wiki 全文検索)
bash scripts/setup-qmd.sh
bash scripts/install-qmd-daemon.sh

# 6. kioku-wiki MCP サーバー (Claude Desktop 経由で wiki 操作)
bash scripts/setup-mcp.sh
bash scripts/install-mcp-client.sh --apply

Claude Desktop 向け: .mcpb ドラッグインストール

  1. Releases から最新の kioku-wiki-0.5.1.mcpb (9.2 MB) をダウンロード
  2. Claude Desktop を起動、設定 → Extensions / Connectors 画面に .mcpb をドラッグ
  3. インストールダイアログで Vault directory を picker から選択 → Install
  4. 新しいチャットを開いて kioku_read で wiki/index.md を読んで で動作確認

エンドユーザー側で Node のインストールは不要 — バンドルに @modelcontextprotocol/sdk が同梱され、Desktop 内蔵の Node ランタイムで動きます。

設計判断: defuddle を作らなかった話

v0.5.2 で defuddle (web 広告 / boilerplate 除去で token 40-60% 削減) を作る予定でしたが、着手前の 実測 probe で不要判定、skip しました。

測ったこと

  1. raw-sources/articles/ の既存 10 件の body 長: 全件 substantial (1,640 〜 170,204 bytes、中央値 ~10KB)
  2. session-logs/ 38 件 grep (short-content / readability.*fail / extracted.*empty): 0 件
  3. .cache/extracted/url-* 失敗 cache: 0 件

既に使っている @mozilla/readability が広告 / boilerplate を十分除去していて、defuddle の前段を足す理由が測定データに存在しない、という結論。工数 6-10h を v0.6.0 Phase C (LP β + plugin marketplace) に振り分けました。

判断は再燃条件付きで handoff/open-issues.md §19 に記録してあります (Readability が空に近い抽出を生成する事例発生 / JavaScript-heavy SPA の本文抽出失敗 / 競合が defuddle で UX 優位を示した時、のいずれかで再評価)。

テスト / Lint

  • v0.5.0: Bash 158 assertions + Node 全 suite green (npm audit で runtime deps 0 vulnerabilities、red-hacker + blue-hacker 並列 /security-review で HIGH/CRITICAL 0)
  • v0.5.1: Node 47 件 (HOT-1..9d + HOT-V1/V2 + injector H1-H5) + Bash 488 assertions (IH-PC1/2 + SS-H1 + CGP-2 拡張) 全 green
  • 既知 issue: fast-xml-parser CVE-2026-41650 は XMLBuilder 固有の問題、KIOKU は XMLParser (読み込み側) しか使わないので exploit 不可。dependabot alert 解消のため v0.5.1 で ^5.7.0 に upgrade 済

Release 情報

v0.6 に向けて

v0.5 系で ingest → persist の基盤が揃ったので、次の Phase C では 外部 user を迎え入れるフェーズに入ります:

  • Agent Skills cross-platform 対応: Cursor / Windsurf / Gemini CLI / Codex に symlink で広げる
  • Claude Code plugin marketplace 登録: claude plugin install kioku@megaphone-tokyo で 1 行 install
  • Delta tracking: .raw/.manifest.json で source-level hash 管理 (同 PDF 2 回 ingest で skip)
  • Obsidian Bases dashboard: wiki/meta/dashboard.base で ingest 履歴 / orphan 一覧を動的表示
  • LP β + Discord soft launch: 1 人 dogfooding から外部 feedback を受け取る体制へ

まとめ

  • v0.5.0: PDF / MD / EPUB / DOCX の統一 ingest router (kioku_ingest_document)、EPUB 8 層防御、DOCX の mammoth + yauzl 二段構え
  • v0.5.1: hot cache (wiki/hot.md) + PostCompact hook、Stop hook は default opt-out (security boundary が違うため)
  • v0.5.1 release 当日の 4 回 iteration: Claude Code v2 の per-event hook schema drift に合わせて schema 対応 (全て v0.5.1 タグ前に commit)
  • v0.5.2 defuddle は skip: 実測データで不要判定、再燃条件付き
  • MIT License、フィードバック歓迎です

他のプロダクト

こんにちは、季節より。 / hello from the seasons.

季節の写真を集めたギャラリーサイトです。作者が撮影した四季折々の写真を眺められるだけでなく、自分の画像と季節の写真を AI で合成する機能もあります。写真が好きで、AI で遊ぶのも好き、という個人的な興味から作りました。


作者: @megaphone_tokyo
コードと AI で何かつくる人 / フリーランスエンジニア 10 年目 / 東京

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?