<?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>Ai on Christian Roy</title>
    <link>https://christianroy.dev/tags/ai/</link>
    <description>Recent content in Ai on Christian Roy</description>
    <generator>Hugo -- 0.156.0</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 07 Jul 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://christianroy.dev/tags/ai/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>The RAID Array That Kept Losing a Disk on Every Reboot</title>
      <link>https://christianroy.dev/til/raid-array-losing-disk-every-reboot/</link>
      <pubDate>Tue, 07 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/raid-array-losing-disk-every-reboot/</guid>
      <description>&lt;p&gt;&lt;em&gt;A NAS owner&amp;rsquo;s account of a firmware bug that dropped a healthy disk on every boot, and how I used Claude Code to reverse-engineer the fix out of the closed-source firmware.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A quick note on this post before we start: the NAS is mine, the problem was mine, and the tests (and the swearing) were mine. The deep reverse-engineering, disassembling the firmware&amp;rsquo;s own binaries and tracing data flow instruction by instruction, was done by Claude Code, which I drove and second-guessed throughout. So when you read &amp;ldquo;Claude found,&amp;rdquo; that is literally what happened. When you read &amp;ldquo;I rebooted and it was still broken,&amp;rdquo; that is me being the reality check. It was a genuine back-and-forth, and it is worth being honest about who did which part.&lt;/p&gt;</description>
    </item>
    <item>
      <title>NOVA·FM: an endless AI radio station built on Stable Audio 3</title>
      <link>https://christianroy.dev/til/novafm-endless-ai-radio-station-stable-audio-3/</link>
      <pubDate>Sun, 31 May 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/novafm-endless-ai-radio-station-stable-audio-3/</guid>
      <description>&lt;p&gt;NOVA·FM is a radio station with no library and no playlist. Every
track is composed on the spot, seconds before it reaches your ears,
then fades and is never reheard in quite the same shape. I built it
in two days with Claude Code (Opus 4.7 and 4.8), guided by me, on
top of Stable Audio 3, Stability AI&amp;rsquo;s open-weight audio model family
released earlier this month.&lt;/p&gt;
&lt;p&gt;More than seven stations so far, each a mood rather than a folder:
lo-fi, synthwave, cinematic, deep house, jazz, ambient, classical,
and a few more I keep adding. Two ways to listen: a private dial
that&amp;rsquo;s just for you, and a shared live signal where everyone tuned
in hears the same track at the same second.&lt;/p&gt;</description>
    </item>
    <item>
      <title>opencode with a local Qwen3.6-35B-A3B backend iterated to a working color-physics web toy</title>
      <link>https://christianroy.dev/til/opencode-local-qwen36-35b-a3b-color-physics-web-toy/</link>
      <pubDate>Thu, 14 May 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/opencode-local-qwen36-35b-a3b-color-physics-web-toy/</guid>
      <description>&lt;p&gt;I gave &lt;a href=&#34;https://opencode.ai&#34;&gt;opencode&lt;/a&gt; a single-paragraph spec for &amp;ldquo;an HTML
canvas where colored circles attract similar hues and repel opposites,&amp;rdquo; and
pointed it at unsloth&amp;rsquo;s quant of Qwen3.6-35B-A3B (UD-Q8_K_XL, ~3B active
params) running locally. About a dozen steering turns later, fixing bugs and
nudging the behavior, I had a working single-file demo.&lt;/p&gt;
&lt;p&gt;That is the part worth noting. Not one-shot, not magic: a small MoE that
fits on one GPU, driven through an agentic loop, can converge on a real
interactive artifact in a reasonable session. Local coding agents are
becoming a usable workflow, not just a demo.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Gemini 3.1 Flash Live: Low-latency voice AI with native audio output</title>
      <link>https://christianroy.dev/til/gemini-3-1-flash-live-low-latency-voice-ai/</link>
      <pubDate>Fri, 27 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/gemini-3-1-flash-live-low-latency-voice-ai/</guid>
      <description>&lt;p&gt;Google launched Gemini 3.1 Flash Live via the Live API for building real-time voice and vision agents. The model processes continuous audio, video, and text streams to deliver immediate spoken responses with acoustic nuance detection and 90+ language support.&lt;/p&gt;
