<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 張峰豪</title>
    <description>The latest articles on DEV Community by 張峰豪 (@_795b499841c010ff4ee9d).</description>
    <link>https://dev.to/_795b499841c010ff4ee9d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3973206%2Fca059af8-4169-489b-a7ed-861a171ffc56.png</url>
      <title>DEV Community: 張峰豪</title>
      <link>https://dev.to/_795b499841c010ff4ee9d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_795b499841c010ff4ee9d"/>
    <language>en</language>
    <item>
      <title>I gave my Claude Code Telegram bot a memory — and found inbound messages skip every hook</title>
      <dc:creator>張峰豪</dc:creator>
      <pubDate>Mon, 08 Jun 2026 01:24:14 +0000</pubDate>
      <link>https://dev.to/_795b499841c010ff4ee9d/i-gave-my-claude-code-telegram-bot-a-memory-and-found-inbound-messages-skip-every-hook-19o7</link>
      <guid>https://dev.to/_795b499841c010ff4ee9d/i-gave-my-claude-code-telegram-bot-a-memory-and-found-inbound-messages-skip-every-hook-19o7</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fju40x6o1fq5g4fnpltoh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fju40x6o1fq5g4fnpltoh.png" alt="LoreRoom recalling a Telegram conversation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I run Claude Code from my phone through its official Telegram plugin. It's great — until the session restarts and the bot forgets the entire conversation. Ask "what did we decide yesterday?" and it has no idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  The surprising part: inbound messages don't trigger any hook
&lt;/h2&gt;

&lt;p&gt;My first instinct was a &lt;code&gt;UserPromptSubmit&lt;/code&gt; hook to log every message. It never fired for Telegram messages.&lt;/p&gt;

&lt;p&gt;Inbound Telegram messages are delivered to Claude through an &lt;strong&gt;internal channel push&lt;/strong&gt; — not through any of Claude Code's hooks. Worse, when the bot is busy they &lt;strong&gt;queue invisibly&lt;/strong&gt;, and if it never replies they can be lost. So the two "obvious" approaches — hooks and scraping the transcript — both silently drop messages.&lt;/p&gt;

&lt;p&gt;The only reliable capture point is &lt;strong&gt;inside the plugin itself&lt;/strong&gt;, the moment a message arrives.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built: LoreRoom
&lt;/h2&gt;

&lt;p&gt;It patches the Telegram plugin at its source to capture &lt;strong&gt;both directions&lt;/strong&gt; the instant each message arrives — even if the bot is busy, crashed, or never replies — into a &lt;strong&gt;whole-file-encrypted SQLite DB&lt;/strong&gt; (SQLCipher). Recall is handed back to Claude as two MCP tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;get_recent_context(hours)&lt;/code&gt; — the last N hours&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search_tg_history(keyword)&lt;/code&gt; — full-text search over everything (FTS5 trigram, works for CJK too)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Local-only; never touches your bot token.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You &amp;lt;-&amp;gt; Telegram ──(patched plugin)──&amp;gt; spool ──&amp;gt; encrypted SQLite ──(MCP)──&amp;gt; Claude recalls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can ask my bot "what did I send you last night?" and it actually answers.&lt;/p&gt;

&lt;h2&gt;
  
  
  On encryption
&lt;/h2&gt;

&lt;p&gt;This is &lt;strong&gt;at-rest encryption of the local DB&lt;/strong&gt;, not Telegram E2E. It protects the DB file if it's copied off the machine; the key lives in a git-ignored, &lt;code&gt;chmod 600&lt;/code&gt; config and is never given to Claude or sent over a network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;MIT-licensed: &lt;a href="https://github.com/fenghaochang/LoreRoom" rel="noopener noreferrer"&gt;https://github.com/fenghaochang/LoreRoom&lt;/a&gt;&lt;br&gt;
Stack: TypeScript, better-sqlite3 (SQLCipher), MCP SDK, FTS5. My first open-source release — feedback very welcome.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>claude</category>
      <category>opensource</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
