<?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: Athreya aka Maneshwar</title>
    <description>The latest articles on DEV Community by Athreya aka Maneshwar (@lovestaco).</description>
    <link>https://dev.to/lovestaco</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%2F1002302%2F9dbe5057-f6da-4c08-9b5d-37fe9d281476.png</url>
      <title>DEV Community: Athreya aka Maneshwar</title>
      <link>https://dev.to/lovestaco</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lovestaco"/>
    <language>en</language>
    <item>
      <title>Teach Your Agent to Forget (On Purpose)</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Sat, 13 Jun 2026 17:26:10 +0000</pubDate>
      <link>https://dev.to/lovestaco/teach-your-agent-to-forget-on-purpose-38dh</link>
      <guid>https://dev.to/lovestaco/teach-your-agent-to-forget-on-purpose-38dh</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Part 2 of a series on context engineering. Part 1 was the map of the whole thing. This is one of the harder pieces of territory — the discipline of throwing things away without throwing away the plot.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's a thing that happens to everyone who builds a long-running agent.&lt;/p&gt;

&lt;p&gt;At turn 10, it's brilliant. &lt;/p&gt;

&lt;p&gt;Sharp, fast, remembers exactly what you asked, threads the needle on the tricky bug. &lt;/p&gt;

&lt;p&gt;You feel like a wizard.&lt;/p&gt;

&lt;p&gt;At turn 80, it's a different creature. &lt;/p&gt;

&lt;p&gt;It re-suggests a fix you already rejected.&lt;/p&gt;

&lt;p&gt;It "forgets" the file it edited twenty turns ago. &lt;/p&gt;

&lt;p&gt;It contradicts a decision you both made at the start. &lt;/p&gt;

&lt;p&gt;The same model, the same prompt, the same task and it's somehow gotten &lt;em&gt;dumber&lt;/em&gt; as it learned more.&lt;/p&gt;

&lt;p&gt;That's not a bug in the model. &lt;/p&gt;

&lt;p&gt;That's the desk filling up.&lt;/p&gt;

&lt;p&gt;In Part 1 I made the case that the context window is RAM, not a hard drive, working memory with a hard edge. &lt;/p&gt;

&lt;p&gt;Everything the model can reason about has to fit on the desk. &lt;/p&gt;

&lt;p&gt;The long conversation is what happens when you keep piling paper on that desk and never clear any of it. &lt;/p&gt;

&lt;p&gt;Eventually the important sheet is buried under four hundred lines of tool output, and the model is doing your taxes at a party while standing in a paper avalanche.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compaction is how you clear the desk without sweeping the important sheet into the trash.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of the four moves from Part 1 — write, retrieve, compact, isolate this is the one people get most confidently wrong. &lt;/p&gt;

&lt;p&gt;Because on the surface it looks trivial: "just summarize the conversation." And then they ship a summarizer, and their agent starts quietly losing its mind.&lt;/p&gt;

&lt;p&gt;Let's do it properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What compaction actually is (and what it isn't)
&lt;/h2&gt;

&lt;p&gt;Compaction is lossy compression for &lt;em&gt;meaning&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;You take a long, sprawling history and replace it with a shorter representation that preserves what matters for the next step and discards what doesn't.&lt;/p&gt;

&lt;p&gt;The "lossy" part is the whole game. &lt;/p&gt;

&lt;p&gt;If it were lossless, it wouldn't help, you'd just have the same tokens in a different font. &lt;/p&gt;

&lt;p&gt;Compaction works precisely because it throws information away. &lt;/p&gt;

&lt;p&gt;The skill is in &lt;em&gt;what&lt;/em&gt; you throw away.&lt;/p&gt;

&lt;p&gt;Two things it is &lt;strong&gt;not&lt;/strong&gt;, and conflating them will hurt you:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Clearing&lt;/strong&gt; is amnesia. &lt;code&gt;/clear&lt;/code&gt; wipes the history and starts fresh, useful when you're switching tasks, catastrophic mid-task.&lt;br&gt;
&lt;strong&gt;Trimming&lt;/strong&gt; is mechanical. Dropping the oldest N messages by a hard rule, no model involved. Cheap, fast, dumb. It doesn't know that the oldest message is the one decision the whole task hinges on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Compaction sits between them: smarter than trimming, less destructive than clearing. &lt;/p&gt;

&lt;p&gt;It uses a model to decide what's worth keeping and rewrites the rest into something dense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "just summarize it" goes wrong
&lt;/h2&gt;

&lt;p&gt;Naive compaction fails in ways that are worth naming, because once you can name them you can design against them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dbreunig.com/" rel="noopener noreferrer"&gt;Drew Breunig&lt;/a&gt; has a clean taxonomy of how long context rots, and every one of these can be &lt;em&gt;introduced&lt;/em&gt; by a sloppy compaction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Poisoning&lt;/strong&gt;: a hallucination makes it into the summary, and now it's load-bearing. The model treats its own earlier mistake as established fact and builds on it. Compaction can launder a guess into a "decision."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distraction&lt;/strong&gt;: the summary keeps so much that it just recreates the original bloat. Congratulations, you compacted a 50K conversation down to 48K.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confusion&lt;/strong&gt;: superfluous detail survives the cut and pulls the model toward irrelevant work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clash&lt;/strong&gt;: the summary and the live messages disagree, and the model has to referee a fight between two versions of reality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then there's the failure mode unique to &lt;em&gt;repeated&lt;/em&gt; compaction, which is the scary one: &lt;strong&gt;cumulative erosion.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Each compaction is lossy. &lt;/p&gt;

&lt;p&gt;Compact a compaction and you lose a little more. &lt;/p&gt;

&lt;p&gt;Do it five times across a marathon session and you've played telephone with your own task, the agent is now working from a summary of a summary of a summary, and the specific constraint you set at turn 3 ("never touch the auth module") is three generations of paraphrase away from the original. &lt;/p&gt;

&lt;p&gt;This is the real reason agents "go off the rails" after an auto-compact fires mid-task: the boundary isn't just a token reduction, it's a behavioral discontinuity. &lt;/p&gt;

&lt;p&gt;The agent on the other side is, in a real sense, a slightly different agent working from slightly worse notes.&lt;/p&gt;

&lt;p&gt;You can't eliminate this. &lt;/p&gt;

&lt;p&gt;You can only be deliberate about slowing it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  The anatomy of a good compaction
&lt;/h2&gt;

&lt;p&gt;So what survives the cut? Here's the heuristic that holds up across basically every serious implementation: &lt;strong&gt;keep the decisions and the state, discard the process that produced them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Remember the example from Part 1, the agent that searched the database and found the user's table is &lt;code&gt;documents_v2&lt;/code&gt;? I told you to hold that thought. Here's why it comes back.&lt;/p&gt;

&lt;p&gt;A good compaction keeps: &lt;em&gt;"The user's table is &lt;code&gt;documents_v2&lt;/code&gt;."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A good compaction discards: the 400 lines of JSON the model waded through to figure that out.&lt;/p&gt;

&lt;p&gt;That single line is the entire philosophy in miniature. &lt;/p&gt;

&lt;p&gt;The fact is durable and tiny. &lt;/p&gt;

&lt;p&gt;The evidence for the fact is enormous and now useless, you already extracted the value from it. &lt;/p&gt;

&lt;p&gt;Keeping the JSON is paying rent forever on information you've already cashed out.&lt;/p&gt;

&lt;p&gt;Generalize it and you get the checklist that every good handoff summary converges on:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Keep&lt;/th&gt;
&lt;th&gt;Drop&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What was decided, and the &lt;em&gt;why&lt;/em&gt; behind it&lt;/td&gt;
&lt;td&gt;The deliberation that led to the decision&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Current state of files / system&lt;/td&gt;
&lt;td&gt;Intermediate states already overwritten&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Explicit user constraints and preferences&lt;/td&gt;
&lt;td&gt;Pleasantries, acknowledgements, retries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What's in progress right now&lt;/td&gt;
&lt;td&gt;Completed-and-verified subtasks (one line each)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concrete next steps&lt;/td&gt;
&lt;td&gt;Raw tool output you've already digested&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Critical references (table names, IDs, paths)&lt;/td&gt;
&lt;td&gt;The search that found them&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The constraints line deserves emphasis: &lt;strong&gt;user constraints are the most expensive thing to lose and the easiest thing to drop.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;"Decided to use Postgres" looks like a fact worth keeping. &lt;/p&gt;

&lt;p&gt;"User said never to touch the auth module" looks like old conversational noise. &lt;/p&gt;

&lt;p&gt;The second one is the one that, when lost, makes your agent confidently do the one thing it was told not to. &lt;/p&gt;

&lt;p&gt;Pin constraints. &lt;/p&gt;

&lt;p&gt;They should survive every compaction unchanged, never paraphrased.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the real tools do it
&lt;/h2&gt;

&lt;p&gt;Two production coding agents are worth contrasting, because they agree on the problem and disagree on the manners.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; leans on automation. &lt;/p&gt;

&lt;p&gt;There's a manual &lt;code&gt;/compact&lt;/code&gt; command, but the headline behavior is auto-compaction firing at roughly 95% of the context window, it summarizes the full trajectory and starts fresh with that summary as the seed.&lt;/p&gt;

&lt;p&gt;You can steer it (&lt;code&gt;/compact "focus on the open TODOs"&lt;/code&gt;), and it's distinct from &lt;code&gt;/clear&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The community consensus, tellingly, is that 95% is &lt;em&gt;too late&lt;/em&gt;: by the time you're that full, the conversation's already degrading, and people compact manually well before the trigger.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenAI's Codex CLI&lt;/strong&gt; is more "handoff"-flavored. Its prompt frames compaction as a &lt;em&gt;checkpoint&lt;/em&gt; producing a summary for "another LLM that will resume the task," and tells that next model to build on the work rather than redo it. &lt;/p&gt;

&lt;p&gt;It triggers on a token threshold, keeps the most recent user messages verbatim alongside the summary, and has retry-with-backoff for when the compaction call itself fails. (Compaction is an LLM call. LLM calls fail. Plan for it.)&lt;/p&gt;

&lt;h2&gt;
  
  
  If you're building your own
&lt;/h2&gt;

&lt;p&gt;Synthesizing into the decisions you'll actually have to make:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trigger earlier than you think.&lt;/strong&gt; 95% is the cautionary tale, not the recommendation. &lt;/p&gt;

&lt;p&gt;Around 85–90% lets you compact while the context is still good enough to summarize well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prune before you summarize.&lt;/strong&gt; Run a cheap mechanical pass that drops stale tool output first. &lt;/p&gt;

&lt;p&gt;Summarization is your expensive, lossy tool, don't spend it on 400 lines of JSON you can just delete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep recent turns verbatim.&lt;/strong&gt; Compact the distant past; preserve the present. &lt;/p&gt;

&lt;p&gt;The model needs the live, un-paraphrased thread of what's happening &lt;em&gt;right now&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pin constraints, and tell the user it happened.&lt;/strong&gt; Carry user constraints through every compaction as exact text, they're the thing that does the most damage when lost. &lt;/p&gt;

&lt;p&gt;And a silent compaction that changes behavior mid-task just feels like the agent randomly got worse; one line ("compacted history to free up context") turns a mystery into a tradeoff.&lt;/p&gt;

&lt;p&gt;And a starting prompt, since you'll need one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a handoff summary so this coding session can continue in a fresh context.
The summary will be the ONLY history available, so preserve:

1. Completed work — what's done and verified (one line each)
2. Current state — files modified and their status
3. In progress — what is being worked on right now
4. Next steps — concrete actions to take
5. Constraints — user preferences and requirements, quoted exactly
6. Critical references — table names, IDs, file paths, key decisions and the why

Be dense. Drop deliberation, raw tool output, and anything already superseded.
Do not invent or assume anything not present in the conversation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That last line — &lt;em&gt;do not invent&lt;/em&gt; — is your cheapest defense against poisoning. &lt;/p&gt;

&lt;p&gt;The summarizer's job is compression, not creativity. &lt;/p&gt;

&lt;p&gt;The moment it starts filling gaps, it's manufacturing the hallucination that turn 80 will treat as gospel.&lt;/p&gt;
&lt;h2&gt;
  
  
  The uncomfortable part
&lt;/h2&gt;

&lt;p&gt;Compaction forces you to admit something the rest of the stack lets you avoid: &lt;strong&gt;you cannot keep everything, so you have to decide what your agent is allowed to forget.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;External memory and retrieval let you dodge that, stash it, pull it back later.&lt;/p&gt;

&lt;p&gt;But inside a single long-running task, on a finite desk, there's no dodge left.&lt;/p&gt;

&lt;p&gt;Something has to go, and compaction is choosing what survives on purpose, instead of letting the context window choose for you by quietly shoving your most important constraint off the edge of attention.&lt;/p&gt;

&lt;p&gt;The best compaction, like the best engineering, is mostly subtraction. &lt;/p&gt;

&lt;p&gt;It's keeping &lt;code&gt;documents_v2&lt;/code&gt; and burning the JSON, one line of constraint outliving a thousand lines of chatter. &lt;/p&gt;

&lt;p&gt;The mantra from Part 1 gets sharper here: the best token is the one you didn't have to send. &lt;/p&gt;

&lt;p&gt;Compaction is how you find out which tokens those were, and have the nerve to delete them.&lt;/p&gt;

&lt;p&gt;Disclaimer: This article was written by me; AI was used to fix grammar and improve readability.&lt;/p&gt;

&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs — without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>ai</category>
      <category>programming</category>
      <category>beginners</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Stop Whispering to the Model, Start Furnishing Its Brain</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Wed, 10 Jun 2026 12:36:20 +0000</pubDate>
      <link>https://dev.to/lovestaco/stop-whispering-to-the-model-start-furnishing-its-brain-20he</link>
      <guid>https://dev.to/lovestaco/stop-whispering-to-the-model-start-furnishing-its-brain-20he</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Part 1 of a series. This one is the map of context engineering. Future posts are the territory.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There's a moment every developer hits with LLMs.&lt;/p&gt;

&lt;p&gt;You write the perfect prompt. Crisp instructions. A nice persona. Maybe a "think step by step" sprinkled on top like seasoning. And the model... gives you something almost right but confidently wrong. &lt;/p&gt;

&lt;p&gt;So you tweak a word. Then another. You add "IMPORTANT:" in all caps because surely that'll do it. &lt;/p&gt;

&lt;p&gt;You're basically performing a small ritual and hoping the machine spirits are pleased.&lt;/p&gt;

&lt;p&gt;Here's the uncomfortable truth: &lt;strong&gt;the prompt was never the bottleneck.&lt;/strong&gt; The &lt;em&gt;context&lt;/em&gt; was.&lt;/p&gt;

&lt;p&gt;Welcome to Context Engineering: the discipline that quietly does most of the heavy lifting in every serious LLM application, while prompt engineering gets all the blog posts. (The irony of saying that in a blog post is not lost on me.)&lt;/p&gt;

&lt;p&gt;This series is my attempt to map the whole thing out. &lt;/p&gt;

&lt;p&gt;Today we start with the big picture: what context engineering actually is, and the five pillars we'll spend the rest of the series digging into.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt Engineering vs. Context Engineering
&lt;/h2&gt;

&lt;p&gt;Let's settle this cleanly, because people use these terms like they're synonyms and then act surprised when their app behaves like a confused intern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt engineering&lt;/strong&gt; is about the &lt;em&gt;instruction&lt;/em&gt;. You're crafting the sentence(s) that tell the model what to do. "Summarize this in three bullet points." "Act as a senior Go reviewer." It's phrasing, framing, and tone. It's important, but it's one ingredient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context engineering&lt;/strong&gt; is about everything the model can &lt;em&gt;see&lt;/em&gt; when it answers. The instruction, sure, but also: the retrieved documents, the conversation history, the tool outputs, the user's preferences, the API schema, the error from the last attempt, the relevant rows from your database. It's the entire information environment you assemble around the question.&lt;/p&gt;

