<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Context-Window on Nick Liu - Software Engineer</title><link>https://nick-liu.com/tags/context-window/</link><description>Recent content in Context-Window on Nick Liu - Software Engineer</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>nickboy@users.noreply.github.com (Nick Liu)</managingEditor><webMaster>nickboy@users.noreply.github.com (Nick Liu)</webMaster><copyright>2026 Nick Liu</copyright><lastBuildDate>Sun, 30 Aug 2026 00:52:14 -0700</lastBuildDate><atom:link href="https://nick-liu.com/tags/context-window/index.xml" rel="self" type="application/rss+xml"/><item><title>The context percentage is a division. Nothing tells you the denominator.</title><link>https://nick-liu.com/posts/context-window-denominator/</link><pubDate>Mon, 07 Sep 2026 00:00:00 +0000</pubDate><author>nickboy@users.noreply.github.com (Nick Liu)</author><guid>https://nick-liu.com/posts/context-window-denominator/</guid><description>&lt;div class="lead text-neutral-500 dark:text-neutral-400 !mb-9 text-xl"&gt;&#10; &#10;Showing "this session is 34% full" requires two numbers. The token count is easy and always right. The window size it divides by is not in the transcript, not in the session state files, not in settings, and not in any hook payload. It exists in exactly one place, and if you cannot read that place you are guessing at the denominator of a number you are about to display as fact.&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;div class="tested-with" role="note"&gt;&#10; &lt;span class="tested-with-icon" aria-hidden="true"&gt;🧪&lt;/span&gt;&#10; &lt;span&gt;Tested with &lt;strong&gt;Claude Code&lt;/strong&gt; &lt;code&gt;2.1.x&lt;/code&gt; · macOS&lt;/span&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;I built a script that reports how full a Claude Code session&amp;rsquo;s context window is, so a Stream Deck key could draw a ring for it. The token side was straightforward. The denominator turned into the whole project.&lt;/p&gt;</description><content:encoded>&lt;div class="lead text-neutral-500 dark:text-neutral-400 !mb-9 text-xl"&gt;&#10; &#10;Showing "this session is 34% full" requires two numbers. The token count is easy and always right. The window size it divides by is not in the transcript, not in the session state files, not in settings, and not in any hook payload. It exists in exactly one place, and if you cannot read that place you are guessing at the denominator of a number you are about to display as fact.&#10;&#10;&lt;/div&gt;&#10;&#10;&lt;div class="tested-with" role="note"&gt;&#10; &lt;span class="tested-with-icon" aria-hidden="true"&gt;🧪&lt;/span&gt;&#10; &lt;span&gt;Tested with &lt;strong&gt;Claude Code&lt;/strong&gt; &lt;code&gt;2.1.x&lt;/code&gt; · macOS&lt;/span&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;I built a script that reports how full a Claude Code session&amp;rsquo;s context window is, so a Stream Deck key could draw a ring for it. The token side was straightforward. The denominator turned into the whole project.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Five places the window size is not&#10; &lt;div id="five-places-the-window-size-is-not" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#five-places-the-window-size-is-not" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;I checked each of these against a live session rather than reasoning about what ought to be there.&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Source&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Has the window size?&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;statusline payload&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;yes&lt;/strong&gt;, as &lt;code&gt;context_window.context_window_size&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;transcript &lt;code&gt;.jsonl&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;no. &lt;code&gt;message.model&lt;/code&gt; drops the &lt;code&gt;[1m]&lt;/code&gt; long-context marker&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;~/.claude/sessions/&amp;lt;pid&amp;gt;.json&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;no&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;only the &lt;em&gt;default&lt;/em&gt; model, which is wrong after a &lt;code&gt;/model&lt;/code&gt; switch&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;hook payloads&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;no, and the hooks documentation says so&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;The transcript row is the one that stings, because the transcript is otherwise a perfect source: it is on disk, Claude Code writes it without being asked, and reading it changes nothing. It carries &lt;code&gt;message.model&lt;/code&gt;. What it does not carry is whether that session is running the long-context variant, because the marker is dropped from the model string it records.&lt;/p&gt;&#10;&lt;p&gt;The transcript can tell you which model. It can never tell you which window.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Why I rejected a model-to-window lookup table&#10; &lt;div id="why-i-rejected-a-model-to-window-lookup-table" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#why-i-rejected-a-model-to-window-lookup-table" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;The obvious fix is a table: model name in, window size out. I decided against it, and not because tables are inelegant.&lt;/p&gt;&#10;&lt;p&gt;A lookup table rots on every model release, and it rots in the bad direction. It does not throw. It does not warn. A model it has never heard of falls through to whatever default the author picked, and the tool goes on confidently reporting a percentage computed against the wrong denominator. Being silently wrong about a percentage is worse than showing nothing, because a number on a screen gets read as a measurement.&lt;/p&gt;&#10;&lt;p&gt;There is a real API answer here and it is worth stating precisely, because it is &lt;em&gt;almost&lt;/em&gt; the fix. Anthropic&amp;rsquo;s Models API returns &lt;code&gt;max_input_tokens&lt;/code&gt; per model id: machine-readable, and it does not rot. What it cannot do is disambiguate a variant that is not a distinct model id. &lt;code&gt;[1m]&lt;/code&gt; is a session-level marker rather than something you can look up, and it is the exact thing the transcript drops. So you would be querying the right API with a key that has already lost the distinction you care about, and getting a confident answer to a question you did not ask.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;What the script does instead&#10; &lt;div id="what-the-script-does-instead" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#what-the-script-does-instead" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;One assumption, named, in one place, with an override and a clamp:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# The one assumption in this script. Not a model-&amp;gt;window table on purpose:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# such a table rots on every model release, and being silently wrong about&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# a percentage is worse than not showing one.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;CONTEXT_WINDOW_TOKENS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HERDDECK_CONTEXT_WINDOW&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;Three properties of that shape matter more than the value itself.&lt;/p&gt;&#10;&lt;p&gt;It is one constant rather than a table, so there is exactly one thing to be wrong about and one thing to change. It takes an environment override, so a machine running a different window fixes itself without a code change. And the overrun clamps:&lt;/p&gt;&#10;&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;CONTEXT_WINDOW_TOKENS&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#10;&lt;p&gt;That clamp does real work. Without it, a session in a larger window than the constant assumes draws a ring at 216%, which is less a display bug than a confession. Clamping to 100 turns &amp;ldquo;my assumption is wrong&amp;rdquo; into &amp;ldquo;this session is full&amp;rdquo;, which is at least the right shape of wrong.&lt;/p&gt;&#10;&lt;p&gt;The deeper point is that only the &lt;em&gt;final division&lt;/em&gt; depends on the guess. The token count, which is what the script actually derives from the transcript, is always correct. Show tokens and you are reporting. Show a percentage and you are asserting.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Two routes, and why both exist&#10; &lt;div id="two-routes-and-why-both-exist" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#two-routes-and-why-both-exist" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;There are two ways to get this number and they are not equivalent:&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;statusline&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;transcript scan&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Percentage&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;exact, computed by Claude Code&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;needs the window constant&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Coverage&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;every session&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;needed two fallbacks to match&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Cost&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;none&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;one polling process&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Requires&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;editing that machine&amp;rsquo;s statusline&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;nothing&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;The statusline route wins wherever the statusline is yours to edit, because Claude Code resolves the window itself and hands over an already-computed &lt;code&gt;used_percentage&lt;/code&gt;. Reading a number somebody else computed correctly is the only approach here that cannot rot.&lt;/p&gt;&#10;&lt;p&gt;The scan exists for machines where the statusline is not yours. A company-managed statusline you must not touch is a real constraint, and the scan reads only files Claude Code already writes while changing nothing in anyone&amp;rsquo;s configuration.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Running both against four live sessions&#10; &lt;div id="running-both-against-four-live-sessions" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#running-both-against-four-live-sessions" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;p&gt;Agreement between two independent routes is the only verification available when there is no ground truth to check against, so I ran them side by side. Three sessions agreed exactly: 34/34, 43/43, 16/16. The fourth converged once its turn completed.&lt;/p&gt;&#10;&lt;p&gt;Getting there took two fixes that only live data surfaced.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;One pane out of four had no session id.&lt;/strong&gt; herdr resolved three of four Claude panes and the fourth came back with &lt;code&gt;agent_session: null&lt;/code&gt;. The fix needed no configuration: &lt;code&gt;claude agents --json&lt;/code&gt; maps pid to session id, and herdr already knows each pane&amp;rsquo;s processes, so joining the two closes the gap.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;That same pane was rate-limited, and its transcript lied.&lt;/strong&gt; A rate-limited session&amp;rsquo;s transcript ends in &lt;code&gt;&amp;lt;synthetic&amp;gt;&lt;/code&gt; records flagged &lt;code&gt;isApiErrorMessage&lt;/code&gt;, carrying all-zero usage. Six of them in a row, in this case.&lt;/p&gt;&#10;&lt;p&gt;Read the newest usage record blindly and you get &lt;strong&gt;0% for a session actually sitting at 34%&lt;/strong&gt;. Not a small error, and not a random one. It always reports empty, and it reports empty exactly when the session is in trouble, which is when you are most likely to be looking at the key. &amp;ldquo;Use the newest record&amp;rdquo; is a reasonable-sounding heuristic that happens to select for the records carrying no information.&lt;/p&gt;&#10;&lt;p&gt;The fix is to skip records flagged as API errors while scanning backwards for the last real usage figure. Obvious once you have seen it, invisible until a session gets rate-limited while you happen to be watching.&lt;/p&gt;&#10;&#10;&lt;h2 class="relative group"&gt;Lessons&#10; &lt;div id="lessons" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#lessons" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;A percentage is a division, and the denominator deserves as much scrutiny as the numerator. Report the number you measured; you are only asserting the one you derived.&lt;/li&gt;&#10;&lt;li&gt;Prefer one named constant to a lookup table when neither is discoverable. A table rots per release and keeps answering; a constant is one thing to be wrong about and one thing to fix.&lt;/li&gt;&#10;&lt;li&gt;Clamp derived percentages at both ends. A 216% ring is your assumption failing in public, and the clamp converts it into the least-wrong reading available.&lt;/li&gt;&#10;&lt;li&gt;A machine-readable API answer is only useful if your key is unambiguous. Per-model context windows do not help when the field you hold has already dropped the variant marker.&lt;/li&gt;&#10;&lt;li&gt;When two independent routes to a number exist, run both against live data and compare. Exact agreement on three sessions surfaced two bugs neither route would have revealed alone.&lt;/li&gt;&#10;&lt;li&gt;Read the flags on a record before trusting its contents. Synthetic error records with zero usage will cheerfully answer &amp;ldquo;0%&amp;rdquo; for a session at 34%, and they show up precisely when things are going wrong.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&#10;&lt;h2 class="relative group"&gt;References&#10; &lt;div id="references" class="anchor"&gt;&lt;/div&gt;&#10; &#10; &lt;span&#10; class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;&#10; &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#references" aria-label="Anchor"&gt;#&lt;/a&gt;&#10; &lt;/span&gt;&#10; &#10;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Claude Code statusline docs, the payload carrying &lt;code&gt;context_window.context_window_size&lt;/code&gt;: &lt;a href="https://code.claude.com/docs/en/statusline" target="_blank" rel="noreferrer"&gt;https://code.claude.com/docs/en/statusline&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Claude Code hooks reference, on what hook payloads carry: &lt;a href="https://code.claude.com/docs/en/hooks" target="_blank" rel="noreferrer"&gt;https://code.claude.com/docs/en/hooks&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Anthropic models overview, per-model context windows: &lt;a href="https://platform.claude.com/docs/en/about-claude/models/overview" target="_blank" rel="noreferrer"&gt;https://platform.claude.com/docs/en/about-claude/models/overview&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;The statusline side channel this builds on: &lt;a href="https://nick-liu.com/posts/statusline-side-channel/" &gt;The Claude Code statusline is a per-turn telemetry side channel&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;The ring this feeds: &lt;a href="https://nick-liu.com/posts/herddeck-frozen-context-ring/" &gt;Every context ring read 10%. Two bugs, and fixing one hid the other.&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;herddeck-ctx-scan&lt;/code&gt;, the transcript scanner: &lt;a href="https://github.com/nickboy/herddeck/blob/main/scripts/herddeck-ctx-scan" target="_blank" rel="noreferrer"&gt;https://github.com/nickboy/herddeck/blob/main/scripts/herddeck-ctx-scan&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</content:encoded></item></channel></rss>