&lt;p&gt;Key improvements over Gemini 2.5 Flash Native Audio:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Better noise filtering in real-world environments&lt;/li&gt;
&lt;li&gt;Stronger adherence to complex system instructions&lt;/li&gt;
&lt;li&gt;More natural dialogue with improved latency&lt;/li&gt;
&lt;li&gt;Thinking capability via &lt;code&gt;thinkingLevel&lt;/code&gt; (minimal/low/medium/high) instead of &lt;code&gt;thinkingBudget&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The model outputs native audio (no STT+TTS pipeline) with a 128k context window. It supports synchronous function calling, Google Search grounding, and video input alongside audio.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Asana&#39;s official Claude MCP connector can&#39;t create tasks in Claude Code CLI because its tools require interactive UI</title>
      <link>https://christianroy.dev/til/asana-mcp-create-task-claude-code-cli/</link>
      <pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/asana-mcp-create-task-claude-code-cli/</guid>
      <description>&lt;p&gt;Asana&amp;rsquo;s official Claude connector uses a tool called &lt;code&gt;create_task_preview&lt;/code&gt; instead of
&lt;code&gt;create_task&lt;/code&gt;. The name suggests a preview, but it&amp;rsquo;s actually the primary creation tool
in the v2 integration. The catch: it requires an interactive UI to render a confirmation
step. Claude Code CLI can&amp;rsquo;t render that interface, so task creation silently fails.&lt;/p&gt;
&lt;p&gt;This was surfaced in the Asana forum after &lt;code&gt;create_task&lt;/code&gt; also went missing from v1 toolset
temporarily (Asana accidentally dropped it during a v2 update, now restored). Asana
confirmed the CLI issue separately and said they&amp;rsquo;re working on detecting whether the surface
supports interactivity before offering interactive tools. ETA: about a week from March 26.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Cohere Transcribe beats Whisper Large v3 on the HuggingFace ASR leaderboard with a 2B open-source model</title>
      <link>https://christianroy.dev/til/cohere-transcribe-asr-beats-whisper/</link>
      <pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/cohere-transcribe-asr-beats-whisper/</guid>
      <description>&lt;p&gt;Cohere, best known for text and embedding models, just shipped a speech recognition model
that hits #1 on the HuggingFace Open ASR Leaderboard: 5.42% average WER versus Whisper
Large v3&amp;rsquo;s 7.44%. It&amp;rsquo;s 2B parameters, Apache 2.0, available on HuggingFace today.&lt;/p&gt;
&lt;p&gt;The architecture is a Conformer: a hybrid of CNNs and Transformers. CNNs handle local
acoustic features (phonemes, rapid transitions), Transformers handle global context.
Interleaving them is the standard trick for ASR; Cohere&amp;rsquo;s bet is that a dedicated,
from-scratch training run focused on WER beats the generalist approach.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tencent&#39;s Covo-Audio is a 7B end-to-end audio model with full-duplex conversation via THINK, SHIFT, and BREAK tokens</title>
      <link>https://christianroy.dev/til/covo-audio-tencent-full-duplex-audio-llm/</link>
      <pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/covo-audio-tencent-full-duplex-audio-llm/</guid>
      <description>&lt;p&gt;Most voice AI pipelines are cascaded: ASR transcribes, an LLM reasons, TTS speaks.
