<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Lifecycle Hooks on Wojciech Marusiak IT Blog</title>
        <link>https://www.wojcieh.net/tags/lifecycle-hooks/</link>
        <description>Recent content in Lifecycle Hooks on Wojciech Marusiak IT Blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <lastBuildDate>Tue, 10 Nov 2026 10:15:00 +0100</lastBuildDate><atom:link href="https://www.wojcieh.net/tags/lifecycle-hooks/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Building Context Guard for Google Antigravity: Real-Time Token Telemetry and Strategic Compaction</title>
        <link>https://www.wojcieh.net/building-context-guard-google-antigravity-strategic-compaction/</link>
        <pubDate>Tue, 10 Nov 2026 10:15:00 +0100</pubDate>
        
        <guid>https://www.wojcieh.net/building-context-guard-google-antigravity-strategic-compaction/</guid>
        <category>Google Antigravity</category>
        <category>Gemini</category>
        <category>AI Agents</category>
        <category>Lifecycle Hooks</category>
        <category>Plugins</category>
        <category>Context Window</category>
        <category>Python</category>
        <category>AI &amp; LLM Ops</category>
        <category>Homelab &amp; Infrastructure</category>
        <description>&lt;p&gt;&lt;img src=&#34;https://www.wojcieh.net/images/uploads/2026/11/antigravity-context-guard-strategic-compact-plugin.webp&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Building Context Guard for Google Antigravity: Live Session Telemetry and Strategic Compaction&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;When you use &lt;strong&gt;Google Antigravity&lt;/strong&gt; to run long infrastructure sessions across six MCP servers (managing Docker containers on MS-01, Unraid 7 ZFS pools, UniFi Wi-Fi channels, Pangolin tunnels, and Wazuh SIEM rules), a single chat thread quickly accumulates over 100,000 tokens of tool output. Eventually you hit the context ceiling, and the engine compacts the conversation right in the middle of a multi-step debugging loop.&lt;/p&gt;