&lt;p&gt;Here's the analogy that finally made it click for me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prompt engineering is asking a good question.&lt;br&gt;
Context engineering is making sure the person you're asking actually has the files open in front of them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can ask a brilliant question to someone staring at a blank desk and get nonsense. Or you can ask a mediocre question to someone with exactly the right three documents open and get gold. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The model is only as smart as the context you hand it at inference time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And this matters more than ever because of one brutal constraint:&lt;/p&gt;

&lt;h3&gt;
  
  
  The context window is RAM, not a hard drive
&lt;/h3&gt;

&lt;p&gt;A model's context window its 200K, or 1M, or whatever-K tokens — is not storage. &lt;/p&gt;

&lt;p&gt;It's working memory. &lt;/p&gt;

&lt;p&gt;It's the desk, not the filing cabinet. &lt;/p&gt;

&lt;p&gt;Everything the model "knows" in the moment has to fit on that desk, and the desk has a hard edge.&lt;/p&gt;

&lt;p&gt;Context engineering is, at its core, &lt;strong&gt;the art of deciding what goes on the desk, when, and in what shape.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Too little and the model guesses. &lt;/p&gt;

&lt;p&gt;Too much and it gets distracted, slow, expensive, and weirdly forgetful in the middle (the dreaded "lost in the middle" effect).&lt;/p&gt;

&lt;p&gt;So how do we manage the desk well? Five pillars. Let's meet them.&lt;/p&gt;

&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%2Fwap0fq4bi05q0hafpy0m.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%2Fwap0fq4bi05q0hafpy0m.png" alt=" " width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pillar 1: External Memory
&lt;/h2&gt;

&lt;p&gt;LLMs have a goldfish problem. &lt;/p&gt;

&lt;p&gt;By default, the model knows two things: whatever got baked into its weights during training, and whatever you put in the current context window. &lt;/p&gt;

&lt;p&gt;The instant the conversation ends, the second one in most cases evaporates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;External memory&lt;/strong&gt; is how we cheat death here. Instead of cramming everything the model might ever need into its parameters (impossible) or into a single prompt (expensive and finite), we stash information &lt;em&gt;outside&lt;/em&gt; the model i.e in databases, vector stores, knowledge graphs, plain files  and pull the relevant bits back in when we need them.&lt;/p&gt;

&lt;p&gt;Think of it as giving the model a notebook it can flip through, instead of demanding it memorize the universe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Model weights ]  →  what it learned in training (frozen, generic)
[ Context window ]  →  what it can see right now (small, expensive)
[ External memory ] →  everything else (huge, cheap, retrievable on demand)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the foundation that makes the next pillar even possible. Because once your knowledge lives outside the model, the obvious question becomes: &lt;em&gt;how do I get the right slice of it back in?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Pillar 2: RAG and Dynamic Filters
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Retrieval-Augmented Generation&lt;/strong&gt;  is the workhorse of modern LLM apps. &lt;/p&gt;

&lt;p&gt;The pitch is simple: before the model answers, go fetch relevant, fresh, factual information from your external memory and slip it into the context.&lt;/p&gt;

&lt;p&gt;Now the model answers with your data instead of its hazy half-memory of the internet from two years ago.&lt;/p&gt;

&lt;p&gt;If you've built anything with LLMs in the last while, you've probably done RAG even if you didn't call it that. &lt;/p&gt;

&lt;p&gt;User asks a question → you embed it → you search a vector DB → you stuff the top results into the prompt → the model answers. Beautiful.&lt;/p&gt;

&lt;p&gt;Except naive RAG has a dirty secret: &lt;strong&gt;it retrieves things that are similar, not things that are useful.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vector similarity will happily hand the model five chunks about "billing" when the user asked about a billing &lt;em&gt;bug&lt;/em&gt;, including that one outdated doc from 2021 and a chunk that's technically relevant but belongs to a different customer.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;dynamic filters&lt;/strong&gt; earn their keep. &lt;/p&gt;

&lt;p&gt;Instead of blindly dumping the top-k matches, you filter the retrieval based on the actual situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Who's asking?&lt;/strong&gt; Filter by user, tenant, permissions. (Nobody should retrieve another customer's data into context. That's not a feature, that's an incident.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When does it apply?&lt;/strong&gt; Filter by recency, version, environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What's the intent?&lt;/strong&gt; Route a "how do I" question to docs, a "why is this broken" question to logs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Pillar 3: Context Compaction
&lt;/h2&gt;

&lt;p&gt;So you've got external memory, and you've got smart retrieval. Congratulations: you can now flood the context window faster than ever.&lt;/p&gt;

&lt;p&gt;That's the new problem. Long contexts are slow, expensive, and  counterintuitively  often &lt;em&gt;worse&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Models lose track of details buried in the middle of a giant blob. &lt;/p&gt;

&lt;p&gt;Every redundant token is a token that pushes the important stuff toward the edges of attention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context compaction&lt;/strong&gt; is the discipline of shrinking what you send without losing what matters. &lt;/p&gt;

&lt;p&gt;It's lossy compression for meaning. &lt;/p&gt;

&lt;p&gt;A few flavors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Summarization&lt;/strong&gt;:replace a 40-message conversation with a tight running summary of what's actually decided and relevant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filtering / pruning&lt;/strong&gt;: drop the chunks, turns, or tool outputs that aren't pulling their weight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-ranking&lt;/strong&gt;: reorder retrieved results so the genuinely most relevant material sits where the model pays the most attention.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A concrete example: in a long agent run, you don't keep every single tool call and its full raw output forever. &lt;/p&gt;

&lt;p&gt;You compact. "Searched the DB, found the user's table is &lt;code&gt;documents_v2&lt;/code&gt;" is worth keeping. &lt;/p&gt;

&lt;p&gt;The 400 lines of JSON it came from? Summarize and discard. (Hold that &lt;code&gt;documents_v2&lt;/code&gt; thought — there's a reason it'll come up again.)&lt;/p&gt;

&lt;p&gt;The mantra: &lt;strong&gt;the best token is the one you didn't have to send.&lt;/strong&gt; Compaction is how you free up desk space for the stuff that actually moves the needle.&lt;/p&gt;
&lt;h2&gt;
  
  
  Pillar 4: Context Isolation
&lt;/h2&gt;

&lt;p&gt;Here's a failure mode everyone discovers eventually. &lt;/p&gt;

&lt;p&gt;You build one mega-prompt agent that does &lt;em&gt;everything&lt;/em&gt;: it answers support questions, writes code, queries the database, drafts emails, and waters your plants. And it's mediocre at all of it.&lt;/p&gt;

&lt;p&gt;Why? Because you've stuffed five jobs' worth of instructions, tools, and context into one window, and they interfere with each other. &lt;/p&gt;

&lt;p&gt;The model trying to write SQL gets distracted by the email-drafting instructions. &lt;/p&gt;

&lt;p&gt;Unrelated information bleeds across tasks. &lt;/p&gt;

&lt;p&gt;It's the cognitive equivalent of trying to do your taxes at a party.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context isolation&lt;/strong&gt; is the fix: give each task its own dedicated, clean context. &lt;/p&gt;

&lt;p&gt;Instead of one omniscient agent, you use multiple smaller, focused agents (or sub-agents, or just separate calls)  each with only the instructions, tools, and information &lt;em&gt;its&lt;/em&gt; job requires.&lt;/p&gt;

&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%2Fmbed89pomqyw66c5qpg7.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%2Fmbed89pomqyw66c5qpg7.png" alt=" " width="760" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The research agent doesn't need your code style guide. &lt;/p&gt;

&lt;p&gt;The coder doesn't need to know how to phrase a customer apology. &lt;/p&gt;

&lt;p&gt;By keeping their contexts separate, each one stays sharp, and a mess in one doesn't poison the others. &lt;/p&gt;

&lt;p&gt;Isolation buys you reliability &lt;em&gt;and&lt;/em&gt; keeps each individual window small enough to actually be good.&lt;/p&gt;
&lt;h2&gt;
  
  
  Putting the desk back together
&lt;/h2&gt;

&lt;p&gt;Step back and look at the five pillars and you'll notice they're all the same idea wearing different hats:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;The question it answers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;External memory&lt;/td&gt;
&lt;td&gt;Where does knowledge live when it's not in the window?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAG + dynamic filters&lt;/td&gt;
&lt;td&gt;How do I pull &lt;em&gt;the right&lt;/em&gt; knowledge back in?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context compaction&lt;/td&gt;
&lt;td&gt;How do I fit it without bloat?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context isolation&lt;/td&gt;
&lt;td&gt;How do I keep unrelated jobs from interfering?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every one of them is a way of managing that scarce, precious desk i.e the context window, so the model sees exactly what it needs and nothing it doesn't.&lt;/p&gt;

&lt;p&gt;That's context engineering. Not begging the model in capital letters. &lt;/p&gt;

&lt;p&gt;Just deliberate, almost boring decisions about information: what to include, what to leave out, where to store it, and when to bring it back.&lt;/p&gt;

&lt;p&gt;The prompt is the question. The context is everything that makes the answer good.&lt;/p&gt;

&lt;p&gt;Disclaimer: This article was written by me; AI was used to fix grammar and improve readability.&lt;/p&gt;

&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs — without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>ai</category>
      <category>programming</category>
      <category>beginners</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Wait... FDE Is Not a JavaScript Framework?</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Tue, 09 Jun 2026 17:30:36 +0000</pubDate>
      <link>https://dev.to/lovestaco/wait-fde-is-not-a-javascript-framework-1947</link>
      <guid>https://dev.to/lovestaco/wait-fde-is-not-a-javascript-framework-1947</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No. And thank god, because we have enough of those.&lt;/p&gt;

&lt;p&gt;If you've been scrolling LinkedIn lately and seen "Forward Deployed Engineer" pop up next to salaries that made you spit out your cold brew — you're not hallucinating. &lt;/p&gt;

&lt;p&gt;The role blew up because of Palantir, got supercharged by the AI gold rush, and now everyone from Google to Razorpay to your favorite Series B startup is hiring them.&lt;/p&gt;

&lt;p&gt;Here's the mental model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A regular SWE&lt;/strong&gt; ships features for &lt;em&gt;millions of users&lt;/em&gt; they'll never meet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An FDE&lt;/strong&gt; ships an entire system for &lt;em&gt;one customer&lt;/em&gt; whose engineers they're sitting next to, screen-sharing with, and occasionally absorbing the rage of.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is the difference between cooking for a restaurant and being a private chef who flies to your client's house and cooks while they critique the knife work over your shoulder. &lt;/p&gt;

&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%2Fcl646qsxchhdq5ize1xk.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%2Fcl646qsxchhdq5ize1xk.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The non-negotiable truth: this is NOT a beginner role
&lt;/h2&gt;

&lt;p&gt;Let's kill the dream early so nobody cries later.&lt;/p&gt;

&lt;p&gt;Per the &lt;a href="https://roadmap.sh" rel="noopener noreferrer"&gt;roadmap.sh FDE roadmap&lt;/a&gt;, the very first note on the path says it plainly: &lt;em&gt;FDE is not a beginner role.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;You're expected to already be a full-stack developer stepping &lt;strong&gt;into&lt;/strong&gt; the role, not someone using it as a launchpad.&lt;/p&gt;

&lt;p&gt;Real job postings back this up hard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fiddler&lt;/strong&gt; wants &lt;strong&gt;5+ years&lt;/strong&gt; building production-grade ML/AI systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Razorpay&lt;/strong&gt; asks for &lt;strong&gt;3–10 years&lt;/strong&gt; of hands-on engineering, people who've &lt;em&gt;shipped production code and debugged it in live customer environments.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if you're 6 months into your first bootcamp project... bookmark this, build for three more years, then come back. I'll wait.&lt;/p&gt;

&lt;h2&gt;
  
  
  The FDE skill tree (or: why you need to be a genuine full-stack threat)
&lt;/h2&gt;

&lt;p&gt;Think of the roadmap as a literal RPG skill tree. &lt;/p&gt;

&lt;p&gt;Here's what you have to level up.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Core technical skills — Frontend + Backend + Linux
&lt;/h3&gt;

&lt;p&gt;FDEs need to be &lt;strong&gt;proficient in full-stack development, have high agency, and be able to deliver full apps for customers.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Not "I can center a div" full-stack. &lt;/p&gt;

&lt;p&gt;More like "I can stand up a frontend, wire the backend, debug the Linux box it's running on, and explain all three to the customer's CTO" full-stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. DSA &amp;amp; System Design
&lt;/h3&gt;

&lt;p&gt;Here's the spicy one. &lt;/p&gt;

&lt;p&gt;The roadmap is brutally honest:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DSA is the &lt;strong&gt;first gate&lt;/strong&gt; in FDE interviews. You won't get to show off your AI skills if you don't pass this round.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Translation: yes, you still have to invert the binary tree. &lt;/p&gt;

&lt;p&gt;The LeetCode grind doesn't end just because the job title is fancier.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. AI Engineering skills
&lt;/h3&gt;

&lt;p&gt;This is where 2026 FDEs separate from the pack. &lt;/p&gt;

&lt;p&gt;You're expected to be fluent in &lt;strong&gt;at least one major cloud platform&lt;/strong&gt; and know how to &lt;strong&gt;deploy infrastructure as code.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;On top of that, the AI-flavored JDs want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LLM / agentic frameworks&lt;/strong&gt;: &lt;a href="https://github.com/langchain-ai/langchain" rel="noopener noreferrer"&gt;LangChain&lt;/a&gt;, &lt;a href="https://github.com/run-llama/llama_index" rel="noopener noreferrer"&gt;LlamaIndex&lt;/a&gt;, &lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;LangGraph&lt;/a&gt;, &lt;a href="https://github.com/microsoft/autogen" rel="noopener noreferrer"&gt;AutoGen&lt;/a&gt;, &lt;strong&gt;MCP&lt;/strong&gt;, &lt;a href="https://github.com/langchain-ai/rag-from-scratch" rel="noopener noreferrer"&gt;RAG&lt;/a&gt;. (Fiddler and Razorpay both list these. "Hands-on counts, not just awareness," as Razorpay puts it.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building and orchestrating agents&lt;/strong&gt;: &lt;a href="https://www.langchain.com/blog/tool-calling-with-langchain" rel="noopener noreferrer"&gt;tool bindings&lt;/a&gt;, &lt;a href="https://github.com/confident-ai/deepeval" rel="noopener noreferrer"&gt;eval pipelines&lt;/a&gt;, &lt;a href="https://cloud.google.com/discover/human-in-the-loop" rel="noopener noreferrer"&gt;human-approval flows&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsible AI&lt;/strong&gt;: &lt;a href="https://www.evidentlyai.com/ml-in-production/model-monitoring" rel="noopener noreferrer"&gt;model monitoring&lt;/a&gt;, &lt;a href="https://www.evidentlyai.com/ml-in-production/data-drift" rel="noopener noreferrer"&gt;drift detection&lt;/a&gt;, explainability, bias detection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. DevOps skills 🔧
&lt;/h3&gt;

&lt;p&gt;FDEs are responsible for &lt;strong&gt;proving to customers that what they built won't break or go rogue in production.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;That means you own the deploy, the monitoring, and the dreaded &lt;strong&gt;hypercare&lt;/strong&gt; period. &lt;/p&gt;

&lt;p&gt;Razorpay literally describes being the &lt;em&gt;"first responder during the 15–30 day hypercare period post go-live."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yeah. You build it, you ship it, &lt;strong&gt;you carry the pager.&lt;/strong&gt; 📟&lt;/p&gt;

&lt;h2&gt;
  
  
  The half nobody warns you about: Customer &amp;amp; Field skills
&lt;/h2&gt;

&lt;p&gt;This is the part that filters out 80% of brilliant engineers. &lt;/p&gt;