Covo-Audio collapses all three into a single 7B model that takes audio in and produces
audio out, built on Qwen2.5-7B with a Whisper-large-v3 encoder.&lt;/p&gt;
&lt;p&gt;The full-duplex variant (Covo-Audio-Chat-FD) is the interesting part. It handles
simultaneous listening and speaking using three special tokens baked into the architecture:
THINK (listening, not yet responding), SHIFT (switching to speaking turn), and BREAK (user
interrupted, stop speaking immediately). Each audio chunk is 0.16 seconds. The model and
user streams are interleaved at a 1:4 ratio.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Google&#39;s TurboQuant compresses LLM KV caches 6x with zero accuracy loss and near-zero indexing time</title>
      <link>https://christianroy.dev/til/turboquant-google-kv-cache-compression/</link>
      <pubDate>Wed, 25 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/turboquant-google-kv-cache-compression/</guid>
      <description>&lt;p&gt;The KV cache is a major memory bottleneck for long-context LLM inference. Traditional
vector quantization methods like Product Quantization require expensive dataset-specific
codebook training that can take hundreds of seconds. TurboQuant, from Google Research
(ICLR 2026), is data-oblivious: no training, no calibration, works instantly.&lt;/p&gt;
&lt;p&gt;The key insight: applying a random rotation to input vectors induces a concentrated Beta
distribution on each coordinate in high dimensions, making coordinates nearly i.i.d. This
lets you solve a simple 1D scalar quantization problem per coordinate instead of a complex
joint optimization. Codebooks are precomputed once per bit-width and reused at inference
time.&lt;/p&gt;</description>
    </item>
    <item>
      <title>TinyLoRA fine-tunes a 7B model to 91.8% GSM8K accuracy with only 13 parameters using RL</title>
      <link>https://christianroy.dev/til/tinylora-13-parameters-fine-tuning/</link>
      <pubDate>Tue, 24 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/tinylora-13-parameters-fine-tuning/</guid>
      <description>&lt;p&gt;A Qwen2.5-7B-Instruct model fine-tuned with 13 trainable parameters (26 bytes in bf16)
reaches 91.8% on GSM8K. Full fine-tuning of all 7.6 billion parameters reaches 91.7%.
That number is not a typo, and yes, they are the same kind of parameters.&lt;/p&gt;
&lt;p&gt;To understand why this is possible, you need to know what those 13 parameters actually do.
They are not 13 weights replacing 7.6 billion others. They are 13 scalar values that get
projected through a fixed random tensor into a high-dimensional update, which then gets
added back into the frozen weight matrices across all layers. You are not tuning 13 knobs
instead of 7.6 billion - you are tuning 13 directions of change that each affect the whole
model via a fixed mathematical transformation. The frozen weights do all the heavy lifting;
the tiny update steers them.&lt;/p&gt;</description>
    </item>
    <item>
      <title>GitAgent defines AI agents as git repos, exportable to any framework with one CLI command</title>
      <link>https://christianroy.dev/til/gitagent-ai-agents-as-git-repos/</link>
      <pubDate>Sat, 21 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/gitagent-ai-agents-as-git-repos/</guid>
      <description>&lt;p&gt;GitAgent proposes that your git repository &lt;em&gt;is&lt;/em&gt; your agent. Two required files -
&lt;code&gt;agent.yaml&lt;/code&gt; (manifest) and &lt;code&gt;SOUL.md&lt;/code&gt; (identity) - define the agent. Everything
else - skills, tools, memory, compliance artifacts - is optional structure layered
on top.&lt;/p&gt;
&lt;p&gt;The interesting part is the supervision model: when an agent updates its memory or
acquires a new skill, the change becomes a git commit or PR. Human reviewers can
diff the agent&amp;rsquo;s personality changes like any code review. If behavior drifts,
&lt;code&gt;git revert&lt;/code&gt; brings it back.&lt;/p&gt;</description>
    </item>
    <item>
      <title>NVIDIA&#39;s Nemotron-Cascade 2 hits gold-medal math and coding with a 30B MoE using only 3B active parameters</title>
      <link>https://christianroy.dev/til/nemotron-cascade-2-moe-gold-medal-math-coding/</link>
      <pubDate>Fri, 20 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/nemotron-cascade-2-moe-gold-medal-math-coding/</guid>
      <description>&lt;p&gt;Nemotron-Cascade 2 is a 30B Mixture-of-Experts model that only activates 3B