&lt;p&gt;In today&amp;rsquo;s post, I will show you how Antigravity&amp;rsquo;s native auto-compaction (&lt;code&gt;CHECKPOINT&lt;/code&gt;) works under the hood based on raw &lt;code&gt;transcript.jsonl&lt;/code&gt; telemetry, how I built and open-sourced the &lt;strong&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/wojciehm/antigravity-context-guard&#34;  title=&#34;antigravity-context-guard on GitHub&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;code&gt;antigravity-context-guard&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; plugin using &lt;code&gt;PreInvocation&lt;/code&gt; lifecycle hooks, and how I tracked down a Go protobuf reflection panic inside &lt;code&gt;language_server.log&lt;/code&gt; along the way.&lt;/p&gt;
&lt;h2 id=&#34;1-how-google-antigravity-handles-auto-compaction-under-the-hood&#34;&gt;1. How Google Antigravity Handles Auto-Compaction Under the Hood
&lt;/h2&gt;&lt;p&gt;Before writing any code, I wanted to verify whether Antigravity already compacts long sessions on its own and at what exact token count it fires. Every conversation in Antigravity writes a JSON Lines log at &lt;code&gt;~/.gemini/antigravity/brain/&amp;lt;conversation-id&amp;gt;/.system_generated/logs/transcript.jsonl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Each &lt;code&gt;PLANNER_RESPONSE&lt;/code&gt; step records three token counters for that model call:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;input_tokens&lt;/code&gt;: fresh uncached tokens sent in the current step,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cache_read_tokens&lt;/code&gt;: cached prefix tokens reused from prior turns,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;output_tokens&lt;/code&gt;: tokens generated by the model.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I ran a quick Python script against my longest homelab administration thread (&lt;code&gt;20,900+&lt;/code&gt; trajectory steps and 15 compactions) to inspect the active context size (&lt;code&gt;input_tokens + cache_read_tokens&lt;/code&gt;) right before every &lt;code&gt;CHECKPOINT&lt;/code&gt; event:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;Trajectory Step&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;Compaction Mode&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;Context Before (&lt;code&gt;input + cache&lt;/code&gt;)&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;Context Immediately After&lt;/th&gt;
					&lt;th style=&#34;text-align: left&#34;&gt;Trigger Source&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;Step #19796&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;MANUAL (/compact)&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;89,334&lt;/code&gt; tokens&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;~21,000&lt;/code&gt; tokens&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Manual &lt;code&gt;/compact&lt;/code&gt; command&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;Step #19929&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;&lt;code&gt;AUTO-COMPACT&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;&lt;code&gt;127,548&lt;/code&gt; tokens&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;21,100&lt;/code&gt; tokens&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Automatic mid-turn tool loop&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;Step #20024&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;&lt;code&gt;AUTO-COMPACT&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;&lt;code&gt;124,074&lt;/code&gt; tokens&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;21,050&lt;/code&gt; tokens&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Automatic mid-turn tool loop&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;Step #20274&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;&lt;code&gt;AUTO-COMPACT&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;&lt;code&gt;127,400&lt;/code&gt; tokens&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;21,126&lt;/code&gt; tokens&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Automatic after MCP dump&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;Step #20293&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;&lt;code&gt;AUTO-COMPACT&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;&lt;code&gt;126,522&lt;/code&gt; tokens&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;20,919&lt;/code&gt; tokens&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Automatic on user prompt&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;Step #20525&lt;/code&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;&lt;code&gt;AUTO-COMPACT&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;&lt;code&gt;129,313&lt;/code&gt; tokens&lt;/strong&gt;&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;&lt;code&gt;21,127&lt;/code&gt; tokens&lt;/td&gt;
					&lt;td style=&#34;text-align: left&#34;&gt;Automatic mid-task&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Three things stand out from the logs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The ~125k–128k Ceiling:&lt;/strong&gt; As soon as &lt;code&gt;input_tokens + cache_read_tokens&lt;/code&gt; crosses roughly &lt;strong&gt;124,000 to 128,000 tokens&lt;/strong&gt; ($2^{17} = 131,072$), Antigravity pauses execution, generates a structured &lt;code&gt;CHECKPOINT&lt;/code&gt; summary, and truncates the earlier history.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Baseline Context Cost:&lt;/strong&gt; Right after compaction, the session drops to &lt;strong&gt;~21,000 tokens&lt;/strong&gt;, which is the fixed footprint of the system prompt, &lt;code&gt;GEMINI.md&lt;/code&gt; workspace rules, and MCP tool declarations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why Native Auto-Compact Still Hurts:&lt;/strong&gt; Because native auto-compaction fires strictly on token count, it often triggers in the middle of a 10-step debugging loop right after a large &lt;code&gt;docker logs&lt;/code&gt; or &lt;code&gt;wazuh-logtest&lt;/code&gt; output. When that happens mid-task, the model keeps the high-level summary but loses fine details from the previous five tool calls.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the Claude Code community, engineers solve this with the &lt;strong&gt;Strategic Compact&lt;/strong&gt; pattern: instead of letting the runtime truncate your context at 128k mid-task, monitor the token counter and run &lt;code&gt;/compact&lt;/code&gt; manually at logical task boundaries once you cross ~70% of the budget.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;2-designing-the-context-guard-plugin-architecture&#34;&gt;2. Designing the &lt;code&gt;context-guard&lt;/code&gt; Plugin Architecture