&lt;p&gt;You can be a 10x coder and still bomb as an FDE because you can't do &lt;strong&gt;this&lt;/strong&gt; half:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field Skill&lt;/th&gt;
&lt;th&gt;What it actually means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Discovery &amp;amp; Scoping&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Run the call, gather requirements, sequence the work, and figure out integration complexity &lt;em&gt;before&lt;/em&gt; you commit.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tradeoffs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Constantly juggling Scope vs. Speed vs. Quality  and explaining the tradeoff to a non-technical stakeholder without making them feel dumb.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Business Acumen&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ROI, stakeholder management, product feedback loops. You're not just building, you're proving &lt;em&gt;value&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Communication&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Technical writing, clear updates, managing expectations, "closing ambiguity without hand-holding."&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As Fiddler puts it, you're literally &lt;strong&gt;"the technical voice of the customer"&lt;/strong&gt;, embedded with their team, translating their messy reality into clean technical designs, then carrying their feedback back to your own Product and Engineering teams.&lt;/p&gt;

&lt;p&gt;Razorpay is even blunter about what it's &lt;em&gt;not&lt;/em&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is &lt;strong&gt;not&lt;/strong&gt; a pre-sales role. It is &lt;strong&gt;not&lt;/strong&gt; a support role. It is &lt;strong&gt;not&lt;/strong&gt; solutions architecture. You write production code... and you own the outcome end-to-end.&lt;/p&gt;
&lt;/blockquote&gt;

&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%2Fq8x8nqg1wpv4z82jklau.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%2Fq8x8nqg1wpv4z82jklau.png" alt=" " width="360" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  "Okay but show me the money 💰"
&lt;/h2&gt;