parameters per forward pass. It&amp;rsquo;s the second open-weight model to reach gold-medal
level on IMO 2025, IOI 2025, and ICPC World Finals - after DeepSeek at 671B, which
is more than 20x the size.&lt;/p&gt;
&lt;p&gt;The core technique is Cascade RL: sequential domain-by-domain reinforcement learning,
where each domain (math, code, instruction following, SWE agents) gets its own
hyperparameters without destabilizing the others. The novel addition is Multi-Domain
On-Policy Distillation (MOPD): when a Cascade RL stage causes regression on other
benchmarks, they distill from the best intermediate teacher model for that domain
on the fly. On AIME 2025, MOPD reached teacher-level performance in 30 steps; GRPO
hit only 91.0 after the same number of steps.&lt;/p&gt;</description>
    </item>
    <item>
      <title>GLM-OCR: A 0.9B document parsing specialist beats 235B models</title>
      <link>https://christianroy.dev/til/glm-ocr-zhipu-ai-document-parsing-specialist/</link>
      <pubDate>Thu, 19 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/glm-ocr-zhipu-ai-document-parsing-specialist/</guid>
      <description>&lt;p&gt;GLM-OCR is a 0.9B multimodal OCR model that achieves 94.62 on OmniDocBench V1.5, ranking first overall despite its compact size. Built by Zhipu AI, it beats Qwen3-VL-235B (260× more parameters) and Gemini-3 Pro on document parsing benchmarks.&lt;/p&gt;
&lt;p&gt;The model combines a 0.4B CogViT visual encoder with a 0.5B GLM language decoder. Its key innovation is Multi-Token Prediction (MTP), which predicts 10 tokens per step instead of one. For OCR—a deterministic task—you&amp;rsquo;re copying characters, not sampling creative text. This delivers about 50% higher throughput vs standard decoding.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Baidu&#39;s Qianfan-OCR collapses the multi-stage OCR pipeline into one 4B model with Layout-as-Thought</title>
      <link>https://christianroy.dev/til/qianfan-ocr-layout-as-thought-document-intelligence/</link>
      <pubDate>Wed, 18 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/qianfan-ocr-layout-as-thought-document-intelligence/</guid>
      <description>&lt;p&gt;Traditional OCR pipelines chain at least three models: a layout detector, a text
recognizer, and a language model for understanding. Qianfan-OCR replaces all three
with a single 4B model that goes directly from image to Markdown.&lt;/p&gt;
&lt;p&gt;The key innovation is Layout-as-Thought: appending a &lt;code&gt;&amp;lt;think&amp;gt;&lt;/code&gt; token to any prompt
triggers an optional reasoning phase where the model explicitly works through bounding
boxes, element types, and reading order before producing output. It&amp;rsquo;s Chain-of-Thought
for document layout - and it&amp;rsquo;s optional, so you can skip it for simple single-column
documents to save latency.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Google&#39;s Colab MCP server lets any AI agent create and run notebooks in the cloud</title>
      <link>https://christianroy.dev/til/colab-mcp-server-ai-agents-notebooks/</link>
      <pubDate>Wed, 18 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/colab-mcp-server-ai-agents-notebooks/</guid>
      <description>&lt;p&gt;Google released an open-source MCP server for Google Colab. Any MCP-compatible