&lt;/h2&gt;&lt;p&gt;Antigravity supports native &lt;strong&gt;Plugins&lt;/strong&gt; (&lt;code&gt;~/.gemini/config/plugins/&amp;lt;name&amp;gt;/&lt;/code&gt;) that bundle &lt;strong&gt;Lifecycle Hooks&lt;/strong&gt; (&lt;code&gt;hooks.json&lt;/code&gt;) and &lt;strong&gt;Skills&lt;/strong&gt; (&lt;code&gt;skills/&amp;lt;name&amp;gt;/SKILL.md&lt;/code&gt;) into a single toggleable package.&lt;/p&gt;
&lt;p&gt;Here is the directory structure of &lt;a class=&#34;link&#34; href=&#34;https://github.com/wojciehm/antigravity-context-guard&#34;  title=&#34;antigravity-context-guard on GitHub&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;code&gt;antigravity-context-guard&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/.gemini/config/plugins/context-guard/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── plugin.json                      # Plugin manifest
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── hooks.json                       # PreInvocation lifecycle hook registration
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── README.md                        # Documentation
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── assets/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── logo.svg                     # Custom gauge icon for the Customizations UI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── scripts/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── context_monitor.py           # Fast (&amp;lt;5ms) PreInvocation hook script
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── context_status.py            # On-demand CLI telemetry &amp;amp; history analyzer
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── skills/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └── context-guard/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        └── SKILL.md                 # Slash command (/context-guard) instructions
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://www.wojcieh.net/images/uploads/2026/11/antigravity-context-guard-banner-live.webp&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Live Context Guard Warning Banner in Google Antigravity Chat&#34;
	
	
&gt;&lt;/p&gt;
&lt;h3 id=&#34;how-the-threshold-tiers-work&#34;&gt;How the Threshold Tiers Work
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Optimal Tier (&lt;code&gt;&amp;lt; 85,000&lt;/code&gt; tokens / &lt;code&gt;&amp;lt; 68%&lt;/code&gt;):&lt;/strong&gt; &lt;code&gt;context_monitor.py&lt;/code&gt; outputs &lt;code&gt;{}&lt;/code&gt; and exits in under 5 milliseconds. Zero UI clutter and zero extra tokens in the conversation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Warning Tier (&lt;code&gt;85,000 – 104,999&lt;/code&gt; tokens / &lt;code&gt;68%–84%&lt;/code&gt;):&lt;/strong&gt; Fires once at the start of a user turn (&lt;code&gt;invocationNum &amp;lt;= 1&lt;/code&gt;), displays the inline &lt;code&gt;🟡 Context Guard&lt;/code&gt; progress bar at the top of the reply, and instructs the agent to delegate heavy log exploration to subagents (&lt;code&gt;invoke_subagent&lt;/code&gt;, which run in isolated context windows).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Critical Tier (&lt;code&gt;&amp;gt;= 105,000&lt;/code&gt; tokens / &lt;code&gt;&amp;gt;= 84%&lt;/code&gt;):&lt;/strong&gt; Displays the &lt;code&gt;🔴 Context Guard&lt;/code&gt; critical alert showing exact remaining token headroom (or overshoot) and advises running &lt;code&gt;/compact&lt;/code&gt; as soon as the current response finishes.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;3-debugging-a-go-protobuf-panic-in-language_serverlog&#34;&gt;3. Debugging a Go Protobuf Panic in &lt;code&gt;language_server.log&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;When I wrote the first version of &lt;code&gt;context_monitor.py&lt;/code&gt;, I used the &lt;code&gt;systemMessage.metadata.user_markdown&lt;/code&gt; field from the hooks documentation to render a user-only UI banner:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;injectSteps&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;systemMessage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;systemMessage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;user_markdown&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;🟡 **Context Guard...**&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The script ran and updated its state file in &lt;code&gt;/tmp/agy-context-guard/&lt;/code&gt;, but nothing showed up in the chat UI. Digging into &lt;code&gt;~/.config/Antigravity/logs/language_server.log&lt;/code&gt; explained why:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;E1110 09:51:26.785106 26745 hookcaller.go:46] hook &amp;#34;jsonhook__context-guard-monitor_PreInvocation_0_0&amp;#34; panicked: type mismatch: cannot convert string to message
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  third_party/golang/protobuf/v2/reflect/protoreflect/value_union.go:346 +0xc9
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  google3/third_party/jetski/cortex/utils/utils.scrubMessage.1.1(...)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    third_party/jetski/cortex/utils/proto_utils.go:34 +0x35
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  google3/third_party/golang/protobuf/v2/internal/impl/impl.(*mapReflect).Range(...)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    third_party/golang/protobuf/v2/internal/impl/convert_map.go:108 +0x18a
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note / Gotcha:&lt;/strong&gt; Inside Antigravity&amp;rsquo;s Go backend, &lt;code&gt;utils.scrubMessage&lt;/code&gt; (&lt;code&gt;proto_utils.go:34&lt;/code&gt;) walks every field of the unmarshaled hook response to scrub sensitive strings before logging. When it encounters a non-empty Protobuf &lt;code&gt;map&amp;lt;string, string&amp;gt;&lt;/code&gt; (like &lt;code&gt;systemMessage.metadata&lt;/code&gt;), its &lt;code&gt;mapReflect.Range&lt;/code&gt; callback calls &lt;code&gt;val.Message()&lt;/code&gt; on the string map value and panics with &lt;code&gt;cannot convert string to message&lt;/code&gt;. Do not pass &lt;code&gt;metadata&lt;/code&gt; maps in &lt;code&gt;PreInvocation&lt;/code&gt; hook outputs until that bug is fixed upstream.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Switching the hook output from &lt;code&gt;systemMessage.metadata&lt;/code&gt; to a plain string &lt;code&gt;ephemeralMessage&lt;/code&gt; (&lt;code&gt;{&amp;quot;injectSteps&amp;quot;: [{&amp;quot;ephemeralMessage&amp;quot;: &amp;quot;...&amp;quot;}]}&lt;/code&gt;) bypasses &lt;code&gt;mapReflect.Range&lt;/code&gt; completely. Better yet, &lt;code&gt;ephemeralMessage&lt;/code&gt; is dropped after the current turn, so it never adds permanent tokens to the trajectory.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;4-installation-and-usage&#34;&gt;4. Installation and Usage
&lt;/h2&gt;&lt;p&gt;I published the full plugin on &lt;a class=&#34;link&#34; href=&#34;https://github.com/wojciehm/antigravity-context-guard&#34;  title=&#34;antigravity-context-guard on GitHub&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub (&lt;code&gt;wojciehm/antigravity-context-guard&lt;/code&gt;)&lt;/a&gt; and &lt;a class=&#34;link&#34; href=&#34;https://codeberg.org/wojcieh/antigravity-context-guard&#34;  title=&#34;antigravity-context-guard on Codeberg&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Codeberg (&lt;code&gt;wojcieh/antigravity-context-guard&lt;/code&gt;)&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Clone the repository directly into your global Antigravity plugins directory:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/wojciehm/antigravity-context-guard.git ~/.gemini/config/plugins/context-guard
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Validate the plugin bundle using the Antigravity CLI:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;agy plugin validate ~/.gemini/config/plugins/context-guard
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [ok]    /home/wojcieh/.gemini/config/plugins/context-guard
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          ✔ skills      : 1 processed
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          - agents      : skipped (not found)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          - commands    : skipped (not found)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          - mcpServers  : skipped (not found)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          ✔ hooks       : 1 processed
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;Restart Antigravity once so the runtime loads the new plugin. From then on, &lt;code&gt;PreInvocation&lt;/code&gt; monitors your active sessions automatically, and you can also run &lt;code&gt;/context-guard&lt;/code&gt; at any time to inspect live token telemetry and compaction history across your recent chats.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;Having live visibility into &lt;code&gt;input_tokens + cache_read_tokens&lt;/code&gt; changes how you manage long coding and homelab sessions. Instead of getting blindsided by an automatic &lt;code&gt;CHECKPOINT&lt;/code&gt; halfway through debugging a Traefik mTLS route or a Wazuh decoder, &lt;code&gt;context-guard&lt;/code&gt; warns me right when a thread hits 68% capacity so I can finish the current step and run &lt;code&gt;/compact&lt;/code&gt; on my own terms.&lt;/p&gt;</description>
        </item>
        
    </channel>
</rss>