&lt;p&gt;Fair. Based on tracked 2026 hiring data (&lt;a href="https://fdepulse.com/insights/fde-hiring-trends-2026/" rel="noopener noreferrer"&gt;fdepulse.com&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FDE base salaries cluster between roughly &lt;strong&gt;$135K and $215K&lt;/strong&gt;, varying by level and metro.&lt;/li&gt;
&lt;li&gt;Hiring is &lt;strong&gt;concentrated&lt;/strong&gt;, a handful of metros and the top ~10 companies hold most of the open roles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI labs and enterprise SaaS&lt;/strong&gt; drive most new openings, with consulting firms a distant third.&lt;/li&gt;
&lt;li&gt;Lots of companies are hiring their &lt;strong&gt;first or second&lt;/strong&gt; FDE ever, a strong signal that brand-new teams are forming (read: ground-floor opportunity).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Top 10 companies by open FDE roles
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Company&lt;/th&gt;
&lt;th&gt;Open Roles&lt;/th&gt;
&lt;th&gt;Median Salary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Deloitte&lt;/td&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;td&gt;$194K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;td&gt;31&lt;/td&gt;
&lt;td&gt;$185K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ZipLine&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;$206K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skyline Eco Adventures&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;$206K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JDA TSG&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;$110K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adobe&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;$221K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Okta&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;$275K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tenex.AI&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Not disclosed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;David Joseph &amp;amp; Company&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;$188K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C3 AI&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$156K&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Okta out here paying &lt;strong&gt;$275K&lt;/strong&gt; to engineers who can both ship and &lt;em&gt;talk&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Suddenly that public-speaking class doesn't seem like a waste, huh.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your roadmap to becoming an FDE
&lt;/h2&gt;

&lt;p&gt;If you want to actually chase this, here's the leveling order I'd suggest based on the roadmap:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Become a genuine full-stack dev first.&lt;/strong&gt; Frontend, backend, and enough Linux to be dangerous. No shortcuts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grind DSA + System Design.&lt;/strong&gt; It's the first interview gate. Period.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get fluent in one cloud + Infrastructure as Code.&lt;/strong&gt; Pick AWS, GCP, or Azure and go deep.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learn the AI/agentic stack hands-on.&lt;/strong&gt; Build something real with LangChain/LangGraph/MCP/RAG. "Awareness" gets you rejected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practice the soft stuff like it's a hard skill.&lt;/strong&gt; Do discovery calls, write docs people actually read, learn to explain tradeoffs to non-engineers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Develop high agency.&lt;/strong&gt; This word shows up everywhere for a reason. FDEs are trusted to own ambiguous problems and just... handle them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The roadmap also points to four follow-on tracks worth leveling into: &lt;strong&gt;Frontend, Backend, DevOps, and AI Engineer.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So... is it for you?
&lt;/h2&gt;

&lt;p&gt;The FDE role is the rare job that rewards engineers who refused to pick a lane. &lt;/p&gt;

&lt;p&gt;If you genuinely enjoy building &lt;strong&gt;and&lt;/strong&gt; the messy human reality of &lt;em&gt;why&lt;/em&gt; you're building it  talking to customers, owning outcomes, carrying the pager and the conversation, this might be the most fun (and best-paid) seat in tech right now.&lt;/p&gt;

&lt;p&gt;If you'd rather put on noise-canceling headphones and never speak to a stakeholder again? Totally valid. &lt;/p&gt;

&lt;p&gt;Backend Roadmap is right over there, no judgment. 🎧&lt;/p&gt;

&lt;p&gt;Either way ship code, talk to humans, don't let it break in prod. &lt;/p&gt;

&lt;p&gt;That's the whole job not just for FDE, applies to all :)&lt;/p&gt;

&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs — without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>one last peek 👀🍵 docs, a demo, and a goodbye for now</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Mon, 08 Jun 2026 19:27:13 +0000</pubDate>
      <link>https://dev.to/lovestaco/one-last-peek-docs-a-demo-and-a-goodbye-for-now-4ddk</link>
      <guid>https://dev.to/lovestaco/one-last-peek-docs-a-demo-and-a-goodbye-for-now-4ddk</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Short one this time.&lt;/p&gt;

&lt;p&gt;peektea now has a proper documentation site: &lt;strong&gt;&lt;a href="https://lovestaco.github.io/peektea/" rel="noopener noreferrer"&gt;lovestaco.github.io/peektea&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Up to now, everything lived in one long README i.e install instructions, keybindings, configuration, WSL notes, all stacked on top of each other. &lt;/p&gt;

&lt;p&gt;Useful, but not exactly a pleasant read once a project grows past a certain size.&lt;/p&gt;

&lt;p&gt;The new site splits all of that into proper pages i.e Installation, Usage (navigation, opening files, filtering, hidden files, preview, sorting), Configuration, WSL support, and more.&lt;/p&gt;

&lt;p&gt;Each with its own room to breathe, demos where they help, and a search bar to jump straight to what you need.&lt;/p&gt;

&lt;p&gt;Built with &lt;a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener noreferrer"&gt;MkDocs Material&lt;/a&gt;, themed in peektea's own palette, and deployed automatically on every push via GitHub Actions.&lt;/p&gt;

&lt;p&gt;Go peek around: &lt;a href="https://lovestaco.github.io/peektea/" rel="noopener noreferrer"&gt;lovestaco.github.io/peektea&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  One last thing: the full demo
&lt;/h2&gt;

&lt;p&gt;Before wrapping up, I also recorded a complete walkthrough, every feature from the series, start to finish, in one go:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/yDNN5x9Y9Ok"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;This is probably the last blog post / improvement on peektea for a while.&lt;/p&gt;

&lt;p&gt;I've got everything I wanted out of my own TUI file browser at this point.&lt;/p&gt;

&lt;p&gt;If you're using &lt;a href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;peektea&lt;/a&gt; and there's something that would genuinely help your workflow, let me know in the comments. &lt;/p&gt;

&lt;p&gt;I'm happy to build it.&lt;/p&gt;

&lt;p&gt;For now, the pot's off the heat. 👀🍵&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>cli</category>
    </item>
    <item>
      <title>peektea brews on WSL (and installs in one line)</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Sat, 06 Jun 2026 17:47:41 +0000</pubDate>
      <link>https://dev.to/lovestaco/peektea-brews-on-wsl-and-installs-in-one-line-34ef</link>
      <guid>https://dev.to/lovestaco/peektea-brews-on-wsl-and-installs-in-one-line-34ef</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Two things I kept putting off.&lt;/p&gt;

&lt;p&gt;First: people on Windows asked if peektea runs on WSL. It does now.&lt;/p&gt;

&lt;p&gt;Second: "brew it from source" is a terrible install story for a tool that's supposed to be minimal. That's fixed too.&lt;/p&gt;

&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%2Fiy323s0wjnu0bctkh2hj.gif" 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%2Fiy323s0wjnu0bctkh2hj.gif" alt="peektea demo on WSL machine gh" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lovestaco/peektea/blob/master/media/wsl_demo.gif" rel="noopener noreferrer"&gt;Demo here&lt;/a&gt; in case above preview not showing up.&lt;/p&gt;

&lt;h2&gt;
  
  
  WSL support
&lt;/h2&gt;

&lt;p&gt;WSL is Linux. peektea runs on Linux. So far, so good.&lt;/p&gt;

&lt;p&gt;The problem is &lt;code&gt;o&lt;/code&gt;  the key that opens files. &lt;/p&gt;

&lt;p&gt;On a normal Linux machine, pressing &lt;code&gt;o&lt;/code&gt; on an image launches &lt;code&gt;feh&lt;/code&gt; or &lt;code&gt;eog&lt;/code&gt;. On WSL there are no Linux GUI apps. &lt;/p&gt;

&lt;p&gt;The call fails silently or prints an error.&lt;/p&gt;

&lt;p&gt;peektea now detects WSL at startup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;IsWSL&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&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;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WSL_DISTRO_NAME"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&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;ReadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/proc/version"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="s"&gt;"microsoft"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When WSL is detected, file opens route through &lt;code&gt;wslview&lt;/code&gt; (from &lt;a href="https://wslutiliti.es/wslu/" rel="noopener noreferrer"&gt;wslu&lt;/a&gt;) if it's installed, otherwise fall back to &lt;code&gt;explorer.exe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;WSLOpener&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LookPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wslview"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"wslview"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LookPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"explorer.exe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"explorer.exe"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&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;Stat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/mnt/c/Windows/explorer.exe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"/mnt/c/Windows/explorer.exe"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There's one more wrinkle: Windows programs can't read Linux paths like &lt;code&gt;/home/taco/file.png&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;They need UNC paths like &lt;code&gt;\\wsl.localhost\Ubuntu\home\taco\file.png&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;WSL ships &lt;code&gt;wslpath&lt;/code&gt; for exactly this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;WindowsPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wslpath"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"-w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When the configured opener ends in &lt;code&gt;.exe&lt;/code&gt;, the path gets converted before the command runs. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;wslview&lt;/code&gt; handles conversion itself so it doesn't need this, only raw &lt;code&gt;explorer.exe&lt;/code&gt; does.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/lovestaco" rel="noopener noreferrer"&gt;
        lovestaco
      &lt;/a&gt; / &lt;a href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;
        peektea
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Peek First. Open Later. A TUI file browser built with bubble tea
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/lovestaco/peektea/media/cover.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Flovestaco%2Fpeektea%2FHEAD%2Fmedia%2Fcover.png" alt="cover"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A minimal terminal file browser built with &lt;a href="https://github.com/charmbracelet/bubbletea" rel="noopener noreferrer"&gt;Bubble Tea&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Peek through your filesystem with arrow keys (or vim keys), then pour each file straight into the app you've configured for it.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demo&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;A quick peek before you steep:&lt;/p&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/lovestaco/peektea/media/demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Flovestaco%2Fpeektea%2FHEAD%2Fmedia%2Fdemo.gif" alt="demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;One-liner:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;curl -fsSL https://raw.githubusercontent.com/lovestaco/peektea/master/scripts/install.sh &lt;span class="pl-k"&gt;|&lt;/span&gt; sh&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Download a binary&lt;/strong&gt; (no Go required) — grab the latest release for your platform from the &lt;a href="https://github.com/lovestaco/peektea/releases/latest" rel="noopener noreferrer"&gt;releases page&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Platform&lt;/th&gt;

&lt;th&gt;File&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;Linux x86-64&lt;/td&gt;

&lt;td&gt;&lt;code&gt;peektea_&lt;em&gt;&lt;em&gt;linux_amd64.tar.gz&lt;/em&gt;&lt;/em&gt;&lt;/code&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Linux arm64&lt;/td&gt;

&lt;td&gt;&lt;code&gt;peektea&lt;em&gt;linux_arm64.tar.gz&lt;/em&gt;&lt;/code&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;macOS x86-64&lt;/td&gt;

&lt;td&gt;&lt;code&gt;peektea&lt;em&gt;&lt;em&gt;darwin_amd64.tar.gz&lt;/em&gt;&lt;/em&gt;&lt;/code&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;macOS Apple Silicon&lt;/td&gt;

&lt;td&gt;&lt;code&gt;peektea_darwin_arm64.tar.gz&lt;/code&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Extract and put the &lt;code&gt;peektea&lt;/code&gt; binary anywhere on your &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install with Go:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;go install github.com/lovestaco/peektea@latest&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Build from source:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/lovestaco/peektea
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; peektea
make install&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;make install&lt;/code&gt; puts the binary in &lt;code&gt;~/go/bin&lt;/code&gt; and figures out &lt;code&gt;$PATH&lt;/code&gt; for you:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Already reachable — done, nothing to do.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.local/bin&lt;/code&gt; is on your PATH — symlinks the binary there, works immediately in the current shell.&lt;/li&gt;
&lt;li&gt;Neither — appends &lt;code&gt;~/go/bin&lt;/code&gt; to your &lt;code&gt;.bashrc&lt;/code&gt;…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  peektea init on WSL
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;peektea init&lt;/code&gt; on a normal Linux machine asks you to pick a text editor, file manager, image viewer, and PDF viewer from what's installed.&lt;/p&gt;

&lt;p&gt;On WSL there usually aren't any Linux GUI apps. Asking you to pick between zero options isn't a great experience.&lt;/p&gt;

&lt;p&gt;So on WSL, init skips those categories and sets the Windows opener as the fallback instead of &lt;code&gt;xdg-open&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;You still get the full text editor setup (vim, nvim, nano  those work fine in WSL), and the Windows side handles everything visual.&lt;/p&gt;

&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%2F2rsngdculba0wkwbwchd.gif" 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%2F2rsngdculba0wkwbwchd.gif" alt="peektea init on WSL" width="760" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lovestaco/peektea/blob/master/media/init_wsl_support.gif" rel="noopener noreferrer"&gt;Demo here&lt;/a&gt; in case the above preview is not showing up.&lt;/p&gt;

&lt;p&gt;While at it, &lt;code&gt;peektea init&lt;/code&gt; got smarter in general. &lt;/p&gt;

&lt;p&gt;If you decline the "already exists, overwrite?" prompt, it used to just exit. &lt;/p&gt;

&lt;p&gt;Now it keeps your config and continues to the chafa check, so you can re-run &lt;code&gt;peektea init&lt;/code&gt; any time just to install extras without nuking your setup.&lt;/p&gt;

&lt;p&gt;And if chafa isn't installed, it doesn't just print the install command anymore. &lt;/p&gt;

&lt;p&gt;It offers to run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;── Image previews
   chafa not found — it renders images right in the terminal (the `p` preview).
   Install it now? (sudo apt install -y chafa) [Y/n]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It detects your package manager (&lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;dnf&lt;/code&gt;, &lt;code&gt;pacman&lt;/code&gt;, &lt;code&gt;zypper&lt;/code&gt;, &lt;code&gt;apk&lt;/code&gt;, &lt;code&gt;brew&lt;/code&gt;) and runs the right command. Bare enter means yes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;The other thing that needed fixing: the only install method was cloning the repo and running &lt;code&gt;make install&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;That requires Go, git, and knowing where &lt;code&gt;~/go/bin&lt;/code&gt; is. &lt;/p&gt;

&lt;p&gt;Too much friction for a tool that's supposed to just work.&lt;/p&gt;

&lt;p&gt;peektea now ships pre-built binaries for Linux and macOS (x86-64 and arm64) on every release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One-liner:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/lovestaco/peektea/master/scripts/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The script detects your OS and architecture, pulls the right binary from the latest release, and installs it to &lt;code&gt;~/.local/bin&lt;/code&gt; or &lt;code&gt;/usr/local/bin&lt;/code&gt; whichever is already on your PATH.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With Go:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/lovestaco/peektea@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;&lt;code&gt;peektea version&lt;/code&gt; now works correctly&lt;/strong&gt; regardless of how you installed it. &lt;/p&gt;

&lt;p&gt;When installed via &lt;code&gt;go install&lt;/code&gt;, the binary reads its own module version from &lt;code&gt;debug.ReadBuildInfo()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When built with &lt;code&gt;make install&lt;/code&gt;, the version comes from &lt;code&gt;git describe&lt;/code&gt; via ldflags. &lt;/p&gt;

&lt;p&gt;Either way:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;peektea version
&lt;span class="c"&gt;# peektea v0.2.1 (linux/amd64)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs — without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>cli</category>
    </item>
    <item>
      <title>peektea past the roadmap 👀 sorting and scrollable previews</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Fri, 05 Jun 2026 07:15:43 +0000</pubDate>
      <link>https://dev.to/lovestaco/peektea-past-the-roadmap-sorting-and-scrollable-previews-1f6g</link>
      <guid>https://dev.to/lovestaco/peektea-past-the-roadmap-sorting-and-scrollable-previews-1f6g</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Last time I said the list was empty.&lt;/p&gt;

&lt;p&gt;That was true.&lt;/p&gt;

&lt;p&gt;Then I kept going anyway.&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;s&lt;/code&gt; and the list sorts by size. Press it again, newest-modified first.&lt;/p&gt;

&lt;p&gt;Previwing something? Press &lt;code&gt;[&lt;/code&gt; and &lt;code&gt;]&lt;/code&gt; and scroll through the preview without leaving the peektea cli.&lt;/p&gt;

&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%2Fjf3xng9vwg6hqzh1egk5.gif" 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%2Fjf3xng9vwg6hqzh1egk5.gif" alt="peektea sort and preview-scroll demo" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sort
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;s&lt;/code&gt; key cycles through three modes: &lt;strong&gt;name → size → modified → name&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The current mode is always visible in the hint bar: &lt;code&gt;s:sorted by name&lt;/code&gt;, &lt;code&gt;s:sorted by size&lt;/code&gt;, &lt;code&gt;s:sorted by modified&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Under the hood it's a single &lt;code&gt;sort.SliceStable&lt;/code&gt; call inside &lt;code&gt;withFilters()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The sort runs on the filtered slice, so it composes with the text filter and the hidden file toggle, same composable approach as before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceStable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sortMode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;sortSize&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// largest first&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;sortMod&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModTime&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c"&gt;// newest first&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;SliceStable&lt;/code&gt; preserves the relative order of entries that compare equal, which keeps directories grouped sensibly when names or sizes match.&lt;/p&gt;
&lt;h2&gt;
  
  
  Preview scroll
&lt;/h2&gt;

&lt;p&gt;The preview panel used to show the first N lines of a file and stop there.&lt;/p&gt;

&lt;p&gt;Now you can scroll through it with &lt;code&gt;[&lt;/code&gt; (up) and &lt;code&gt;]&lt;/code&gt; (down). Each press moves a quarter of the panel height.&lt;/p&gt;

&lt;p&gt;The key insight: instead of limiting what gets loaded to the visible height, the preview now loads up to 500 lines and stores the whole thing. &lt;/p&gt;

&lt;p&gt;The rendering step slices out the visible window:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;previewContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;scroll&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;previewScroll&lt;/span&gt;
&lt;span class="n"&gt;maxScroll&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;ph&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;maxScroll&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;maxScroll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;scroll&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;maxScroll&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;scroll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;maxScroll&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;scroll&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ph&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ph&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;previewScroll&lt;/code&gt; resets to zero whenever you move to a new file, so you always start at the top.&lt;/p&gt;
&lt;h2&gt;
  
  
  Syntax highlighting via bat
&lt;/h2&gt;

&lt;p&gt;While reworking the preview loading, I added a bat check.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sharkdp/bat" rel="noopener noreferrer"&gt;bat&lt;/a&gt; is a &lt;code&gt;cat&lt;/code&gt; clone with syntax highlighting. If it's installed, peektea uses it for text previews:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LookPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bat"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"--color=always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"--style=plain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"--line-range"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;":500"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"--terminal-width"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimRight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// fallback to plain text reader&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Same graceful-fallback pattern as chafa. Not installed? Plain text. Installed but fails on a particular file? Plain text. The preview never breaks.&lt;/p&gt;
&lt;h2&gt;
  
  
  Scrollbars
&lt;/h2&gt;

&lt;p&gt;Both panels now have scrollbars.&lt;/p&gt;

&lt;p&gt;When the preview has more content than fits on screen, a thin &lt;code&gt;│&lt;/code&gt; track with a &lt;code&gt;┃&lt;/code&gt; thumb appears on the right edge of the preview.&lt;/p&gt;

&lt;p&gt;Same thing in the file list when there are more entries than the terminal can show.&lt;/p&gt;

&lt;p&gt;A single function handles both:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;buildScrollbar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scroll&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;chars&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;scrollTrackStyle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"│"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;thumb&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;scrollThumbStyle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"┃"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;chars&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;chars&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;thumbSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;thumbSize&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;thumbSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;thumbPos&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;scroll&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;thumbSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;chars&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;thumbPos&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;thumbPos&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;thumbSize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;thumb&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;chars&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It returns a slice of styled characters, one per visible row  that get appended to each rendered line. &lt;/p&gt;

&lt;p&gt;The thumb size scales proportionally: if half the content is visible, the thumb fills half the track.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/lovestaco" rel="noopener noreferrer"&gt;
        lovestaco
      &lt;/a&gt; / &lt;a href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;
        peektea
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Peek First. Open Later. A TUI file browser built with bubble tea
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/lovestaco/peektea/media/cover.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Flovestaco%2Fpeektea%2FHEAD%2Fmedia%2Fcover.png" alt="cover"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A minimal terminal file browser built with &lt;a href="https://github.com/charmbracelet/bubbletea" rel="noopener noreferrer"&gt;Bubble Tea&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Peek through your filesystem with arrow keys (or vim keys), then pour each file straight into the app you've configured for it.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demo&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;A quick peek before you steep:&lt;/p&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/lovestaco/peektea/media/demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Flovestaco%2Fpeektea%2FHEAD%2Fmedia%2Fdemo.gif" alt="demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;One-liner:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;curl -fsSL https://raw.githubusercontent.com/lovestaco/peektea/master/scripts/install.sh &lt;span class="pl-k"&gt;|&lt;/span&gt; sh&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Download a binary&lt;/strong&gt; (no Go required) — grab the latest release for your platform from the &lt;a href="https://github.com/lovestaco/peektea/releases/latest" rel="noopener noreferrer"&gt;releases page&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Platform&lt;/th&gt;

&lt;th&gt;File&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;Linux x86-64&lt;/td&gt;

&lt;td&gt;&lt;code&gt;peektea_&lt;em&gt;&lt;em&gt;linux_amd64.tar.gz&lt;/em&gt;&lt;/em&gt;&lt;/code&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Linux arm64&lt;/td&gt;

&lt;td&gt;&lt;code&gt;peektea&lt;em&gt;linux_arm64.tar.gz&lt;/em&gt;&lt;/code&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;macOS x86-64&lt;/td&gt;

&lt;td&gt;&lt;code&gt;peektea&lt;em&gt;&lt;em&gt;darwin_amd64.tar.gz&lt;/em&gt;&lt;/em&gt;&lt;/code&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;macOS Apple Silicon&lt;/td&gt;

&lt;td&gt;&lt;code&gt;peektea_darwin_arm64.tar.gz&lt;/code&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Extract and put the &lt;code&gt;peektea&lt;/code&gt; binary anywhere on your &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install with Go:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;go install github.com/lovestaco/peektea@latest&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Build from source:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/lovestaco/peektea
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; peektea
make install&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;make install&lt;/code&gt; puts the binary in &lt;code&gt;~/go/bin&lt;/code&gt; and figures out &lt;code&gt;$PATH&lt;/code&gt; for you:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Already reachable — done, nothing to do.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.local/bin&lt;/code&gt; is on your PATH — symlinks the binary there, works immediately in the current shell.&lt;/li&gt;
&lt;li&gt;Neither — appends &lt;code&gt;~/go/bin&lt;/code&gt; to your &lt;code&gt;.bashrc&lt;/code&gt;…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs — without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>cli</category>
      <category>productivity</category>
    </item>
    <item>
      <title>peektea narrows its gaze 👀 filter-as-you-type and hidden files</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Thu, 04 Jun 2026 17:22:56 +0000</pubDate>
      <link>https://dev.to/lovestaco/peektea-narrows-its-gaze-filter-as-you-type-and-hidden-files-23ic</link>
      <guid>https://dev.to/lovestaco/peektea-narrows-its-gaze-filter-as-you-type-and-hidden-files-23ic</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Last time I ended with two items left on the list.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Filter as you type&lt;/strong&gt; — Bubble Tea's &lt;code&gt;textinput&lt;/code&gt; component from bubbles is sitting there waiting&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hidden file toggle&lt;/strong&gt; — show/hide dotfiles&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Both ship today.&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;/&lt;/code&gt; and start typing, the list narrows instantly. &lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;.&lt;/code&gt; and dotfiles appear. &lt;/p&gt;

&lt;p&gt;Press it again and they vanish.&lt;/p&gt;

&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%2Fqq7on8nmqdcbyl97w5ya.gif" 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%2Fqq7on8nmqdcbyl97w5ya.gif" alt="peektea filter and hidden files demo" width="799" height="406"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/lovestaco" rel="noopener noreferrer"&gt;
        lovestaco
      &lt;/a&gt; / &lt;a href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;
        peektea
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Peek First. Open Later. A TUI file browser built with bubble tea
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/lovestaco/peektea/media/cover.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Flovestaco%2Fpeektea%2FHEAD%2Fmedia%2Fcover.png" alt="cover"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A minimal terminal file browser built with &lt;a href="https://github.com/charmbracelet/bubbletea" rel="noopener noreferrer"&gt;Bubble Tea&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Peek through your filesystem with arrow keys (or vim keys), then pour each file straight into the app you've configured for it.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demo&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;A quick peek before you steep:&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/lovestaco/peektea/media/demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Flovestaco%2Fpeektea%2FHEAD%2Fmedia%2Fdemo.gif" alt="demo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;One-liner:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;curl -fsSL https://raw.githubusercontent.com/lovestaco/peektea/master/scripts/install.sh &lt;span class="pl-k"&gt;|&lt;/span&gt; sh&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Download a binary&lt;/strong&gt; (no Go required) — grab the latest release for your platform from the &lt;a href="https://github.com/lovestaco/peektea/releases/latest" rel="noopener noreferrer"&gt;releases page&lt;/a&gt;:&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linux x86-64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;peektea_*_linux_amd64.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux arm64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;peektea_*_linux_arm64.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS x86-64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;peektea_*_darwin_amd64.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS Apple Silicon&lt;/td&gt;
&lt;td&gt;&lt;code&gt;peektea_*_darwin_arm64.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Extract and put the &lt;code&gt;peektea&lt;/code&gt; binary anywhere on your &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Install with Go:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;go install github.com/lovestaco/peektea@latest&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Build from source:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/lovestaco/peektea
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; peektea
make install&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;make install&lt;/code&gt; puts the binary in &lt;code&gt;~/go/bin&lt;/code&gt; and figures out &lt;code&gt;$PATH&lt;/code&gt; for you:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Already reachable — done, nothing to do.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.local/bin&lt;/code&gt; is on your PATH — symlinks the binary there, works immediately in the current shell.&lt;/li&gt;
&lt;li&gt;Neither — appends &lt;code&gt;~/go/bin&lt;/code&gt; to your &lt;code&gt;.bashrc&lt;/code&gt;…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Filter as you type
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;/&lt;/code&gt; key enters filter mode. &lt;/p&gt;

&lt;p&gt;A text input appears at the bottom of the panel right above the hint bar, like &lt;a href="https://github.com/vim/vim" rel="noopener noreferrer"&gt;vim&lt;/a&gt;'s command line. &lt;/p&gt;

&lt;p&gt;Type anything and only matching entries stay visible. &lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;esc&lt;/code&gt; to clear it.&lt;/p&gt;

&lt;p&gt;The component doing the work is &lt;code&gt;textinput&lt;/code&gt; from &lt;a href="https://github.com/charmbracelet/bubbles" rel="noopener noreferrer"&gt;charmbracelet/bubbles&lt;/a&gt;, a library of ready-made Bubble Tea components.&lt;/p&gt;

&lt;p&gt;Wiring it into the model is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// ...&lt;/span&gt;
    &lt;span class="n"&gt;filterInput&lt;/span&gt; &lt;span class="n"&gt;textinput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;
    &lt;span class="n"&gt;filtering&lt;/span&gt;   &lt;span class="kt"&gt;bool&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When &lt;code&gt;/&lt;/code&gt; is pressed, focus the input and return &lt;code&gt;textinput.Blink&lt;/code&gt;, that's the command that starts the cursor blinking animation:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filtering&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filterInput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Focus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;textinput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Blink&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While filtering, most keystrokes go straight to the textinput's own &lt;code&gt;Update&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Navigation keys (&lt;code&gt;↑↓&lt;/code&gt;) are intercepted first so you can still move the cursor while typing:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filtering&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"k"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"down"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"j"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"esc"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filtering&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filterInput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Blur&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filterInput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withFilters&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tiCmd&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cmd&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filterInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tiCmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filterInput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withFilters&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tiCmd&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;tiCmd&lt;/code&gt; returned by &lt;code&gt;m.filterInput.Update&lt;/code&gt; carries the next blink tick. &lt;/p&gt;

&lt;p&gt;You have to pass it back out of &lt;code&gt;Update&lt;/code&gt;, drop it and the cursor freezes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Composable filters with withFilters()
&lt;/h2&gt;

&lt;p&gt;The model now stores two entry slices: &lt;code&gt;allEntries&lt;/code&gt; (everything &lt;code&gt;os.ReadDir&lt;/code&gt; returned) and &lt;code&gt;entries&lt;/code&gt; (what's visible after filters). &lt;/p&gt;

&lt;p&gt;Every filter change calls &lt;code&gt;withFilters()&lt;/code&gt; to recompute:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;withFilters&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filterInput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;filtered&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;DirEntry&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allEntries&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;showHidden&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filtered&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Hidden toggle and text filter compose naturally,  you can filter by name with dotfiles visible or hidden simultaneously. &lt;/p&gt;

&lt;p&gt;Adding a third filter later means touching one function.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;withFilters&lt;/code&gt; returns a new model value rather than mutating in place, which fits cleanly with Bubble Tea's immutable-update pattern.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hidden file toggle
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;.&lt;/code&gt; key flips &lt;code&gt;showHidden&lt;/code&gt; and calls &lt;code&gt;withFilters()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"."&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;showHidden&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;showHidden&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withFilters&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;needPreview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The hint bar reflects the current state so you always know where you are:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;. show hidden   ← dotfiles hidden
. hide hidden   ← dotfiles visible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Navigating into a directory clears the filter, the search you ran in one folder doesn't carry over to its children. &lt;/p&gt;

&lt;p&gt;Makes the behaviour predictable without any extra state to manage.&lt;/p&gt;
&lt;h2&gt;
  
  
  The vim-style bottom bar
&lt;/h2&gt;

&lt;p&gt;The filter input sits at the bottom of the panel, one line above the hint bar. &lt;/p&gt;

&lt;p&gt;That's the slot vim uses for its command line, &lt;code&gt;/pattern&lt;/code&gt;, &lt;code&gt;:w&lt;/code&gt;, &lt;code&gt;:q&lt;/code&gt;  so it feels immediately familiar.&lt;/p&gt;

&lt;p&gt;When filtering is active the text input renders there instead of the hint. &lt;/p&gt;

&lt;p&gt;When you press &lt;code&gt;enter&lt;/code&gt; to confirm and leave filter mode, the active filter stays visible:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/main  esc to clear
↑/↓  →/enter  o open  / filter  . hide hidden  p preview  ←/h  q
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The hint never disappears, even in filter mode it's always one line below. &lt;/p&gt;

&lt;p&gt;The layout calculates how many rows the file list consumed and pads blank lines to push both the filter bar and the hint bar to the very bottom of the terminal.&lt;/p&gt;



&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs — without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>cli</category>
      <category>go</category>
    </item>
    <item>
      <title>peektea opens a second eye 👀 side-by-side file previews</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Tue, 02 Jun 2026 19:31:31 +0000</pubDate>
      <link>https://dev.to/lovestaco/peektea-opens-a-second-eye-side-by-side-file-previews-n6j</link>
      <guid>https://dev.to/lovestaco/peektea-opens-a-second-eye-side-by-side-file-previews-n6j</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Last time, I ended with a "what's next" list.&lt;/p&gt;

&lt;p&gt;At the top of it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Image previews inline&lt;/strong&gt;: render images in the terminal via Kitty/iTerm protocols or &lt;code&gt;chafa&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Split-pane file preview&lt;/strong&gt;: selected file content on the right, so you can peek without leaving&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today both of those ship.&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;p&lt;/code&gt;. A preview panel opens on the right. Press &lt;code&gt;p&lt;/code&gt; again. It closes.&lt;/p&gt;

&lt;p&gt;That's it. That's the whole feature from the outside.&lt;/p&gt;

&lt;p&gt;The inside is more interesting.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/lovestaco" rel="noopener noreferrer"&gt;
        lovestaco
      &lt;/a&gt; / &lt;a href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;
        peektea
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Peek First. Open Later. A TUI file browser built with bubble tea
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/lovestaco/peektea/media/cover.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Flovestaco%2Fpeektea%2FHEAD%2Fmedia%2Fcover.png" alt="cover"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A minimal terminal file browser built with &lt;a href="https://github.com/charmbracelet/bubbletea" rel="noopener noreferrer"&gt;Bubble Tea&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Peek through your filesystem with arrow keys (or vim keys), then pour each file straight into the app you've configured for it.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demo&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;A quick peek before you steep:&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/lovestaco/peektea/media/demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Flovestaco%2Fpeektea%2FHEAD%2Fmedia%2Fdemo.gif" alt="demo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;One-liner:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;curl -fsSL https://raw.githubusercontent.com/lovestaco/peektea/master/scripts/install.sh &lt;span class="pl-k"&gt;|&lt;/span&gt; sh&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Download a binary&lt;/strong&gt; (no Go required) — grab the latest release for your platform from the &lt;a href="https://github.com/lovestaco/peektea/releases/latest" rel="noopener noreferrer"&gt;releases page&lt;/a&gt;:&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linux x86-64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;peektea_*_linux_amd64.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux arm64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;peektea_*_linux_arm64.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS x86-64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;peektea_*_darwin_amd64.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS Apple Silicon&lt;/td&gt;
&lt;td&gt;&lt;code&gt;peektea_*_darwin_arm64.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Extract and put the &lt;code&gt;peektea&lt;/code&gt; binary anywhere on your &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Install with Go:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;go install github.com/lovestaco/peektea@latest&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Build from source:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/lovestaco/peektea
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; peektea
make install&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;make install&lt;/code&gt; puts the binary in &lt;code&gt;~/go/bin&lt;/code&gt; and figures out &lt;code&gt;$PATH&lt;/code&gt; for you:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Already reachable — done, nothing to do.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.local/bin&lt;/code&gt; is on your PATH — symlinks the binary there, works immediately in the current shell.&lt;/li&gt;
&lt;li&gt;Neither — appends &lt;code&gt;~/go/bin&lt;/code&gt; to your &lt;code&gt;.bashrc&lt;/code&gt;…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  The preview panel
&lt;/h2&gt;

&lt;p&gt;peektea now renders in two columns when preview is on.&lt;/p&gt;

&lt;p&gt;Left: the file browser. Right: whatever's under the cursor.&lt;/p&gt;

&lt;p&gt;It handles four cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Text files&lt;/strong&gt;: first N lines, tab-expanded, truncated to panel width&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Images&lt;/strong&gt;: rendered inline via &lt;a href="https://hpjansson.org/chafa/" rel="noopener noreferrer"&gt;chafa&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Directories&lt;/strong&gt;: lists the contents with the same dir/file styling as the browser&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Binary files&lt;/strong&gt;: a &lt;code&gt;[binary file]&lt;/code&gt; notice instead of garbage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The preview updates as you navigate. &lt;/p&gt;

&lt;p&gt;Move the cursor, a new preview loads. &lt;/p&gt;

&lt;p&gt;Navigate into a directory, it previews the new selection.&lt;/p&gt;

&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%2Ffrau7rkinoajewvlqyx6.gif" 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%2Ffrau7rkinoajewvlqyx6.gif" alt=" " width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Async loading with tea.Cmd
&lt;/h2&gt;

&lt;p&gt;The preview can't block the TUI, reading a large file or running chafa takes time.&lt;/p&gt;

&lt;p&gt;In Bubble Tea, anything that takes time is a &lt;code&gt;tea.Cmd&lt;/code&gt;: a function that runs off the main loop and returns a message when it's done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;previewMsg&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;loadPreview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entry&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;DirEntry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cmd&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDir&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;previewMsg&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;previewDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;isImageExt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;previewMsg&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;previewImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;previewMsg&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;previewText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The model sets &lt;code&gt;previewLoading = true&lt;/code&gt; and fires the command. &lt;/p&gt;

&lt;p&gt;The panel shows &lt;code&gt;loading…&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;When the goroutine finishes, &lt;code&gt;previewMsg&lt;/code&gt; comes back through &lt;code&gt;Update&lt;/code&gt; and the panel renders the result.&lt;/p&gt;

&lt;p&gt;The TUI stays responsive the whole time, you can keep navigating while a slow preview loads.&lt;/p&gt;
&lt;h2&gt;
  
  
  Image previews via chafa
&lt;/h2&gt;

&lt;p&gt;chafa is a terminal image viewer that converts images into coloured Unicode blocks. &lt;/p&gt;

&lt;p&gt;It respects &lt;code&gt;--size WxH&lt;/code&gt; so the output fits exactly inside the preview panel.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;previewImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LookPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"chafa"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"[image — install chafa for inline preview]"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"chafa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"--size"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%dx%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[image preview failed: %v]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimRight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If chafa isn't installed, the panel tells you so. No crash, no silent blank.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;peektea init&lt;/code&gt; now checks for chafa at the end of setup and prints the install command for your distro if it's missing.&lt;/p&gt;
&lt;h2&gt;
  
  
  Binary detection
&lt;/h2&gt;

&lt;p&gt;Opening a binary file as text gives you noise. &lt;/p&gt;

&lt;p&gt;So before reading, peektea checks the first 512 bytes for null bytes, that's the standard heuristic used by &lt;code&gt;git diff&lt;/code&gt; and most editors.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;isBinary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&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;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If it's binary, the preview says &lt;code&gt;[binary file]&lt;/code&gt; and moves on.&lt;/p&gt;
&lt;h2&gt;
  
  
  Terminal size and the adaptive left panel
&lt;/h2&gt;

&lt;p&gt;To split the screen correctly, peektea needs to know how big it is.&lt;/p&gt;

&lt;p&gt;Bubble Tea sends a &lt;code&gt;tea.WindowSizeMsg&lt;/code&gt; whenever the terminal is resized. &lt;/p&gt;

&lt;p&gt;The model stores &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; and uses them to calculate panel dimensions on every render.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WindowSizeMsg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Width&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Height&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The left panel width isn't fixed, it starts at a minimum of 50 chars and then expands to fit the longest filename in the current directory:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;leftWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;minWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;minWidth&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;nameW&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;rune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDir&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;nameW&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;nameW&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nameW&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// Always leave at least 30 chars for the preview panel.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Navigate into a directory with long filenames and the left panel widens to accommodate. Navigate out and it shrinks back. &lt;/p&gt;

&lt;p&gt;The preview panel takes whatever's left.&lt;/p&gt;
&lt;h2&gt;
  
  
  The hint bar
&lt;/h2&gt;

&lt;p&gt;One last small thing: the hint bar at the bottom of the left panel is pinned to the very last row of the terminal, not floating just below the last entry.&lt;/p&gt;

&lt;p&gt;The panel counts how many lines the file list consumed and fills the gap with blank lines so the hint always sits at the floor. &lt;/p&gt;

&lt;p&gt;Feels more like a proper pane and less like text that happened to end there.&lt;/p&gt;
&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The list is getting shorter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;del&gt;Image previews inline&lt;/del&gt; ✓&lt;/li&gt;
&lt;li&gt;
&lt;del&gt;Split-pane file preview&lt;/del&gt; ✓&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter as you type&lt;/strong&gt; — Bubble Tea's &lt;code&gt;textinput&lt;/code&gt; component from &lt;a href="https://github.com/charmbracelet/bubbles" rel="noopener noreferrer"&gt;bubbles&lt;/a&gt; is sitting there waiting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden file toggle&lt;/strong&gt; — show/hide dotfiles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model grows, &lt;code&gt;Update&lt;/code&gt; handles new keys, &lt;code&gt;View&lt;/code&gt; renders the new state.&lt;/p&gt;

&lt;p&gt;That's still the whole pattern. It still scales. The puns still never run dry.&lt;/p&gt;

&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs — without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>cli</category>
      <category>beginners</category>
    </item>
    <item>
      <title>peektea v2: yesterday it peeked, today it actually opens things</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Mon, 01 Jun 2026 21:12:39 +0000</pubDate>
      <link>https://dev.to/lovestaco/peektea-v2-yesterday-it-peeked-today-it-actually-opens-things-njh</link>
      <guid>https://dev.to/lovestaco/peektea-v2-yesterday-it-peeked-today-it-actually-opens-things-njh</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Yesterday I shipped &lt;a href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;peektea&lt;/a&gt;,  a tiny terminal file browser in Go. &lt;/p&gt;

&lt;p&gt;It browsed. &lt;/p&gt;

&lt;p&gt;It peeked. &lt;/p&gt;

&lt;p&gt;And then it just... stood there, staring at your files, unable to do anything with them. All peek, no pour.&lt;/p&gt;

&lt;p&gt;Like a golden retriever that fetches the ball and won't drop it.&lt;/p&gt;

&lt;p&gt;Today that changes. peektea can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;open files&lt;/strong&gt; in your configured editor, image viewer, file manager, whatever you set up&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;detect your installed software&lt;/strong&gt; and walk you through setup with &lt;code&gt;peektea init&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tell you what it can do&lt;/strong&gt; with &lt;code&gt;peektea -h&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;uninstall itself cleanly&lt;/strong&gt; with &lt;code&gt;peektea uninstall&lt;/code&gt; (and ask nicely if you want your config deleted too)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the whole brew in action:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The demo GIF isn't rendering here on dev.to for some reason :( &lt;br&gt;
You can watch it on GitHub instead: &lt;a href="https://github.com/lovestaco/peektea#demo" rel="noopener noreferrer"&gt;lovestaco/peektea#demo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The config problem (or: how do you take your tea?)
&lt;/h2&gt;

&lt;p&gt;The moment you add "open files" to a file browser, you hit a question: open them &lt;em&gt;how&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.md&lt;/code&gt; files want vim. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;.png&lt;/code&gt; wants an image viewer. &lt;/p&gt;

&lt;p&gt;A directory wants a file manager. &lt;/p&gt;

&lt;p&gt;And everyone's machine is different, you might have &lt;code&gt;thunar&lt;/code&gt;, I might have &lt;code&gt;nautilus&lt;/code&gt;, someone else is running &lt;code&gt;dolphin&lt;/code&gt; and judging us both.&lt;/p&gt;

&lt;p&gt;So peektea reads &lt;code&gt;~/.peektea.toml&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The keys are derived straight from the file extension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file.md        → _md_config
archive.tar.gz → _tar_gz_config
hello.xd.dd    → _xd_dd_config
directory      → _dir_config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Dots become underscores, wrapped with &lt;code&gt;_&lt;/code&gt; and &lt;code&gt;_config&lt;/code&gt;. The whole config is one flat file:&lt;/p&gt;

&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%2Fqpx3vofjqtkbiww38wem.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%2Fqpx3vofjqtkbiww38wem.png" alt="image" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unknown extension? &lt;/p&gt;

&lt;p&gt;Falls through to &lt;code&gt;_default_config&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Completely missing key? &lt;/p&gt;

&lt;p&gt;Falls through to &lt;code&gt;vim&lt;/code&gt;.  The bag never comes up empty.&lt;/p&gt;

&lt;p&gt;You can configure literally any extension, including made-up ones like &lt;code&gt;_xd_dd_config&lt;/code&gt; for &lt;code&gt;hello.xd.dd&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The lookup is fully generalised. No extension is too obscure to brew.&lt;/p&gt;
&lt;h2&gt;
  
  
  peektea init: it takes a peek at your system first
&lt;/h2&gt;

&lt;p&gt;Writing that config by hand is annoying. &lt;/p&gt;

&lt;p&gt;So &lt;code&gt;peektea init&lt;/code&gt; does it for you.&lt;/p&gt;

&lt;p&gt;It scans your &lt;code&gt;$PATH&lt;/code&gt;, finds what's actually installed, and asks you to pick:&lt;/p&gt;

&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%2F0edtgk2p3x9swqmxlzya.gif" 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%2F0edtgk2p3x9swqmxlzya.gif" alt="peektea init" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If there's only one option for a category it auto-selects it and moves on.&lt;/p&gt;

&lt;p&gt;If there are multiple, you get a picker — arrow keys or just type the number and it jumps immediately.  Pick your poison, or your potion.&lt;/p&gt;

&lt;p&gt;The whole wizard is a Bubble Tea program running inside a CLI command. (Yes, the puns write themselves here.)&lt;/p&gt;

&lt;p&gt;That last part is the interesting bit. &lt;/p&gt;

&lt;p&gt;The picker isn't a plain stdin readline, it's a full &lt;code&gt;tea.Model&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;pickerModel&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;pickerModel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KeyMsg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"k"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"down"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"j"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"enter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quit&lt;/span&gt;
        &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="c"&gt;// type a number → jump and confirm immediately&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quit&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;tea.NewProgram(pickerModel{options: found}).Run()&lt;/code&gt; — that's the whole pot.&lt;/p&gt;

&lt;p&gt;You get a full keyboard-driven selector inside what looks like a plain terminal prompt. &lt;/p&gt;

&lt;p&gt;Bubble Tea handles all the rendering and input, you just describe the model and let it steep.&lt;/p&gt;
&lt;h2&gt;
  
  
  Opening files: the terminal vs GUI problem
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;o&lt;/code&gt; key opens whatever's under the cursor. One keystroke and you're peeking inside.&lt;/p&gt;

&lt;p&gt;Simple enough, except there's a catch in the kettle.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;terminal editors&lt;/strong&gt; like vim, you want to hand the terminal over completely. &lt;/p&gt;

&lt;p&gt;Vim needs raw input, it needs to own the screen - the whole table, not just a saucer.&lt;/p&gt;

&lt;p&gt;The right Bubble Tea API for this is &lt;code&gt;tea.ExecProcess&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;openResultMsg&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;tea.ExecProcess&lt;/code&gt; suspends the Bubble Tea event loop, gives the child process the full terminal, and resumes peektea when you quit. &lt;/p&gt;

&lt;p&gt;It's the same trick that lets you run vim from inside ranger or lf.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;GUI apps&lt;/strong&gt; like nautilus or feh, you do the opposite, launch them in the background and keep the TUI brewing:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// reap the child so it doesn't become a zombie&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;But how does peektea know which is which? &lt;/p&gt;

&lt;p&gt;It keeps a set of known terminal programs like vim, nvim, nano, micro, helix, etc.  and anything not in that set gets backgrounded. &lt;/p&gt;

&lt;p&gt;You can extend it in your config:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;terminal_programs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"vim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"nvim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"nano"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hx"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  peektea -h
&lt;/h2&gt;

&lt;p&gt;Every proper CLI tool deserves a &lt;code&gt;-h&lt;/code&gt;.  Consider it the menu before you order.&lt;/p&gt;

&lt;p&gt;Here's what it looks like now:&lt;/p&gt;

&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%2F3wcoouqzo1ovsmde6ez6.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%2F3wcoouqzo1ovsmde6ez6.png" alt="peektea help" width="506" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And yes, &lt;code&gt;peektea uninstall&lt;/code&gt; exists. &lt;/p&gt;

&lt;p&gt;It finds the binary via &lt;code&gt;os.Executable()&lt;/code&gt;, tells you exactly what it's about to delete, asks for confirmation, and then asks separately if you want the config gone too. &lt;/p&gt;

&lt;p&gt;No silent nuke. No tea spilled without warning.&lt;/p&gt;
&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The original dream was &lt;code&gt;ncdu&lt;/code&gt;-style navigation with inline image previews in the terminal. A proper sneak peek, right in the pane.&lt;/p&gt;

&lt;p&gt;That's still where this is headed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image previews inline&lt;/strong&gt; — render images in the terminal via Kitty/iTerm protocols or &lt;code&gt;chafa&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split-pane file preview&lt;/strong&gt; — selected file content on the right, so you can peek without leaving&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter as you type&lt;/strong&gt; — Bubble Tea ships a &lt;code&gt;textinput&lt;/code&gt; component in &lt;a href="https://github.com/charmbracelet/bubbles" rel="noopener noreferrer"&gt;bubbles&lt;/a&gt; for exactly this&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden file toggle&lt;/strong&gt; — show/hide dotfiles for the leaves that like to lurk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model grows, &lt;code&gt;Update&lt;/code&gt; handles new keys, &lt;code&gt;View&lt;/code&gt; renders the new state. &lt;/p&gt;

&lt;p&gt;That's the whole Bubble Tea pattern. It scales surprisingly cleanly and the puns never run dry.&lt;/p&gt;



&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs — without telling you. You often find out in production.&lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.&lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.&lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>go</category>
      <category>cli</category>
    </item>
    <item>
      <title>peektea: brewing a terminal file browser with Bubble Tea</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Sun, 31 May 2026 19:00:22 +0000</pubDate>
      <link>https://dev.to/lovestaco/peektea-brewing-a-terminal-file-browser-with-bubble-tea-4jg1</link>
      <guid>https://dev.to/lovestaco/peektea-brewing-a-terminal-file-browser-with-bubble-tea-4jg1</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback for improving the project.&lt;/em&gt;&lt;/p&gt; 




&lt;p&gt;What I actually want is an &lt;code&gt;ncdu&lt;/code&gt;-style file browser fully keyboard-driven, where I can hop through directories &lt;em&gt;and&lt;/em&gt; open files straight into Nautilus, vim, Nemo, whatever, even preview images right in the terminal. &lt;/p&gt;

&lt;p&gt;No mouse, no leaving the keyboard.&lt;/p&gt;

&lt;p&gt;But that's a big pot to brew. &lt;/p&gt;

&lt;p&gt;So I started small and used it as an excuse to learn &lt;a href="https://github.com/charmbracelet/bubbletea" rel="noopener noreferrer"&gt;Bubble Tea&lt;/a&gt;, Charmbracelet's Go TUI framework. &lt;/p&gt;

&lt;p&gt;The result is &lt;strong&gt;&lt;a href="https://github.com/lovestaco/peektea" rel="noopener noreferrer"&gt;peektea&lt;/a&gt;&lt;/strong&gt;: a minimal version that, for now, just &lt;em&gt;browses&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Run it, arrow your way through directories, pop back up to the parent. &lt;/p&gt;

&lt;p&gt;That's the whole cup of tea so far. &lt;/p&gt;

&lt;p&gt;~140 lines of Go: the opening-files-and-previewing-images part is where it's headed next.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's Bubble Tea?
&lt;/h2&gt;

&lt;p&gt;Bubble Tea is a Go framework for building terminal UIs, built on the &lt;a href="https://guide.elm-lang.org/architecture/" rel="noopener noreferrer"&gt;Elm Architecture&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Which is a fancy way of saying your entire app boils down to three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt; — the state of your program&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update&lt;/strong&gt; — a function that takes events and returns a &lt;em&gt;new&lt;/em&gt; model&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View&lt;/strong&gt; — a function that renders the model to a string&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No mutation, no spilled state. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Update&lt;/code&gt; and &lt;code&gt;View&lt;/code&gt; are pure functions. &lt;/p&gt;

&lt;p&gt;The framework handles the event loop, terminal I/O, and all the redrawing so you don't have to. &lt;/p&gt;

&lt;p&gt;You just describe what things should look like and it does the dishes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dir&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;entries&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;DirEntry&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt;     &lt;span class="kt"&gt;error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's the &lt;em&gt;entire&lt;/em&gt; state of peektea.&lt;/p&gt;

&lt;p&gt;The current directory, what's in it, where the cursor sits, and whether something went sideways. &lt;/p&gt;

&lt;p&gt;When you navigate into a new directory you don't mutate anything in place, &lt;code&gt;Update&lt;/code&gt; hands back a fresh model with the new values.&lt;/p&gt;
&lt;h2&gt;
  
  
  The update loop (where the tea gets stirred)
&lt;/h2&gt;

&lt;p&gt;Every keypress shows up as a &lt;code&gt;tea.KeyMsg&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;You pattern-match on it and return the next model:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KeyMsg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"right"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"l"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"enter"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDir&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&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;ReadDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;
                    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt;
                    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// ...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That second return value, &lt;code&gt;tea.Cmd&lt;/code&gt;, is a function that runs asynchronously and produces the next message. &lt;/p&gt;

&lt;p&gt;Here &lt;code&gt;Update&lt;/code&gt; is fully synchronous, so we just return &lt;code&gt;nil&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;But the moment you want to fetch data or read files in the background, &lt;code&gt;Cmd&lt;/code&gt; is how you do it &lt;em&gt;without&lt;/em&gt; blocking the UI. &lt;/p&gt;

&lt;p&gt;Think of it as putting the kettle on and getting pinged when it's ready, instead of standing there watching it.&lt;/p&gt;

&lt;p&gt;One small touch worth calling out: when you go back up to the parent directory, the cursor lands right back on the folder you just came out of, instead of snapping to the top. &lt;/p&gt;

&lt;p&gt;It's just a little loop over the entries to find the matching name  but it makes navigation feel natural instead of jarring.&lt;/p&gt;
&lt;h2&gt;
  
  
  The view
&lt;/h2&gt;

&lt;p&gt;Rendering is a pure string transformation. &lt;/p&gt;

&lt;p&gt;Bubble Tea calls &lt;code&gt;View()&lt;/code&gt; after every &lt;code&gt;Update&lt;/code&gt; and redraws the terminal for you.&lt;/p&gt;

&lt;p&gt;Styling comes from &lt;a href="https://github.com/charmbracelet/lipgloss" rel="noopener noreferrer"&gt;Lipgloss&lt;/a&gt;, also from Charmbracelet (they really committed to the tea house aesthetic).&lt;/p&gt;

&lt;p&gt;You define styles once at the package level:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;cursorStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lipgloss&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewStyle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Foreground&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lipgloss&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"212"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dirStyle&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lipgloss&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewStyle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Foreground&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lipgloss&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"39"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;fileStyle&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lipgloss&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewStyle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Foreground&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lipgloss&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"252"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then call &lt;code&gt;.Render(s)&lt;/code&gt; on them anywhere in your view. Directories get a trailing &lt;code&gt;/&lt;/code&gt; and a cyan tint, the cursor row gets a background highlight, and the selected entry gets a &lt;code&gt;▶&lt;/code&gt; so you always know where you are.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wiring it up
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&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;Getwd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewProgram&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithAltScreen&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The one line worth highlighting is &lt;code&gt;tea.WithAltScreen()&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;It flips the terminal into the alternate screen buffer — the same trick &lt;code&gt;vim&lt;/code&gt; and &lt;code&gt;htop&lt;/code&gt; use. &lt;/p&gt;

&lt;p&gt;Your TUI takes over the whole terminal, and when you quit, your shell session comes back clean like nothing happened. &lt;/p&gt;

&lt;p&gt;Without it, your UI just dumps into the scrollback like any other output. &lt;/p&gt;

&lt;p&gt;Nobody wants tea stains on their terminal history.&lt;/p&gt;

&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%2Fy4ojscj47l67inis37tl.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%2Fy4ojscj47l67inis37tl.png" alt="image" width="540" height="295"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What I'd steep next
&lt;/h2&gt;

&lt;p&gt;This is where the &lt;code&gt;ncdu&lt;/code&gt;-style dream actually starts brewing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open files in your editor/app&lt;/strong&gt; — &lt;code&gt;enter&lt;/code&gt; on a file shells out to vim, or hands it to Nautilus/Nemo/&lt;code&gt;xdg-open&lt;/code&gt; based on type&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image previews in the terminal&lt;/strong&gt; — render images inline via Kitty/iTerm protocols or &lt;code&gt;chafa&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File previews&lt;/strong&gt; — split the screen, show the selected file's content on the right&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filtering&lt;/strong&gt; — type to narrow the list (Bubble Tea ships a &lt;code&gt;textinput&lt;/code&gt; in &lt;a href="https://github.com/charmbracelet/bubbles" rel="noopener noreferrer"&gt;bubbles&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden file toggle&lt;/strong&gt; — &lt;code&gt;h&lt;/code&gt; to show/hide dotfiles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of it stays keyboard-driven no reaching for the mouse. As they land, they'll be in the repo. &lt;/p&gt;

&lt;p&gt;The nice thing is the framework makes each one refreshingly easy: you extend the model and handle new keys in &lt;code&gt;Update&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;That's the whole pattern.&lt;/p&gt;



&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. &lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.* &lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use. &lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub: &lt;br&gt;
 &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>go</category>
    </item>
    <item>
      <title>You Have a Free AI Model Sitting in Chrome Right Now</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Sat, 30 May 2026 18:47:06 +0000</pubDate>
      <link>https://dev.to/lovestaco/you-have-a-free-ai-model-sitting-in-chrome-right-now-43c3</link>
      <guid>https://dev.to/lovestaco/you-have-a-free-ai-model-sitting-in-chrome-right-now-43c3</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback for improving the project.&lt;/em&gt;&lt;/p&gt; 

&lt;p&gt;You might not have noticed, but Chrome quietly started shipping a local AI model called &lt;strong&gt;Gemini Nano&lt;/strong&gt;  bundled right into the browser. &lt;/p&gt;

&lt;p&gt;No API keys. No cloud round-trips. No per-token cost. It just runs on your machine.&lt;/p&gt;

&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%2Fwzksxqstc1ugjf17n5vx.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%2Fwzksxqstc1ugjf17n5vx.png" alt=" " width="360" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The interface to talk to it is called the &lt;strong&gt;Prompt API&lt;/strong&gt;, and it landed in Chrome 138. &lt;/p&gt;

&lt;p&gt;I spent some time going through the full API surface and built a &lt;a href="https://github.com/lovestaco/gemini-brow" rel="noopener noreferrer"&gt;playground&lt;/a&gt; that lets you experiment with every feature session management, streaming, structured output, multimodal input, response prefixing, and more  in one page.&lt;/p&gt;

&lt;p&gt;This post walks you through all of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does this matter?
&lt;/h2&gt;

&lt;p&gt;On-device AI flips the usual tradeoffs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free at runtime&lt;/strong&gt; — the model runs on the user's hardware, not your servers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private by default&lt;/strong&gt; — no data leaves the device once the model is downloaded&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works offline&lt;/strong&gt; — after the initial download, no network required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low latency&lt;/strong&gt; — no round-trip to a data centre&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The catch is that Gemini Nano is a small model. &lt;/p&gt;

&lt;p&gt;It's great for classification, summarization, Q&amp;amp;A on focused content, and structured extraction. &lt;/p&gt;

&lt;p&gt;It won't replace GPT-4 for complex reasoning. &lt;/p&gt;

&lt;p&gt;Think of it as a smart, free, always-available layer you can add on top of your existing product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enabling the API
&lt;/h2&gt;

&lt;p&gt;The Prompt API isn't on by default in all Chrome builds. Enable two flags:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt; — Go to &lt;code&gt;chrome://flags/#optimization-guide-on-device-model&lt;/code&gt; and set it to &lt;strong&gt;Enabled BypassPerfRequirement&lt;/strong&gt;.&lt;/p&gt;

&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%2Fg7fv7zc8tg22wv073lcx.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%2Fg7fv7zc8tg22wv073lcx.png" alt="enable optimization guide on device" width="799" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt; — Go to &lt;code&gt;chrome://flags/#prompt-api-for-gemini-nano&lt;/code&gt; and enable both the base API and the multimodal option.&lt;/p&gt;

&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%2Fr37mek4u1ge0he9d0nli.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%2Fr37mek4u1ge0he9d0nli.png" alt="prompt api for gemini nano, prompt api for gemini nano with multimodel input" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Relaunch Chrome. &lt;/p&gt;

&lt;p&gt;Then visit &lt;code&gt;chrome://on-device-internals&lt;/code&gt; to check the model download status. First use will trigger a download — Gemini Nano is a few gigabytes.&lt;/p&gt;

&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%2Fsjeihk15ho89nhneg50m.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%2Fsjeihk15ho89nhneg50m.png" alt=" " width="360" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2F53xu5343v76d9fetx7la.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%2F53xu5343v76d9fetx7la.png" alt=" " width="800" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Playground
&lt;/h2&gt;

&lt;p&gt;I put together a single-file HTML playground that covers the entire API surface. &lt;/p&gt;

&lt;p&gt;Clone it and open &lt;code&gt;playground.html&lt;/code&gt; directly in Chrome  no build step, no server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/lovestaco/gemini-brow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then open &lt;code&gt;playground.html&lt;/code&gt; in Chrome 138+.&lt;/p&gt;
&lt;h2&gt;
  
  
  Session Setup and Context Window
&lt;/h2&gt;

&lt;p&gt;Everything starts with a &lt;strong&gt;session&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;You create one with &lt;code&gt;LanguageModel.create()&lt;/code&gt;, optionally passing a system prompt and expected input/output modalities.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;LanguageModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;initialPrompts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You are a helpful and friendly assistant.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;expectedInputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;expectedOutputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Always call &lt;code&gt;LanguageModel.availability()&lt;/code&gt; with the &lt;strong&gt;same options&lt;/strong&gt; you'll pass to &lt;code&gt;create()&lt;/code&gt; before creating a session  the model may not support certain modalities on every device.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;avail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;LanguageModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;availability&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;expectedInputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;expectedOutputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// 'available' | 'downloadable' | 'downloading' | 'unavailable'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Each session has a &lt;strong&gt;context window&lt;/strong&gt;  a token budget that tracks everything in the conversation. &lt;/p&gt;

&lt;p&gt;When it fills up, the oldest prompt/response pairs are dropped (but the system prompt is never dropped). &lt;/p&gt;

&lt;p&gt;You can monitor it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contextUsage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; / &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contextWindow&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; tokens used`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;contextoverflow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oldest turns are being dropped to make room&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The playground shows a live progress bar for context usage, and a warning badge on overflow.&lt;/p&gt;

&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%2Fh9ppywa7gak2fxmgjhyd.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%2Fh9ppywa7gak2fxmgjhyd.png" alt="Chrome Prompt API Playground: Session Setup, Context Window" width="799" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also &lt;strong&gt;clone&lt;/strong&gt; a session to fork the conversation at a point in time — the clone is fully independent and won't see future messages sent to the original.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;forkedSession&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And &lt;strong&gt;destroy&lt;/strong&gt; it when you're done to free resources:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Prompting the Model
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Request-based (wait for the full response)
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;prompt()&lt;/code&gt; when you want the complete output before rendering:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Write me a short haiku about coffee.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Pass an &lt;code&gt;AbortController&lt;/code&gt; signal to add a stop button:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;stopBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Write me a poem!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&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%2Fidg6mf1kd2twe9zopmaw.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%2Fidg6mf1kd2twe9zopmaw.png" alt="Prompt — request-based" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Streaming (show output as it generates)
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;promptStreaming()&lt;/code&gt; for longer responses. &lt;/p&gt;

&lt;p&gt;It returns a &lt;code&gt;ReadableStream&lt;/code&gt; where each chunk is a &lt;strong&gt;delta&lt;/strong&gt;  the new tokens only. &lt;/p&gt;

&lt;p&gt;Accumulate them yourself:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;promptStreaming&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Explain how a browser renders a web page.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fullText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fullText&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;outputEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fullText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the right pattern, don't replace the display with each raw chunk or you'll get flickering (each chunk is only a word or two).&lt;/p&gt;
&lt;h2&gt;
  
  
  Append Messages
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;session.append()&lt;/code&gt; lets you pre-load context into the session without triggering a response. This is useful when you want the model to process heavy inputs (like images) while the user is still typing their question.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pre-load context&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Here is the document you will answer questions about: ...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}]);&lt;/span&gt;

&lt;span class="c1"&gt;// Later, ask the question&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;What are the key takeaways?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The promise from &lt;code&gt;append()&lt;/code&gt; resolves once the input has been processed and is ready in the session's context.&lt;/p&gt;

&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%2Fkrrvwf5gqgi92fut7djt.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%2Fkrrvwf5gqgi92fut7djt.png" alt="Append Messages" width="800" height="698"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Image Input (Multimodal)
&lt;/h2&gt;

&lt;p&gt;If your device has a GPU with more than 4 GB VRAM, the model can process images. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Image input needs its own session&lt;/strong&gt;  you must declare &lt;code&gt;{ type: 'image' }&lt;/code&gt; in &lt;code&gt;expectedInputs&lt;/code&gt; at creation time, and check availability separately since not all devices support it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageAvail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;LanguageModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;availability&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;expectedInputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;expectedOutputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageAvail&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unavailable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// GPU requirement not met&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageSession&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;LanguageModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;expectedInputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;expectedOutputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageBlob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;photo.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;imageSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;What is in this image?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageBlob&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The API accepts &lt;code&gt;Blob&lt;/code&gt;, &lt;code&gt;HTMLImageElement&lt;/code&gt;, &lt;code&gt;HTMLCanvasElement&lt;/code&gt;, &lt;code&gt;ImageBitmap&lt;/code&gt;, &lt;code&gt;ImageData&lt;/code&gt;, and more. In the playground, you can upload any image file and ask the model about it.&lt;/p&gt;

&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%2Faosavqvxb7hqm0d5k030.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%2Faosavqvxb7hqm0d5k030.png" alt="Image Input" width="800" height="673"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2Fxzmdcj37howfvct7tml4.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%2Fxzmdcj37howfvct7tml4.png" alt=" " width="280" height="420"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Response Prefix — Force an Output Format
&lt;/h2&gt;

&lt;p&gt;One of my favourite features. &lt;/p&gt;

&lt;p&gt;You can prefill the &lt;strong&gt;start&lt;/strong&gt; of the assistant's response by passing an assistant-role message with &lt;code&gt;prefix: true&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The model is forced to continue from that prefix.&lt;/p&gt;

&lt;p&gt;This is a clean way to lock in an output format without relying on instruction-following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Force the model to start its response with ```&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;endraw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;toml&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Create a character sheet for a gnome barbarian.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;
{% raw %}
```toml&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="c1"&gt;// result continues from the prefix: ```&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;endraw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;toml&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;nname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...
{% raw %}

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In the playground, you can set any prefix string and watch the model continue from exactly that point.&lt;/p&gt;

&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%2Fbb6pvm2n4zksygos2vge.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%2Fbb6pvm2n4zksygos2vge.png" alt="Response Prefix" width="800" height="710"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Boolean Classification
&lt;/h2&gt;

&lt;p&gt;Need a fast yes/no answer? Pass &lt;code&gt;{ type: 'boolean' }&lt;/code&gt; as the &lt;code&gt;responseConstraint&lt;/code&gt; and you'll always get back a raw &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; — no parsing, no prompt engineering around output format:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
js
const raw = await session.prompt(
  `Is this post about pottery?\n\n"${text}"`,
  { responseConstraint: { type: 'boolean' } }
);

const result = JSON.parse(raw); // true or false


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This is great for content moderation, topic detection, or gating features based on page content.&lt;/p&gt;

&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%2F7yfx9dxd6b2344qt30zg.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%2F7yfx9dxd6b2344qt30zg.png" alt="Boolean Classification" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Structured Output with JSON Schema
&lt;/h2&gt;

&lt;p&gt;The full power of &lt;code&gt;responseConstraint&lt;/code&gt; is a complete &lt;strong&gt;JSON Schema&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;The model is constrained to produce valid JSON that matches your schema  no hallucinated keys, no wrong types.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
js
const schema = {
  type: 'object',
  properties: {
    sentiment: { type: 'string', enum: ['positive', 'negative', 'neutral'] },
    score:     { type: 'number', minimum: 0, maximum: 10 },
    summary:   { type: 'string' },
  },
  required: ['sentiment', 'score', 'summary'],
};

const raw = await session.prompt(
  `Analyze the sentiment of this review:\n\n"${reviewText}"`,
  { responseConstraint: schema }
);

const data = JSON.parse(raw);
// { sentiment: 'positive', score: 8.5, summary: '...' }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: the schema itself uses some tokens from your context window. You can measure how many with &lt;code&gt;session.measureContextUsage({ responseConstraint: schema })&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&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%2Fikkm8coaoj171obld0rc.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%2Fikkm8coaoj171obld0rc.png" alt="Structured Output" width="799" height="350"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;Here's how these features combine in a real use case. &lt;/p&gt;

&lt;p&gt;Say you're building a Chrome Extension that summarises product reviews on any e-commerce page:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
js
// 1. Check availability
const avail = await LanguageModel.availability({
  expectedInputs:  [{ type: 'text', languages: ['en'] }],
  expectedOutputs: [{ type: 'text', languages: ['en'] }],
});
if (avail === 'unavailable') return;

// 2. Create a session with context
const session = await LanguageModel.create({
  initialPrompts: [{
    role: 'system',
    content: 'You analyse product reviews and extract structured insights.',
  }],
  expectedInputs:  [{ type: 'text', languages: ['en'] }],
  expectedOutputs: [{ type: 'text', languages: ['en'] }],
});

// 3. Pre-load the reviews while user looks at the page
await session.append([{
  role: 'user',
  content: `Here are the reviews:\n\n${scrapedReviews}`,
}]);

// 4. Get structured output
const schema = {
  type: 'object',
  properties: {
    verdict:  { type: 'string', enum: ['buy', 'skip', 'depends'] },
    pros:     { type: 'array', items: { type: 'string' } },
    cons:     { type: 'array', items: { type: 'string' } },
    summary:  { type: 'string' },
  },
  required: ['verdict', 'pros', 'cons', 'summary'],
};

const result = JSON.parse(
  await session.prompt('Summarise these reviews.', { responseConstraint: schema })
);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Zero API cost. &lt;/p&gt;

&lt;p&gt;Runs entirely on the user's machine. &lt;/p&gt;

&lt;p&gt;Works offline after first load.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try the playground
&lt;/h2&gt;

&lt;p&gt;The full playground is one HTML file no dependencies, no build step:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/lovestaco/gemini-brow" rel="noopener noreferrer"&gt;github.com/lovestaco/gemini-brow&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Clone it, open &lt;code&gt;playground.html&lt;/code&gt; in Chrome 138+, enable the flags above, and every feature in this post is wired up and ready to experiment with.&lt;/p&gt;

&lt;p&gt;The Prompt API is still evolving, language support is limited (&lt;code&gt;en&lt;/code&gt;, &lt;code&gt;ja&lt;/code&gt;, &lt;code&gt;es&lt;/code&gt; for now), mobile isn't supported yet, and the model is small. &lt;/p&gt;

&lt;p&gt;But the fundamentals are solid and the use cases where it shines  classification, summarization, extraction, Q&amp;amp;A on focused content  are genuinely useful without touching your server budget.&lt;/p&gt;

&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. &lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.* &lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use. &lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub: &lt;br&gt;
 &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>node</category>
    </item>
    <item>
      <title>What actually happens when you run `go run main.go`</title>
      <dc:creator>Athreya aka Maneshwar</dc:creator>
      <pubDate>Fri, 29 May 2026 10:11:16 +0000</pubDate>
      <link>https://dev.to/lovestaco/what-actually-happens-when-you-run-go-run-maingo-13l4</link>
      <guid>https://dev.to/lovestaco/what-actually-happens-when-you-run-go-run-maingo-13l4</guid>
      <description>&lt;p&gt;&lt;em&gt;Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;Star git-lrc&lt;/a&gt; to help devs discover the project. Do give it a try and share your feedback for improving the project.&lt;/em&gt;&lt;/p&gt; 

&lt;p&gt;# What actually happens when you run &lt;code&gt;go run main.go&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You've typed it hundreds of times. &lt;/p&gt;

&lt;p&gt;The program runs. &lt;/p&gt;

&lt;p&gt;But what's &lt;em&gt;actually&lt;/em&gt; going on between pressing Enter and your first &lt;code&gt;fmt.Println&lt;/code&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  The full picture
&lt;/h2&gt;

&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%2Flhstk5cadw2cve17r8ux.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%2Flhstk5cadw2cve17r8ux.png" alt="image" width="280" height="1329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: You press Enter
&lt;/h2&gt;

&lt;p&gt;Your shell finds &lt;code&gt;go&lt;/code&gt; in &lt;code&gt;$PATH&lt;/code&gt;, usually &lt;code&gt;/usr/local/go/bin/go&lt;/code&gt; or wherever your version manager (like &lt;code&gt;asdf&lt;/code&gt; or &lt;code&gt;goenv&lt;/code&gt;) installed it. &lt;/p&gt;

&lt;p&gt;Unlike &lt;code&gt;npm run dev&lt;/code&gt;, there's no separate launcher script. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;go&lt;/code&gt; binary is the single front-end to your whole toolchain build driver, dependency manager, test runner, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: The &lt;code&gt;go&lt;/code&gt; command parses your arguments
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;go run&lt;/code&gt; is one of many subcommands (&lt;code&gt;go build&lt;/code&gt;, &lt;code&gt;go test&lt;/code&gt;, &lt;code&gt;go mod tidy&lt;/code&gt;...). &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;go&lt;/code&gt; binary dispatches accordingly. &lt;/p&gt;

&lt;p&gt;For &lt;code&gt;go run main.go&lt;/code&gt; it does essentially two things: &lt;strong&gt;build&lt;/strong&gt; and then &lt;strong&gt;exec&lt;/strong&gt; the result.&lt;/p&gt;

&lt;p&gt;One thing worth clearing up: the &lt;code&gt;go&lt;/code&gt; command itself doesn't &lt;em&gt;compile&lt;/em&gt; anything. &lt;/p&gt;

&lt;p&gt;It's a driver that orchestrates the build, invoking the individual toolchain programs  &lt;code&gt;compile&lt;/code&gt;, &lt;code&gt;asm&lt;/code&gt;, &lt;code&gt;link&lt;/code&gt;, &lt;code&gt;pack&lt;/code&gt;  that live in &lt;code&gt;$GOROOT/pkg/tool/$GOOS_$GOARCH/&lt;/code&gt;, each as a separate process. &lt;/p&gt;

&lt;p&gt;You can watch the whole sequence with &lt;code&gt;go build -x&lt;/code&gt;, which prints every tool invocation it makes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lovestaco@i3nux-mint:~/pers/blogs/go-rate-limiters&lt;span class="nv"&gt;$ &lt;/span&gt;go build &lt;span class="nt"&gt;-x&lt;/span&gt; 01_token_bucket_basic.go
&lt;span class="nv"&gt;WORK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/go-build1951611363
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/tmp/go-build1951611363/b001/importcfg &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;' # internal
# import config
packagefile context=/home/lovestaco/.cache/go-build/15/1575351e64b96edf357d10ac88f3cab30fcb1cfa9a191331bcad6190a73853f4-d
packagefile fmt=/home/lovestaco/.cache/go-build/51/516c0f36e371fc103e5e31bffc64e8899c256a1d9278377baeaee3c3d67d5990-d
packagefile golang.org/x/time/rate=/home/lovestaco/.cache/go-build/d5/d5dd928826b919bdb04e4142718ffda25ffa97a1f788e61444596c150f6df76a-d
packagefile time=/home/lovestaco/.cache/go-build/2b/2ba963660e1b7abf46deaef03614f8cce1f6230e971041e2f60a9b8b5bca5326-d
packagefile runtime=/home/lovestaco/.cache/go-build/f0/f09fa4ced4d67a86c477e2daecfaf39fccd7d0cb936478c5d73427221189029e-d
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /home/lovestaco/pers/blogs/go-rate-limiters
/usr/local/go/pkg/tool/linux_amd64/compile &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/_pkg_.a &lt;span class="nt"&gt;-trimpath&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORK&lt;/span&gt;&lt;span class="s2"&gt;/b001=&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; main &lt;span class="nt"&gt;-lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;go1.24 &lt;span class="nt"&gt;-complete&lt;/span&gt; &lt;span class="nt"&gt;-buildid&lt;/span&gt; cR1ay72gpouW8Dj1wpHA/cR1ay72gpouW8Dj1wpHA &lt;span class="nt"&gt;-goversion&lt;/span&gt; go1.24.4 &lt;span class="nt"&gt;-c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4 &lt;span class="nt"&gt;-nolocalimports&lt;/span&gt; &lt;span class="nt"&gt;-importcfg&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/importcfg &lt;span class="nt"&gt;-pack&lt;/span&gt; ./01_token_bucket_basic.go
/usr/local/go/pkg/tool/linux_amd64/buildid &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/_pkg_.a &lt;span class="c"&gt;# internal&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/_pkg_.a /home/lovestaco/.cache/go-build/7f/7fa4c76fda90e3f91bee04d9326171d548b473efc9a5a49059e5650d52c7ed40-d &lt;span class="c"&gt;# internal&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/tmp/go-build1951611363/b001/importcfg.link &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;' # internal
packagefile command-line-arguments=/tmp/go-build1951611363/b001/_pkg_.a
packagefile context=/home/lovestaco/.cache/go-build/15/1575351e64b96edf357d10ac88f3cab30fcb1cfa9a191331bcad6190a73853f4-d
packagefile internal/oserror=/home/lovestaco/.cache/go-build/38/38a0285b4078334a8d1c6a928e079b3ee65331a955fae62da547452857e18da5-d
packagefile path=/home/lovestaco/.cache/go-build/24/24092a25546a3b8c3771592daca75c8fb2d416c84952f466cc92fcb99959688c-d
modinfo "0w&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;af&lt;/span&gt;&lt;span class="se"&gt;\f\x&lt;/span&gt;&lt;span class="sh"&gt;92t&lt;/span&gt;&lt;span class="se"&gt;\b\x&lt;/span&gt;&lt;span class="sh"&gt;02A&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;e1&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;c1&lt;/span&gt;&lt;span class="se"&gt;\a\x&lt;/span&gt;&lt;span class="sh"&gt;e6&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;d6&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;18&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;e6path&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;command-line-arguments&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;dep&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;golang.org/x/time&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;v0.5.0&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;-buildmode=exe&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;-compiler=gc&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;DefaultGODEBUG=asynctimerchan=1,gotestjsonbuildtext=1,gotypesalias=0,httplaxcontentlength=1,httpmuxgo121=1,httpservecontentkeepheaders=1,multipathtcp=0,randseednop=0,rsa1024min=0,tls10server=1,tls3des=1,tlsmlkem=0,tlsrsakex=1,tlsunsafeekm=1,winreadlinkvolume=0,winsymlink=0,x509keypairleaf=0,x509negativeserial=1,x509rsacrt=0,x509usepolicies=0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;CGO_ENABLED=1&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;CGO_CFLAGS=&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;CGO_CPPFLAGS=&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;CGO_CXXFLAGS=&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;CGO_LDFLAGS=&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;GOARCH=amd64&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;GOOS=linux&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;build&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sh"&gt;GOAMD64=v1&lt;/span&gt;&lt;span class="se"&gt;\n\x&lt;/span&gt;&lt;span class="sh"&gt;f92C1&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;86&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;18 r&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;00&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;82B&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;10A&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;16&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;d8&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="sh"&gt;f2"
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/exe/
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;GOROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/usr/local/go'&lt;/span&gt; /usr/local/go/pkg/tool/linux_amd64/link &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/exe/a.out &lt;span class="nt"&gt;-importcfg&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/importcfg.link &lt;span class="nt"&gt;-X&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;runtime.godebugDefault&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;asynctimerchan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1,gotestjsonbuildtext&lt;span class="o"&gt;=&lt;/span&gt;1,gotypesalias&lt;span class="o"&gt;=&lt;/span&gt;0,httplaxcontentlength&lt;span class="o"&gt;=&lt;/span&gt;1,httpmuxgo121&lt;span class="o"&gt;=&lt;/span&gt;1,httpservecontentkeepheaders&lt;span class="o"&gt;=&lt;/span&gt;1,multipathtcp&lt;span class="o"&gt;=&lt;/span&gt;0,randseednop&lt;span class="o"&gt;=&lt;/span&gt;0,rsa1024min&lt;span class="o"&gt;=&lt;/span&gt;0,tls10server&lt;span class="o"&gt;=&lt;/span&gt;1,tls3des&lt;span class="o"&gt;=&lt;/span&gt;1,tlsmlkem&lt;span class="o"&gt;=&lt;/span&gt;0,tlsrsakex&lt;span class="o"&gt;=&lt;/span&gt;1,tlsunsafeekm&lt;span class="o"&gt;=&lt;/span&gt;1,winreadlinkvolume&lt;span class="o"&gt;=&lt;/span&gt;0,winsymlink&lt;span class="o"&gt;=&lt;/span&gt;0,x509keypairleaf&lt;span class="o"&gt;=&lt;/span&gt;0,x509negativeserial&lt;span class="o"&gt;=&lt;/span&gt;1,x509rsacrt&lt;span class="o"&gt;=&lt;/span&gt;0,x509usepolicies&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nt"&gt;-buildmode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exe &lt;span class="nt"&gt;-buildid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;wvZLsb-w6x3yjmaurfAY/cR1ay72gpouW8Dj1wpHA/ipt4_u-REyDFqYjqF2h5/wvZLsb-w6x3yjmaurfAY &lt;span class="nt"&gt;-extld&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gcc &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/_pkg_.a
/usr/local/go/pkg/tool/linux_amd64/buildid &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/exe/a.out &lt;span class="c"&gt;# internal&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/exe/a.out 01_token_bucket_basic
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="nv"&gt;$WORK&lt;/span&gt;/b001/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 2: Package loading — reading the import graph
&lt;/h2&gt;

&lt;p&gt;Before a single line is compiled, Go needs to know &lt;em&gt;what&lt;/em&gt; it's compiling.&lt;/p&gt;

&lt;p&gt;It reads your &lt;code&gt;go.mod&lt;/code&gt; to establish the module root and dependency versions.&lt;/p&gt;

&lt;p&gt;Then it walks your imports recursively, building a directed acyclic graph of packages. &lt;/p&gt;

&lt;p&gt;Standard library package sources (&lt;code&gt;fmt&lt;/code&gt;, &lt;code&gt;os&lt;/code&gt;, &lt;code&gt;net/http&lt;/code&gt;) live in &lt;code&gt;$GOROOT/src&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Your own packages are resolved relative to the module root. &lt;/p&gt;

&lt;p&gt;Third-party packages come from the module cache at &lt;code&gt;$GOPATH/pkg/mod&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This graph is the foundation everything else depends on.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: The compilation pipeline
&lt;/h2&gt;

&lt;p&gt;This is where Go earns its reputation for speed. &lt;/p&gt;

&lt;p&gt;Each package in the import graph goes through this pipeline independently:&lt;/p&gt;

&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%2Fv8mu1axjg29gknvtx56p.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%2Fv8mu1axjg29gknvtx56p.png" alt="image" width="797" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lexer&lt;/strong&gt; → turns raw source characters into a flat stream of tokens (&lt;code&gt;func&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;(&lt;/code&gt;, &lt;code&gt;)&lt;/code&gt;, ...).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parser&lt;/strong&gt; → builds an Abstract Syntax Tree from those tokens. &lt;br&gt;
Go's parser is hand-written (not generated) and intentionally simple, the language grammar is small enough to fit in your head.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type checker&lt;/strong&gt; → walks the AST and verifies every expression is well-typed. &lt;br&gt;
This is also where Go resolves identifiers and builds its scope chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IR &amp;amp; middle-end optimisations&lt;/strong&gt; → the typed AST is converted into the compiler's intermediate representation (IR), and this is where the big high-level optimisations run: function &lt;strong&gt;inlining&lt;/strong&gt;, devirtualisation, and &lt;strong&gt;escape analysis&lt;/strong&gt; (which decides whether a variable lives on the stack or escapes to the heap).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSA&lt;/strong&gt; → the optimised IR is then lowered into Static Single Assignment form, a lower-level representation where the compiler runs passes like dead-code elimination and common-subexpression elimination, followed by the machine-specific lowering that prepares for codegen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codegen&lt;/strong&gt; → SSA is turned into native machine code, written out as a per-package object file and packed into a &lt;code&gt;.a&lt;/code&gt; archive that the linker later consumes.&lt;/p&gt;

&lt;p&gt;Two things make this fast:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Packages compile in parallel.&lt;/strong&gt; If &lt;code&gt;A&lt;/code&gt; imports &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt;, Go compiles &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; concurrently, then &lt;code&gt;A&lt;/code&gt; once they're done. 
On an 8-core machine this is real parallelism.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$GOCACHE.&lt;/strong&gt; Go caches compiled packages (on Linux, in &lt;code&gt;~/.cache/go/build&lt;/code&gt;; macOS uses &lt;code&gt;~/Library/Caches/go-build&lt;/code&gt;), keyed by a hash of the source + build flags. Change nothing? Every package is a cache hit. 
Only the packages you &lt;em&gt;touched&lt;/em&gt; recompile.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 4: The linker
&lt;/h2&gt;

&lt;p&gt;Once all &lt;code&gt;.a&lt;/code&gt; files exist, the linker combines them into a single self-contained binary. &lt;/p&gt;

&lt;p&gt;For &lt;code&gt;go run&lt;/code&gt;, this binary lands in a temporary work directory (something like &lt;code&gt;$TMPDIR/go-buildXXXXXXXX/&lt;/code&gt;) rather than your working directory, and is then exec'd.&lt;/p&gt;

&lt;p&gt;Go's linker includes the &lt;strong&gt;entire Go runtime&lt;/strong&gt; in every binary. &lt;/p&gt;

&lt;p&gt;There's no shared runtime DLL to worry about. &lt;/p&gt;

&lt;p&gt;This is why &lt;em&gt;pure-Go&lt;/em&gt; binaries are statically linked by default and why you can &lt;code&gt;scp&lt;/code&gt; one to any compatible machine and it just runs, no dependency installation step. (The caveat: programs that use cgo, or certain stdlib packages like &lt;code&gt;net&lt;/code&gt; and &lt;code&gt;os/user&lt;/code&gt; that can pull in the system C resolver, may link dynamically against libc unless you build with &lt;code&gt;CGO_ENABLED=0&lt;/code&gt;.)&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: The runtime initializes — before your code runs
&lt;/h2&gt;

&lt;p&gt;Here's the part most Go developers never think about. When the OS loads your binary, the &lt;em&gt;first&lt;/em&gt; thing that runs is not &lt;code&gt;main()&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;It's the Go runtime bootstrap, written in assembly (&lt;code&gt;rt0_amd64.s&lt;/code&gt; or equivalent).&lt;/p&gt;

&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%2F0tupsop5qf6hxulx8md9.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%2F0tupsop5qf6hxulx8md9.png" alt="image" width="800" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack and TLS setup&lt;/strong&gt; — the runtime allocates the initial goroutine stack (starts at 8KB, grows dynamically) and sets up thread-local storage so each OS thread knows which goroutine it's running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The M:P:G scheduler&lt;/strong&gt; — Go's concurrency model involves three abstractions. &lt;em&gt;G&lt;/em&gt; (goroutines) are lightweight green threads. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;M&lt;/em&gt; (machine) are OS threads that actually run goroutines. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;P&lt;/em&gt; (processor) is a logical processor with a run queue; there are &lt;code&gt;GOMAXPROCS&lt;/code&gt; of them. That defaults to the number of logical CPUs — though since &lt;strong&gt;Go 1.25&lt;/strong&gt;, on Linux, if the process runs under a cgroup CPU limit (as in most containers) that's lower than the core count, &lt;code&gt;GOMAXPROCS&lt;/code&gt; defaults to that limit instead, and the runtime re-checks it periodically. &lt;/p&gt;

&lt;p&gt;All this infrastructure spins up before &lt;code&gt;main()&lt;/code&gt; is reached.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Garbage collector&lt;/strong&gt; — the GC's data structures are initialized. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;init()&lt;/code&gt; functions&lt;/strong&gt; — every package can define &lt;code&gt;init()&lt;/code&gt; functions. &lt;/p&gt;

&lt;p&gt;The runtime calls them in dependency order: a package's &lt;code&gt;init()&lt;/code&gt; runs only after all of its imports' &lt;code&gt;init()&lt;/code&gt; functions have completed. &lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;main&lt;/code&gt; package's &lt;code&gt;init()&lt;/code&gt; is last.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Only then&lt;/em&gt; does the runtime call &lt;code&gt;main.main()&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6: &lt;code&gt;main()&lt;/code&gt; runs
&lt;/h2&gt;

&lt;p&gt;Your code finally executes, on the main goroutine. &lt;/p&gt;

&lt;p&gt;One subtle point: if &lt;code&gt;main()&lt;/code&gt; returns, the process exits — even if other goroutines are still running. &lt;/p&gt;

&lt;p&gt;The main goroutine is special; it doesn't go back to a pool.&lt;/p&gt;

&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%2Fed6ratvd5eb5bp0ep9ck.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%2Fed6ratvd5eb5bp0ep9ck.png" alt=" " width="360" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. &lt;/p&gt;

&lt;p&gt;git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.* &lt;/p&gt;

&lt;p&gt;Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use. &lt;/p&gt;

&lt;p&gt;⭐ Star it on GitHub: &lt;br&gt;
 &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HexmosTech" rel="noopener noreferrer"&gt;
        HexmosTech
      &lt;/a&gt; / &lt;a href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;
        git-lrc
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Free, Micro AI Code Reviews That Run on Commit
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;p&gt;| &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.da.md" rel="noopener noreferrer"&gt;🇩🇰 Dansk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.es.md" rel="noopener noreferrer"&gt;🇪🇸 Español&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fa.md" rel="noopener noreferrer"&gt;🇮🇷 Farsi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.fi.md" rel="noopener noreferrer"&gt;🇫🇮 Suomi&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ja.md" rel="noopener noreferrer"&gt;🇯🇵 日本語&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.nn.md" rel="noopener noreferrer"&gt;🇳🇴 Norsk&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.pt.md" rel="noopener noreferrer"&gt;🇵🇹 Português&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.ru.md" rel="noopener noreferrer"&gt;🇷🇺 Русский&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.sq.md" rel="noopener noreferrer"&gt;🇦🇱 Shqip&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.zh.md" rel="noopener noreferrer"&gt;🇨🇳 中文&lt;/a&gt; | &lt;a href="https://github.com/HexmosTech/git-lrc/readme/README.hi.md" rel="noopener noreferrer"&gt;🇮🇳 हिन्दी&lt;/a&gt; |&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;img width="60" alt="git-lrc logo" src="https://camo.githubusercontent.com/948c8f2d5cf41b48985cd364d48c3a2dc9bfbfd42eab3e0a9a1b3e61f5f17ce3/68747470733a2f2f6865786d6f732e636f6d2f66726565646576746f6f6c732f7075626c69632f6c725f6c6f676f2e737667"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;git-lrc&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Free, Micro AI Code Reviews That Run on Commit&lt;/h2&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.producthunt.com/products/git-lrc?embed=true&amp;amp;utm_source=badge-top-post-badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=badge-git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt" width="200" src="https://camo.githubusercontent.com/87bf2d4283c1e0aa99e254bd17fefb1c67c0c0d39300043a243a4aa633b6cecc/68747470733a2f2f6170692e70726f6475637468756e742e636f6d2f776964676574732f656d6265642d696d6167652f76312f746f702d706f73742d62616467652e7376673f706f73745f69643d31303739323632267468656d653d6c6967687426706572696f643d6461696c7926743d31373731373439313730383638"&gt;&lt;/a&gt;
&amp;nbsp;&lt;/p&gt;
&lt;br&gt;
&lt;a href="https://discord.gg/sGdnKwB3qq" rel="nofollow noopener noreferrer"&gt;
  &lt;img alt="Discord Community" src="https://camo.githubusercontent.com/b8f979318aaabc8dec512b9d4e6e2a12431fba3c8a3b8738e1a97a0722d4e4bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d436f6d6d756e6974792d3538363546323f6c6f676f3d646973636f7264266c6162656c436f6c6f723d7768697465"&gt;
&lt;/a&gt; &lt;a href="https://goreportcard.com/report/github.com/HexmosTech/git-lrc" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Go Report Card" src="https://camo.githubusercontent.com/e74c0651c3ee9165a2ed01cb0f6842c494029960df30eb9c24cf622d3d21bf46/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f4865786d6f73546563682f6769742d6c7263"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml" rel="noopener noreferrer"&gt;&lt;img alt="gitleaks.yml" title="gitleaks.yml: Secret scanning workflow" src="https://github.com/HexmosTech/git-lrc/actions/workflows/gitleaks.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml" rel="noopener noreferrer"&gt;&lt;img alt="osv-scanner.yml" title="osv-scanner.yml: Dependency vulnerability scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/osv-scanner.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml" rel="noopener noreferrer"&gt;&lt;img alt="govulncheck.yml" title="govulncheck.yml: Go vulnerability check" src="https://github.com/HexmosTech/git-lrc/actions/workflows/govulncheck.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml" rel="noopener noreferrer"&gt;&lt;img alt="semgrep.yml" title="semgrep.yml: Static analysis security scan" src="https://github.com/HexmosTech/git-lrc/actions/workflows/semgrep.yml/badge.svg"&gt;&lt;/a&gt;&amp;nbsp;&lt;a rel="noopener noreferrer" href="https://github.com/HexmosTech/git-lrc/./gfx/dependabot-enabled.svg"&gt;&lt;img alt="dependabot-enabled" title="dependabot-enabled: Automated dependency updates are enabled" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FHexmosTech%2Fgit-lrc%2FHEAD%2F.%2Fgfx%2Fdependabot-enabled.svg"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;

&lt;p&gt;AI agents write code fast. They also &lt;em&gt;silently remove logic&lt;/em&gt;, change behavior, and introduce bugs -- without telling you. You often find out in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;git-lrc&lt;/code&gt; fixes this.&lt;/strong&gt; It hooks into &lt;code&gt;git commit&lt;/code&gt; and reviews every diff &lt;em&gt;before&lt;/em&gt; it lands. 60-second setup. Completely free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See It In Action&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;See git-lrc catch serious security issues such as leaked credentials, expensive cloud
operations, and sensitive material in log statements&lt;/p&gt;
&lt;/blockquote&gt;

  
    
    &lt;span class="m-1"&gt;git-lrc-intro-60s.mp4&lt;/span&gt;
    
  

  

  


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;AI agents silently break things.&lt;/strong&gt; Code removed. Logic changed. Edge cases gone. You won't notice until production.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Catch it before it ships.&lt;/strong&gt; AI-powered inline comments show you &lt;em&gt;exactly&lt;/em&gt; what changed and what looks wrong.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HexmosTech/git-lrc" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>go</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