agent - Claude Code, Gemini CLI, or a custom agent - can now programmatically
control a Colab notebook: create cells, write and execute code, install
dependencies, rearrange content.&lt;/p&gt;
&lt;p&gt;The setup is one config block:&lt;/p&gt;
&lt;div class=&#34;highlight&#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;s2&#34;&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#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;colab-mcp&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;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;uvx&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;args&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 class=&#34;s2&#34;&gt;&amp;#34;git+https://github.com/googlecolab/colab-mcp&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;timeout&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;30000&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;/div&gt;&lt;p&gt;The motivation is concrete: developers were copying code from their terminals
into Colab cells to run or visualize things. That context switch kills flow.
With this server, the agent writes directly into an open notebook - you get a
reproducible, executable artifact in the cloud instead of a code snippet in
your terminal.&lt;/p&gt;</description>
    </item>
    <item>
      <title>NVIDIA&#39;s OpenShell enforces AI agent guardrails outside the agent process so a compromised agent can&#39;t override them</title>
      <link>https://christianroy.dev/til/nvidia-openshell-out-of-process-agent-guardrails/</link>
      <pubDate>Tue, 17 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/nvidia-openshell-out-of-process-agent-guardrails/</guid>
      <description>&lt;p&gt;The problem with agent guardrails that live inside the agent: a compromised agent
can override them. Claude Code and Cursor ship with internal safety prompts, but
those protections are inside the same process they&amp;rsquo;re supposed to guard. A prompt
injection or a bad third-party skill has access to the same runtime.&lt;/p&gt;
&lt;p&gt;NVIDIA OpenShell moves the enforcement point outside. It wraps any agent in an
isolated container with YAML-defined policies the agent cannot read or modify.
Network access is deny-by-default and hot-reloadable; filesystem and process
constraints are locked at creation. The agent can&amp;rsquo;t escalate privileges because
the kernel won&amp;rsquo;t allow it - not because the agent was told not to.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Unsloth Studio is an open-source no-code UI for training and running local LLMs</title>
      <link>https://christianroy.dev/til/unsloth-studio-no-code-local-llm-training/</link>
      <pubDate>Tue, 17 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/unsloth-studio-no-code-local-llm-training/</guid>
      <description>&lt;p&gt;Unsloth Studio bundles local inference, fine-tuning, and model export into a single
no-code web UI. One curl command installs it; then you can run GGUF or safetensor
models on Mac, Windows, or Linux without writing any code.&lt;/p&gt;
&lt;p&gt;The training side is the main draw: 2x faster fine-tuning with 70% less VRAM across
500+ model families (text, vision, TTS, embeddings). LoRA, FP8, and full fine-tuning
all work on NVIDIA hardware, with multi-GPU support already in.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Mistral Small 4 merges instruct, reasoning, and coding into one model with per-request reasoning effort</title>
      <link>https://christianroy.dev/til/mistral-small-4-unified-instruct-reasoning-coding/</link>
      <pubDate>Mon, 16 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/mistral-small-4-unified-instruct-reasoning-coding/</guid>
      <description>&lt;p&gt;Mistral Small 4 replaces three separate Mistral models - Magistral for reasoning,
Devstral for coding agents, and Mistral Small for instruct - with a single 119B MoE
model (128 experts, 4 active, 6.5B active params per token). You pick the behavior
per request with a &lt;code&gt;reasoning_effort&lt;/code&gt; parameter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;reasoning_effort=&amp;quot;none&amp;quot;&lt;/code&gt;: fast chat-style responses, equivalent to Mistral Small 3.2&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reasoning_effort=&amp;quot;high&amp;quot;&lt;/code&gt;: deep step-by-step reasoning, equivalent to Magistral&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Same weights, same deployment, different behavior at inference time.&lt;/p&gt;</description>
    </item>
    <item>
      <title>OpenViking: A context database using filesystem paradigm for AI agents</title>
      <link>https://christianroy.dev/til/openviking-context-database-ai-agents/</link>
      <pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/openviking-context-database-ai-agents/</guid>
      <description>&lt;p&gt;OpenViking abandons traditional RAG vector storage and uses a filesystem paradigm instead. It organizes agent context (memories, resources, skills) under &lt;code&gt;viking://&lt;/code&gt; URIs with a three-tier structure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;L0 (Abstract)&lt;/strong&gt;: One-sentence summary for quick retrieval&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L1 (Overview)&lt;/strong&gt;: Core information and usage scenarios&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L2 (Details)&lt;/strong&gt;: Full original data, loaded on demand&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This enables directory recursive retrieval that locks high-score directories first, then refines content exploration. The retrieval trajectory is fully observable, letting users see exactly how context is being accessed.&lt;/p&gt;</description>
    </item>
    <item>
      <title>You can force an LLM to only output valid answers</title>
      <link>https://christianroy.dev/til/static-constrained-decoding-gpu/</link>
      <pubDate>Tue, 03 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/static-constrained-decoding-gpu/</guid>
      <description>&lt;p&gt;YouTube just open-sourced a project called &lt;a href=&#34;https://github.com/youtube/static-constraint-decoding&#34;&gt;STATIC&lt;/a&gt;
that solves a problem most people don&amp;rsquo;t know exists: &lt;strong&gt;LLMs can say anything, but sometimes
you need them to only pick from a specific list.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-problem&#34;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;When an LLM generates text, it picks one token (word/number) at a time from a vocabulary
of ~32,000+ options. That&amp;rsquo;s great for conversation, but terrible when you need it to output
something specific: a valid product ID, a medical code, or a video recommendation from a
catalog of millions.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pipe Mastra agent responses through jq to colorize reasoning and tool calls in the terminal</title>
      <link>https://christianroy.dev/til/mastra-jq-ansi-agent-responses/</link>
      <pubDate>Mon, 02 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/mastra-jq-ansi-agent-responses/</guid>
      <description>&lt;p&gt;Mastra&amp;rsquo;s agent HTTP API returns a JSON structure with &lt;code&gt;steps&lt;/code&gt;, each containing &lt;code&gt;content&lt;/code&gt;
items typed as &lt;code&gt;reasoning&lt;/code&gt;, &lt;code&gt;tool-call&lt;/code&gt;, &lt;code&gt;tool-result&lt;/code&gt;, and &lt;code&gt;text&lt;/code&gt;. The raw output is
dense. Start by exploring it:&lt;/p&gt;
&lt;div class=&#34;highlight&#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;&lt;span class=&#34;c1&#34;&gt;# Hit the API and see raw structure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http localhost:4111/api/agents/weather-agent/generate &lt;span class=&#34;se&#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;  messages&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0&lt;span class=&#34;o&#34;&gt;]=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;what&amp;#39;s the weather in montreal?&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&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;c1&#34;&gt;# Get just the final answer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http localhost:4111/api/agents/weather-agent/generate &lt;span class=&#34;se&#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;  messages&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0&lt;span class=&#34;o&#34;&gt;]=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;what&amp;#39;s the weather in montreal?&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.text&amp;#39;&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&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Explore what&amp;#39;s inside steps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http localhost:4111/api/agents/weather-agent/generate &lt;span class=&#34;se&#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;  messages&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0&lt;span class=&#34;o&#34;&gt;]=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;what&amp;#39;s the weather in montreal?&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq &lt;span class=&#34;s1&#34;&gt;&amp;#39;.steps[].content[] | .type&amp;#39;&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;c1&#34;&gt;# &amp;#34;reasoning&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;c1&#34;&gt;# &amp;#34;tool-call&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;c1&#34;&gt;# &amp;#34;tool-result&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;c1&#34;&gt;# &amp;#34;text&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;c1&#34;&gt;# &amp;#34;reasoning&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;c1&#34;&gt;# &amp;#34;text&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&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# See what fields each type has&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http localhost:4111/api/agents/weather-agent/generate &lt;span class=&#34;se&#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;  messages&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0&lt;span class=&#34;o&#34;&gt;]=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;what&amp;#39;s the weather in montreal?&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq &lt;span class=&#34;s1&#34;&gt;&amp;#39;.steps[].content[] | select(.type == &amp;#34;tool-call&amp;#34;)&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the structure is clear, pipe through &lt;code&gt;jq -r&lt;/code&gt; with inline ANSI escape sequences to
colorize each piece:&lt;/p&gt;</description>
    </item>
    <item>
      <title>OpenClaw custom skills silently disappear without quoted YAML descriptions and openclaw metadata</title>
      <link>https://christianroy.dev/til/openclaw-skill-frontmatter-metadata/</link>
      <pubDate>Fri, 20 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/openclaw-skill-frontmatter-metadata/</guid>
      <description>&lt;p&gt;If a custom OpenClaw skill doesn&amp;rsquo;t show up in &lt;code&gt;openclaw skills list&lt;/code&gt; and the agent can&amp;rsquo;t
see it either, the SKILL.md frontmatter is likely the culprit. OpenClaw fails silently,
so the debugging feedback is minimal.&lt;/p&gt;
&lt;p&gt;Two things must be right. First, any &lt;code&gt;name&lt;/code&gt; or &lt;code&gt;description&lt;/code&gt; containing a colon must be
wrapped in double quotes, otherwise YAML interprets the colon as a key-value separator
and the parse fails. Second, the frontmatter must include an &lt;code&gt;openclaw&lt;/code&gt; metadata block
declaring the emoji icon and any required binaries or environment variables. Without it,
OpenClaw won&amp;rsquo;t register the skill at all.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Google DeepMind&#39;s Lyria 3 generates full songs from a photo or a sentence</title>
      <link>https://christianroy.dev/til/lyria3-music-gen/</link>
      <pubDate>Wed, 18 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/lyria3-music-gen/</guid>
      <description>&lt;p&gt;Lyria 3 takes a text prompt or an image and produces a complete track: instrumentation,
vocals, lyrics. Not a loop, not a mood board. A song.&lt;/p&gt;
&lt;p&gt;The image input is what makes it interesting. Most generative audio models take text.
Lyria 3 can look at a picture and decide what it sounds like. That&amp;rsquo;s a different kind
of creative interpretation, closer to how a composer might respond to visual art than
to a spec.&lt;/p&gt;</description>
    </item>
    <item>
      <title>HTTPie needs --ignore-stdin in non-TTY environments like Claude Code</title>
      <link>https://christianroy.dev/til/httpie-ignore-stdin-claude-code/</link>
      <pubDate>Tue, 17 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/httpie-ignore-stdin-claude-code/</guid>
      <description>&lt;p&gt;HTTPie detects whether it&amp;rsquo;s running in a TTY. When there&amp;rsquo;s no TTY, like when Claude
Code invokes it as a subprocess, HTTPie assumes stdin might have data coming and
interprets the request as a POST, even if you meant a GET.&lt;/p&gt;
&lt;p&gt;The fix is &lt;code&gt;--ignore-stdin&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#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;http --ignore-stdin GET localhost:3000/things
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The catch: once you tell Claude Code to always use &lt;code&gt;--ignore-stdin&lt;/code&gt;, it will also use
it when piping data, which breaks that use case entirely:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Claude Code runs natively as a GitHub Action</title>
      <link>https://christianroy.dev/til/claude-code-gha/</link>
      <pubDate>Thu, 12 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/claude-code-gha/</guid>
      <description>&lt;p&gt;Anthropic ships an official &lt;code&gt;claude-code-action&lt;/code&gt; that runs Claude Code inside a GitHub Actions workflow. It can read your repo, write files, run commands, and commit, all triggered by a PR comment or a schedule.&lt;/p&gt;
&lt;p&gt;The interesting part: it uses the same Claude Code you run locally, so your &lt;code&gt;CLAUDE.md&lt;/code&gt; instructions carry over. The action respects the same permission model.&lt;/p&gt;
&lt;p&gt;Immediate use cases I&amp;rsquo;m thinking about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Auto-generate TIL posts from GitHub Issues with a specific label&lt;/li&gt;
&lt;li&gt;Run a nightly review pass on open PRs&lt;/li&gt;
&lt;li&gt;Summarize recent commits and update a changelog&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main constraint is the Actions runner environment: you need to install any tools Claude Code will call (glow, rsync, etc.) as workflow steps before handing off to the action.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kimi&#39;s agent swarm runs up to 100 parallel sub-agents to escape context window limits</title>
      <link>https://christianroy.dev/til/kimi-agent-swarm-parallel-sub-agents/</link>
      <pubDate>Mon, 09 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/kimi-agent-swarm-parallel-sub-agents/</guid>
      <description>&lt;p&gt;The interesting part isn&amp;rsquo;t the parallelism itself, it&amp;rsquo;s the reason for it. A single agent
on a long-horizon task eventually hits its context window and starts compressing earlier
context, degrading output quality. Kimi&amp;rsquo;s solution: spawn up to 100 sub-agents, each with
their own fresh context, coordinating as a swarm.&lt;/p&gt;
&lt;p&gt;The system is self-organizing: it determines how many agents to deploy and how to split
the work based on the task. In benchmarks they cite 4.5x faster results and over 1,500
tool calls per task.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Zvec is an embedded vector database aiming to be the SQLite of vector search</title>
      <link>https://christianroy.dev/til/zvec-embedded-vector-database/</link>
      <pubDate>Wed, 21 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/zvec-embedded-vector-database/</guid>
      <description>&lt;p&gt;Zvec is an open-source embedded vector database from Alibaba, built on their Proxima
engine. The pitch is simple: vector search that runs in-process, no server required,
with the same frictionless setup as SQLite.&lt;/p&gt;
&lt;p&gt;The gap it fills is real. Faiss gives you indexes but no CRUD or crash recovery.
DuckDB-VSS has limited vector features. Milvus needs its own process and network hop.
Zvec aims to be the option that just works when you&amp;rsquo;re building a local RAG pipeline,
a CLI tool, or anything on-device where you need semantic search without infrastructure.&lt;/p&gt;</description>
    </item>
    <item>
      <title>LLMs struggle with Asana&#39;s strict non-standard rich text format</title>
      <link>https://christianroy.dev/til/asana-rich-text-llm/</link>
      <pubDate>Fri, 12 Sep 2025 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/asana-rich-text-llm/</guid>
      <description>&lt;p&gt;Asana&amp;rsquo;s rich text API doesn&amp;rsquo;t use standard HTML. It accepts a strict subset with
specific rules: only certain tags are allowed, nesting rules differ from what browsers
tolerate, and the format is closer to XML than HTML, meaning unclosed tags, loose
attributes, or anything outside the allowed set will be rejected or silently mangled.&lt;/p&gt;
&lt;p&gt;LLMs tend to produce plausible-looking but subtly wrong output here. They&amp;rsquo;ll use tags
Asana doesn&amp;rsquo;t support, nest things incorrectly, or generate valid HTML that Asana&amp;rsquo;s
parser rejects.&lt;/p&gt;</description>
    </item>
    <item>
      <title>MCP servers support prompts as a first-class concept, separate from tools</title>
      <link>https://christianroy.dev/til/mcp-server-asana-1-1-0-prompts/</link>
      <pubDate>Tue, 03 Dec 2024 00:00:00 +0000</pubDate>
      <guid>https://christianroy.dev/til/mcp-server-asana-1-1-0-prompts/</guid>
      <description>&lt;p&gt;When I shipped mcp-server-asana 1.1.0, the headline addition wasn&amp;rsquo;t the six new
Asana tools (task dependencies, stories, subtasks, project sections). It was prompts.&lt;/p&gt;
&lt;p&gt;In the MCP protocol, prompts and tools are distinct concepts. Tools are individual
actions an LLM can invoke: create a task, add a dependency, fetch a comment. Prompts
are predefined conversation templates: parameterized, reusable starting points that
an MCP host can surface directly to users.&lt;/p&gt;
&lt;p&gt;The task-summary prompt added in 1.1.0 illustrates the difference. Instead of leaving
the LLM to figure out what to fetch and how to present it, the prompt defines a
scaffold: current status, key updates, blockers, next steps. The LLM gets structure,
not a blank page.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
