The articles cover several parts of modern engineering stacks, including how Go programs run and how newer AI techniques and tools aim to improve performance, controllability, and reliability. One piece explains the flow behind a command like `go run main.go`: the `go` tool dispatches to compilation tools, builds an import graph, compiles packages through lexer/parser/type checking/IR optimizations/SSA/codegen, links resulting objects into a binary, then runs Go runtime initialization (stack/TLS, the scheduler, GC, package `init` functions) before `main`. Another set of posts focuses on LLM inference and control. Speculative decoding is described as using a smaller draft model to propose multiple tokens and a larger model to verify them, reducing latency while keeping the large model as the source of truth. Steering vectors are described as adding a learned activation-direction at inference time to nudge behaviors like careful reasoning or security awareness without retraining. Additional posts describe practical AI-development infrastructure: Genkit for structuring production workflows (tools, observability, evaluation, schemas), and the Chrome Prompt API with on-device Gemini Nano, including streaming, context-window behavior, and chunking/RAG experiments. Finally, several posts discuss deployment and developer tooling patterns for cross-platform automation and Go testing/mocking.
What happens in Go builds, and how speculative decoding, steering, and tooling affect AI systems
The articles cover several parts of modern engineering stacks, including how Go programs run and how newer AI techniques and tools aim to improve performance, controllability, and reliability. One pie...
- `go run main.go` uses the `go` tool as an orchestration driver: it builds packages, links a temporary binary, then executes it while the Go runtime initializes before `main`.
- Speculative decoding speeds up LLM generation by having a small model draft multiple tokens and a large model verify them; the large model still determines the final output distribution.
- Steering vectors propose changing LLM behavior at inference by adding a learned direction in activation space, without retraining the model.
- Genkit is presented as a framework for production-ready AI apps in Go, emphasizing workflows, structured outputs, tool calling, observability, and evaluation.
- Chrome’s Prompt API enables on-device Gemini Nano sessions with availability checks, streaming responses, context-window tracking/overflow events, and constraints like JSON schema output.
Hello, I'm Shrijith Venkatramana. I'm building git-lrc, an AI code reviewer that runs on every commit. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product. Large Language Models keep getting smarter. But there's a problem: users don't experience intelligence directly. They experience latency. If a model takes 30 seconds to write an answer instead of 3 seconds, most users won't care that it scored higher on some benchmark. This creates an interesting engineering challenge: How do we make LLMs generate text faster without making them worse? One of the most important techniques to emerge in recent years is speculative decoding. The idea sounds almost absurd at first: What if a small model could guess what a large model is about to say, and the large model simply verifies those guesses? Surprisingly, that's exactly what happens. Let's see how it works. The Fundamental Bottleneck of LLM Inference To understand speculative decoding, we first need to understand why LLMs are slow. Imagine a model is generating: The capital of France is Paris. The model doesn't generate the entire sentence at once. Instead it generates one token at a time: The The capital The capital of The capital of France ... Each new token requires another forward pass through the model. For a large model with hundreds of billions of parameters, every token is expensive. This means generation is inherently sequential: Token 1 → Token 2 → Token 3 → Token 4 You can't generate token 4 until you know token 3. This sequential nature becomes one of the biggest sources of inference latency. The Intuition: Let a Smaller Model Predict Ahead Suppose you have: A large model (expensive) A small model (cheap) The small model is usually less accurate. But it's often correct about obvious next tokens. For example: Prompt: The capital of France is Small model prediction: Paris Large model prediction: Paris Both agree. Now imagine the small model predicts several tokens: Paris, which is Instead of asking the large model for each token individually, we ask it to verify the entire sequence in one pass. If the predictions are correct, we've effectively skipped multiple expensive decoding steps. This is the core idea behind speculative decoding. A Simple Example Let's say our draft model predicts: The weather today is sunny and warm. Tokenized: sunny and warm . The large model then evaluates these proposed tokens. Possible outcome: Token Draft Model Large Model sunny ✓ ✓ and ✓ ✓ warm ✓ ✓ . ✓ ✓ Everything matches. The large model accepts all four tokens. Instead of generating four separate tokens sequentially, we've effectively generated four tokens in a single verification step. That's a major latency reduction. What Happens When They Disagree? This is where the algorithm becomes interesting. Suppose the draft model predicts: The weather today is rainy and cold. The large model evaluates the proposal. rainy ✓ and ✓ cold ✗ The large model agrees until "cold". At that point: Accepted tokens are kept. Incorrect tokens are discarded. Generation resumes from the first disagreement. Result: The weather today is rainy and pleasant. Only part of the speculation was useful. But even partial acceptance can significantly improve throughput. Why This Doesn't Change Model Quality A common misconception is: "Aren't we replacing the big model with a smaller model?" No. The large model remains the source of truth. The draft model merely proposes candidates. The verification process guarantees that the final output follows the same probability distribution as standard decoding. Conceptually: Normal Decoding --------------- Large Model → Token Speculative Decoding -------------------- Small Model → Proposed Tokens Large Model → Verify Tokens Accepted Tokens → Output The final answer is still determined by the large model. The user gets the same quality, but faster. A Simplified Algorithm At a high level: while not finished: proposed = small_model.generate(k_tokens) verification = large_model.evaluate(proposed) accepted = longest_matching_prefix( proposed, verification ) output.extend(accepted) if mismatch: output.append( large_model.next_token() ) In practice, the real algorithm is more sophisticated because it must preserve exact sampling behavior. But this captures the overall workflow. Why It Works So Well Speculative decoding exploits an observation about language: Most tokens are predictable. Consider: Once upon a Most models will predict: time Similarly: Thank you for your Likely: help Large models spend a surprising amount of compute confirming obvious continuations. A smaller model can often predict these easy regions accurately. The large model only needs to intervene when things become ambiguous. This creates a useful division of labor: Component Job Small Model Predict likely tokens Large Model Verify and correct User Receives faster output Modern Variants Research and production systems have extended the original idea in several directions. Self-Speculative Decoding Instead of using two separate models: Early layers generate drafts Full model verifies This avoids maintaining a second model entirely. Multi-Token Prediction Some architectures are trained to predict multiple future tokens directly. Instead of: Predict token N+1 They predict: N+1 N+2 N+3 ... This increases opportunities for speculative execution. Tree-Based Speculation Rather than proposing a single sequence: A → B → C The draft model proposes multiple branches: B1 / A -- \ B2 The verifier can then select among several possible continuations. These approaches push throughput even further. Where You'll Encounter It Many developers use speculative decoding without realizing it. Modern inference systems frequently employ variants of: Server-side LLM inference platforms High-throughput API providers Optimized open-source inference engines Enterprise deployment stacks Whenever you see a large model streaming unusually quickly, there's a decent chance some form of speculative execution is happening behind the scenes. It's becoming one of the standard techniques for making frontier models economically viable at scale. Final Thoughts Speculative decoding is a beautiful example of an engineering idea that sounds counterintuitive but turns out to be remarkably effective. Instead of trying to make large models inherently faster, it asks a different question: What if most of the work they're doing is already predictable? By letting a smaller model make educated guesses and allowing the larger model to verify them, we can reduce latency dramatically while preserving output quality. As LLM deployment scales to millions of users and billions of generated tokens, techniques like speculative decoding are likely to matter just as much as advances in model architecture itself. Question: If you were deploying a large LLM in production, would you prefer investing in a better model, a faster model, or inference optimizations like speculative decoding? Why? *AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.* Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use. HexmosTech / git-lrc Free, Micro AI Code Reviews That Run on Commit | 🇩🇰 Dansk | 🇪🇸 Español | 🇮🇷 Farsi | 🇫🇮 Suomi | 🇯🇵 日本語 | 🇳🇴 Norsk | 🇵🇹 Português | 🇷🇺 Русский | 🇦🇱 Shqip | 🇨🇳 中文 | 🇮🇳 हिन्दी | git-lrc Free, Micro AI Code Reviews That Run on Commit AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free. See It In Action See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements git-lrc-intro-60s.mp4 Why 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production. 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong. … View on GitHub
6 hours agoHello, I'm Shrijith Venkatramana. I'm building git-lrc, an AI code reviewer that runs on every commit. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product. A few years ago, choosing a Go mocking framework was mostly a matter of personal preference. Today, things are different. Most Go developers have at least one AI coding assistant generating tests alongside them. Some teams even generate the majority of their unit tests automatically. Yet one area remains surprisingly messy: mocks. Ask an LLM to write a test for the same interface and you'll often get completely different results depending on whether your project uses GoMock, Mockery, MockIO, Minimock, Moq, or hand-written test doubles. The problem isn't that the models are bad. The problem is that mocking libraries represent very different philosophies: Strict vs flexible Generated vs runtime-created DSL-heavy vs idiomatic Go Feature-rich vs minimalist In this article we'll compare the most popular Go mocking libraries in 2026, examine their strengths and weaknesses, and discuss which one may be the best fit for your project. What Makes a Good Mocking Library? Before comparing tools, it's worth defining what matters. A good mocking library should ideally provide: Easy mock generation Clear test failures Minimal boilerplate Strong refactoring support Good IDE experience Readable tests Reliable call verification Different libraries optimize for different parts of this list. That's why there is no universally correct answer. 1. GoMock: The Enterprise Workhorse GoMock remains one of the most widely used mocking frameworks in the Go ecosystem. Originally created by Google and now actively maintained by Uber, it has become the standard choice for many large organizations. Its philosophy is straightforward: define expectations explicitly and verify them rigorously. Example func TestUserService(t *testing.T) { ctrl := gomock.NewController(t) repo := NewMockUserRepository(ctrl) repo.EXPECT(). GetUser(gomock.Any(), "123"). Return("John", nil) result, _ := service.GetUser("123") assert.Equal(t, "John", result) } What It Does Well Excellent matcher support Strong verification guarantees Call ordering support Mature ecosystem Well understood across large teams Drawbacks Requires code generation Can become verbose DSL feels heavy in simple tests Generated files add maintenance overhead Best Fit Large codebases where consistency and strictness matter more than simplicity. 2. Testify + Mockery: The Safe Default If you started a new Go project today and asked ten developers which mocking stack to use, this would probably be the most common answer. Testify provides assertions and mocking support while Mockery generates mocks from interfaces. The combination has become the default choice for many teams. Example func TestUserService(t *testing.T) { repo := mocks.NewUserRepository(t) repo.EXPECT(). GetUser(mock.Anything, "123"). Return("John", nil). Once() result, _ := service.GetUser("123") assert.Equal(t, "John", result) } What It Does Well Familiar API Large community Excellent assertion integration Good balance between flexibility and verification Easy onboarding for new developers Drawbacks Less strict than GoMock Generated mocks can grow large Expectations are easier to misconfigure Best Fit Most application teams. If you're unsure what to choose, this is usually the safest answer. 3. MockIO: The Most Interesting Newcomer MockIO takes a different approach. Unlike traditional Go mocking frameworks, it supports runtime-created mocks and offers a modern matcher system inspired by frameworks from other languages. For developers tired of constantly regenerating mocks, this is immediately appealing. Example func TestUserService(t *testing.T) { ctrl := mock.NewMockController( t, mockopts.StrictVerify(), ) repo := mock.Mock[UserRepository](ctrl) mock.WhenDouble( repo.GetUser( mock.AnyContext(), mock.Equal("123"), ), ).ThenReturn("John", nil) result, _ := service.GetUser("123") assert.Equal(t, "John", result) } What It Does Well Runtime mocks Rich matcher support Powerful argument capture Less dependency on generated code Modern API design Drawbacks Smaller ecosystem Depends on compiler internals and unsafe features Less proven in very large codebases Best Fit Developers looking for a modern alternative to traditional code-generation workflows. 4. Minimock: Fast and Strict Minimock focuses on simplicity and performance. It generates lightweight mocks and automatically verifies expectations when tests finish. The result is a relatively small API surface with strong guarantees. Example func TestUserService(t *testing.T) { ctrl := minimock.NewController(t) repo := NewUserRepositoryMock(ctrl) repo.GetUserMock. When(minimock.AnyContext, "123"). Then("John", nil) result, _ := service.GetUser("123") assert.Equal(t, "John", result) } What It Does Well Fast execution Strict verification Clean generated code Automatic cleanup integration Drawbacks Smaller community Fewer advanced capabilities Less flexibility than GoMock Best Fit Teams that value strict tests and fast feedback cycles. 5. Moq: The Go-Like Option Moq has a philosophy that many Go developers appreciate: Don't build a framework if ordinary Go code can do the job. Instead of constructing a large expectation DSL, Moq generates structs whose behavior is implemented through functions. Example func TestUserService(t *testing.T) { repo := UserRepositoryMock{ GetUserFunc: func( ctx context.Context, id string, ) (string, error) { return "John", nil }, } result, _ := service.GetUser("123") assert.Equal(t, "John", result) } What It Does Well Extremely simple Minimal abstraction Highly readable tests Easy to debug Feels like ordinary Go Drawbacks Limited matcher support Manual verification is sometimes necessary Less suitable for highly complex interaction testing Best Fit Developers who prefer explicit code over frameworks. The Bigger Trend: Fewer Mocks, More Fakes One of the most interesting testing trends in 2026 is that many experienced Go teams are using fewer mocks than they did a few years ago. Instead of mocking every dependency, they're increasingly creating lightweight in-memory implementations. For example: type FakeUserRepo struct { users map[string]User } func (r *FakeUserRepo) GetUser( ctx context.Context, id string, ) (User, error) { return r.users[id], nil } Compared to mocks, fakes often provide: Better readability More realistic behavior Easier maintenance Reduced brittleness Better AI-generated tests Mocks remain valuable for external boundaries: Payment providers Email services Message queues LLM providers Third-party APIs But many teams no longer mock every interface by default. Which One Should You Choose? If you're starting a new project today: Choose GoMock if You want maximum verification and are working in a large organization. Choose Testify + Mockery if You want the safest and most widely adopted option. Choose MockIO if You want modern runtime mocking and fewer code-generation steps. Choose Minimock if You prioritize speed and strictness. Choose Moq if You believe tests should look as much like ordinary Go as possible. Final Thoughts The most important shift in Go testing isn't a new mocking framework. It's that maintainability has become more important than capability. In 2026, every major mocking library can mock interfaces effectively. The real differentiator is what your tests look like six months later when someone else has to understand them. The best mocking framework is rarely the one with the longest feature list. It's the one your team can read, trust, and maintain. And increasingly, it's the one that both humans and AI assistants can work with comfortably. What does your team use today: a mocking framework, hand-written fakes, or a mix of both? Have your testing practices changed since AI coding assistants became part of your workflow? *AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.* Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use. HexmosTech / git-lrc Free, Micro AI Code Reviews That Run on Commit | 🇩🇰 Dansk | 🇪🇸 Español | 🇮🇷 Farsi | 🇫🇮 Suomi | 🇯🇵 日本語 | 🇳🇴 Norsk | 🇵🇹 Português | 🇷🇺 Русский | 🇦🇱 Shqip | 🇨🇳 中文 | 🇮🇳 हिन्दी | git-lrc Free, Micro AI Code Reviews That Run on Commit AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free. See It In Action See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements git-lrc-intro-60s.mp4 Why 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production. 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong. … View on GitHub
1 day agoHello, I'm Shrijith Venkatramana. I'm building git-lrc, an AI code reviewer that runs on every commit. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product. Large Language Models have made it surprisingly easy to generate text. Building a reliable AI application, however, is a completely different problem. Once you move beyond a simple "send prompt, get response" demo, you quickly encounter real-world concerns: Prompt management Structured outputs Multi-step workflows Tool calling Observability Evaluation Model switching Production debugging Many teams end up creating custom frameworks around OpenAI, Anthropic, Gemini, or local models just to manage these concerns. This is where Genkit comes in. Originally developed by Google, Genkit provides a framework for building AI-powered applications with a focus on workflows, tooling, observability, evaluation, and production readiness. While most examples online focus on Node.js, Genkit now has growing support for Go, making it an interesting option for backend engineers who want AI capabilities without introducing an entirely separate application stack. In this article we'll build practical examples and explore how Genkit helps structure real-world AI systems. Why Genkit Exists Most AI applications evolve like this: Phase 1: response := callLLM(prompt) Everything seems simple. Phase 2: You need: Retry logic Prompt versioning JSON outputs Tool integrations Tracing Metrics Human review workflows Now your codebase starts accumulating AI-specific infrastructure. Genkit attempts to provide these building blocks from day one. Think of it as: "Spring Boot for AI workflows" rather than "an LLM SDK." Installing Genkit for Go Create a new project: mkdir genkit-demo cd genkit-demo go mod init github.com/example/genkit-demo Install Genkit: go get github.com/firebase/genkit/go/ai Depending on your provider, you'll also install provider plugins. For Gemini: go get github.com/firebase/genkit/go/plugins/googleai Your First AI Call Let's start with a simple generation. package main import ( "context" "fmt" "github.com/firebase/genkit/go/ai" "github.com/firebase/genkit/go/genkit" "github.com/firebase/genkit/go/plugins/googleai" ) func main() { ctx := context.Background() g, err := genkit.Init(ctx, genkit.WithPlugins( &googleai.GoogleAI{ APIKey: "YOUR_API_KEY", }, ), ) if err != nil { panic(err) } resp, err := g.Generate(ctx, ai.GenerateRequest{ Model: "googleai/gemini-2.5-flash", Prompt: "Explain vector databases in one paragraph.", }) if err != nil { panic(err) } fmt.Println(resp.Text()) } This resembles a normal LLM call, but Genkit's value becomes more apparent when applications grow beyond this stage. Structured Outputs: Stop Parsing AI Text One of the most common mistakes in AI systems is asking models to return text and then parsing it manually. Instead of: Name: John Score: 87 Risk: Medium Use schemas. Imagine a customer-support ticket classifier. type TicketClassification struct { Category string `json:"category"` Priority string `json:"priority"` Summary string `json:"summary"` } Prompt: Classify this support ticket. Return JSON matching the schema. Now downstream services can safely consume the result. Real-world uses: Lead qualification Risk analysis Invoice extraction Customer support routing Contract review Structured outputs dramatically reduce prompt fragility. Building Multi-Step AI Workflows Most production AI systems involve multiple steps. Example: Customer email arrives. Workflow: Summarize email Detect sentiment Extract action items Generate response draft Send for human review Without a framework: Controller ├─ LLM Call #1 ├─ LLM Call #2 ├─ LLM Call #3 └─ LLM Call #4 Logic becomes difficult to maintain. With Genkit, you can model the workflow as a flow. summaryFlow := genkit.DefineFlow( g, "summarizeCustomerEmail", func(ctx context.Context, email string) (string, error) { result, err := g.Generate(ctx, ai.GenerateRequest{ Model: "googleai/gemini-2.5-flash", Prompt: "Summarize:\n\n" + email, }) if err != nil { return "", err } return result.Text(), nil }, ) Flows become reusable application components rather than scattered LLM calls. Tool Calling: Let the Model Use Your Systems A common misconception is that AI models should know everything. In reality: Models should reason. Systems should provide facts. Imagine an order-tracking assistant. Instead of teaching the model about orders: Order #78291 Status: Shipped Carrier: FedEx ETA: Tomorrow Expose a tool. func GetOrderStatus(orderID string) string { return "Shipped" } The model decides: I need order information. Call tool. Read result. Answer user. This pattern enables: Database lookups CRM access Internal APIs Inventory systems Knowledge bases Many enterprise AI systems are essentially: LLM + Tools rather than LLM + More Prompting Observability: The Feature Most Teams Discover Too Late Suppose users report: "The AI gave a terrible answer." Without tracing, you're blind. Questions immediately arise: Which prompt was used? Which model answered? What context was supplied? Which tool calls executed? How much did it cost? Genkit includes observability capabilities that make debugging AI workflows significantly easier. Traditional debugging: Error at line 87 AI debugging: Prompt → Context → Tool Calls → Model Output → Final Result This is often the difference between a manageable production system and weeks of confusion. Real Example: AI-Powered Incident Summaries Imagine you're running a platform team. Every incident generates: Slack messages Alerts Logs Jira tickets Engineers spend time creating incident reports. A Genkit workflow could: Collect incident data Summarize timeline Identify root cause indicators Draft postmortem Suggest follow-up actions Pseudo-flow: Alerts ↓ Summarization ↓ Root Cause Analysis ↓ Draft Postmortem ↓ Engineer Review This is exactly the type of repeatable, multi-step process where Genkit shines. Model Portability Matters More Than Most Teams Expect Early-stage teams often assume they'll stay with one model forever. Reality: Pricing changes New models appear Performance shifts Compliance requirements emerge Today's choice: Gemini Six months later: Anthropic Twelve months later: Local model Frameworks that separate application logic from model providers reduce migration pain. Genkit encourages this separation. Your workflow logic remains relatively stable while models evolve underneath. Common Mistakes When Adopting Genkit 1. Treating It Like Another SDK Genkit is most valuable when you embrace workflows, tools, schemas, and evaluation. Using it only for text generation leaves much of its value unused. 2. Over-Automating Not every process should become autonomous. Many successful systems use: AI → Human Review → Action rather than AI → Action 3. Ignoring Evaluations A workflow that works today may degrade after: Prompt changes Model upgrades Data changes Evaluation should be treated as seriously as unit testing. Final Thoughts The AI ecosystem currently has no shortage of model providers. What many teams actually need is better infrastructure around those models. Genkit addresses a practical gap between simple API calls and production-grade AI systems. It provides a structured way to build workflows, integrate tools, monitor behavior, and evolve applications as models change. For Go developers, that's particularly valuable because it allows AI capabilities to live inside existing backend services rather than forcing a separate JavaScript stack. The interesting question is no longer: "Which model should I use?" It's increasingly: "How do I build a system that can survive five generations of models?" Frameworks like Genkit are one possible answer. If you were building an AI-powered product today, which capability would you invest in first: better models, better prompts, better tools, or better workflows? And more importantly, which of those do you think will still be a competitive advantage three years from now? *AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.* Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use. HexmosTech / git-lrc Free, Micro AI Code Reviews That Run on Commit | 🇩🇰 Dansk | 🇪🇸 Español | 🇮🇷 Farsi | 🇫🇮 Suomi | 🇯🇵 日本語 | 🇳🇴 Norsk | 🇵🇹 Português | 🇷🇺 Русский | 🇦🇱 Shqip | 🇨🇳 中文 | git-lrc Free, Micro AI Code Reviews That Run on Commit AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free. See It In Action See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements git-lrc-intro-60s.mp4 Why 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production. 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong. 🔁 Build a… View on GitHub
3 days agoHello, 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. Star git-lrc to help devs discover the project. Do give it a try and share your feedback. Two things I kept putting off. First: people on Windows asked if peektea runs on WSL. It does now. Second: "brew it from source" is a terrible install story for a tool that's supposed to be minimal. That's fixed too. Demo here in case above preview not showing up. WSL support WSL is Linux. peektea runs on Linux. So far, so good. The problem is o the key that opens files. On a normal Linux machine, pressing o on an image launches feh or eog. On WSL there are no Linux GUI apps. The call fails silently or prints an error. peektea now detects WSL at startup: func IsWSL() bool { if os.Getenv("WSL_DISTRO_NAME") != "" { return true } data, err := os.ReadFile("/proc/version") return err == nil && strings.Contains(strings.ToLower(string(data)), "microsoft") } When WSL is detected, file opens route through wslview (from wslu) if it's installed, otherwise fall back to explorer.exe: func WSLOpener() string { if _, err := exec.LookPath("wslview"); err == nil { return "wslview" } if _, err := exec.LookPath("explorer.exe"); err == nil { return "explorer.exe" } if _, err := os.Stat("/mnt/c/Windows/explorer.exe"); err == nil { return "/mnt/c/Windows/explorer.exe" } return "" } There's one more wrinkle: Windows programs can't read Linux paths like /home/taco/file.png. They need UNC paths like \\wsl.localhost\Ubuntu\home\taco\file.png. WSL ships wslpath for exactly this: func WindowsPath(path string) string { out, err := exec.Command("wslpath", "-w", path).Output() if err != nil { return path } return strings.TrimSpace(string(out)) } When the configured opener ends in .exe, the path gets converted before the command runs. wslview handles conversion itself so it doesn't need this, only raw explorer.exe does. lovestaco / peektea brewing a terminal file browser with Bubble Tea A minimal terminal file browser built with Bubble Tea. Peek through your filesystem with arrow keys (or vim keys), then pour each file straight into the app you've configured for it. Demo A quick peek before you steep: Install One-liner: curl -fsSL https://raw.githubusercontent.com/lovestaco/peektea/master/scripts/install.sh | sh Download a binary (no Go required) — grab the latest release for your platform from the releases page: Platform File Linux x86-64 peektea_linux_amd64.tar.gz Linux arm64 peektealinux_arm64.tar.gz macOS x86-64 peekteadarwin_amd64.tar.gz macOS Apple Silicon peektea_darwin_arm64.tar.gz Extract and put the peektea binary anywhere on your $PATH. Install with Go: go install github.com/lovestaco/peektea@latest Build from source: git clone https://github.com/lovestaco/peektea cd peektea make install make install puts the binary in ~/go/bin and figures out $PATH for you: Already reachable — done, nothing to do. ~/.local/bin is on your PATH — symlinks the binary there, works immediately in the current shell. Neither — appends ~/go/bin to your .bashrc… View on GitHub peektea init on WSL peektea init on a normal Linux machine asks you to pick a text editor, file manager, image viewer, and PDF viewer from what's installed. On WSL there usually aren't any Linux GUI apps. Asking you to pick between zero options isn't a great experience. So on WSL, init skips those categories and sets the Windows opener as the fallback instead of xdg-open. You still get the full text editor setup (vim, nvim, nano those work fine in WSL), and the Windows side handles everything visual. Demo here in case the above preview is not showing up. While at it, peektea init got smarter in general. If you decline the "already exists, overwrite?" prompt, it used to just exit. Now it keeps your config and continues to the chafa check, so you can re-run peektea init any time just to install extras without nuking your setup. And if chafa isn't installed, it doesn't just print the install command anymore. It offers to run it: ── 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]: It detects your package manager (apt, dnf, pacman, zypper, apk, brew) and runs the right command. Bare enter means yes. Installation The other thing that needed fixing: the only install method was cloning the repo and running make install. That requires Go, git, and knowing where ~/go/bin is. Too much friction for a tool that's supposed to just work. peektea now ships pre-built binaries for Linux and macOS (x86-64 and arm64) on every release. One-liner: curl -fsSL https://raw.githubusercontent.com/lovestaco/peektea/master/scripts/install.sh | sh The script detects your OS and architecture, pulls the right binary from the latest release, and installs it to ~/.local/bin or /usr/local/bin whichever is already on your PATH. With Go: go install github.com/lovestaco/peektea@latest peektea version now works correctly regardless of how you installed it. When installed via go install, the binary reads its own module version from debug.ReadBuildInfo(). When built with make install, the version comes from git describe via ldflags. Either way: peektea version # peektea v0.2.1 (linux/amd64) AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs — without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free. Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use. ⭐ Star it on GitHub: HexmosTech / git-lrc Free, Micro AI Code Reviews That Run on Commit | 🇩🇰 Dansk | 🇪🇸 Español | 🇮🇷 Farsi | 🇫🇮 Suomi | 🇯🇵 日本語 | 🇳🇴 Norsk | 🇵🇹 Português | 🇷🇺 Русский | 🇦🇱 Shqip | 🇨🇳 中文 | git-lrc Free, Micro AI Code Reviews That Run on Commit AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free. See It In Action See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements git-lrc-intro-60s.mp4 Why 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production. 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong. 🔁 Build a… View on GitHub
3 days agoHello, I'm Shrijith Venkatramana. I'm building git-lrc, an AI code reviewer that runs on every commit. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product. What if you could change how an AI thinks without retraining it? Not by rewriting prompts. Not by fine-tuning billions of parameters. Not by collecting another mountain of training data. Instead, imagine finding a direction inside the model's internal representation space and nudging the model a little in that direction. A small push. A different behavior. This idea sits at the heart of one of the most fascinating areas of modern AI interpretability: steering vectors. Steering vectors suggest that many behaviors we care about—careful reasoning, honesty, coding style, security awareness, verbosity, and more—may already exist inside a model. The challenge is learning how to activate them. Let's explore what steering vectors are, how they're created, and why they might become one of the most practical tools for controlling AI systems. 1. What Exactly Is a Steering Vector? Large language models process information through layers of high-dimensional activations. At any point during generation, the model's internal state can be represented as a vector containing thousands of numbers. Researchers discovered something surprising: Different behaviors often correspond to different regions of this activation space. For example: Writing Python code Solving math problems Speaking French Explaining concepts carefully Producing insecure code Each tends to produce distinctive activation patterns. A steering vector is essentially the difference between two activation patterns. Suppose we gather examples where the model is: Careful Methodical Thorough and compare them to examples where it is: Rushed Superficial Incomplete The average difference between these internal states becomes a steering vector. At inference time, we can add that vector back into the model's activations: new_activation = activation + α × steering_vector where α controls the steering strength. Conceptually, it's like moving the model's internal state toward a desired behavior. 2. Why Steering Vectors Matter Traditionally, changing model behavior meant: More training More data More compute More cost Steering vectors challenge that assumption. They suggest that many capabilities already exist inside the model and merely need to be activated. This has an important implication: The model may know more than it appears to know. The behavior is already present, but not always dominant. Instead of teaching the model something new, steering often means amplifying a latent behavior that already exists. This is one reason steering vectors have attracted significant attention from interpretability researchers. They provide a glimpse into how concepts may be organized internally. 3. The Most Useful Coding Applications For software engineering, steering vectors could be particularly valuable. Careful Code Review Imagine building a vector from examples of excellent code reviews versus weak reviews. When applied, the model might become more likely to: Identify edge cases Spot race conditions Notice missing validation Highlight maintainability concerns without changing the prompt itself. Security-Oriented Coding A vector could be constructed from secure versus insecure implementations. The model may become more likely to: Validate inputs Sanitize outputs Handle failures explicitly Avoid common vulnerabilities Better Refactoring Some code is technically correct but difficult to maintain. A refactoring-oriented steering vector could encourage: Clearer abstractions Better naming Simpler control flow Reduced complexity Thinking Before Coding Perhaps the most interesting possibility is steering toward analysis before implementation. Many coding assistants jump directly into code generation. A steering vector could encourage the model to spend more effort evaluating requirements, assumptions, and tradeoffs before writing the first line of code. 4. How Researchers Create Steering Vectors The simplest approach is surprisingly straightforward. First, collect two sets of examples. Positive Examples Examples that exhibit the target behavior. For example: High-quality code reviews Secure implementations Careful reasoning traces Negative Examples Examples lacking that behavior. For example: Superficial reviews Insecure implementations Rushed solutions Next: Run both datasets through the model. Capture activations from a chosen layer. Compute the average activation for each group. Subtract one average from the other. The resulting difference vector becomes the steering vector. Researchers often call this a contrastive activation difference. More advanced approaches use: Linear probes PCA Sparse Autoencoders (SAEs) Contrastive learning techniques to identify cleaner and more interpretable directions. 5. How Do You Evaluate a Steering Vector? Creating a steering vector is easy. Proving it works is much harder. A common mistake is assuming a behavior improved simply because the output changed. Researchers typically evaluate steering vectors by running controlled benchmarks. For example: Generate a set of coding tasks. Run the baseline model. Run the steered model. Compare measurable outcomes. Metrics might include: Bugs discovered Security issues identified Test coverage quality Correctness False positive rates Human review is equally important. Many steering vectors initially appear useful but primarily increase verbosity. Longer answers often look smarter, even when they aren't. A good evaluation distinguishes genuine capability improvements from stylistic changes. 6. Where Steering Vectors Are Heading Next The most exciting research is moving beyond single dense vectors. A common criticism of steering vectors is that they often blend multiple concepts together. A "careful reasoning" vector might simultaneously influence: Length Formality Confidence Attention to detail Recent interpretability work attempts to break these behaviors into smaller, more precise features. Instead of steering toward a broad concept like "good coding," future systems may activate specific internal features such as: Checking edge cases Searching for counterexamples Validating assumptions Looking for security risks The long-term vision is not merely controlling outputs. It is understanding and controlling the internal computations that generate those outputs. If successful, steering could become one of the most practical bridges between interpretability research and real-world AI systems. Final Thoughts Steering vectors reveal something profound about large language models. Many behaviors that appear mysterious from the outside may correspond to surprisingly simple geometric directions on the inside. We are still far from fully understanding these representations. But the idea that a model's behavior can be altered by moving through activation space—without retraining and sometimes without even changing the prompt—offers a fascinating glimpse into how intelligence may be organized inside neural networks. And perhaps more importantly, it suggests that the future of AI control might involve understanding the model's internal world rather than merely observing its outputs. Question: If you could build a steering vector for your coding assistant today, what behavior would you choose: deeper reasoning, stronger security awareness, better code reviews, more maintainable code, or something else entirely? *AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.* Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use. HexmosTech / git-lrc Free, Micro AI Code Reviews That Run on Commit | 🇩🇰 Dansk | 🇪🇸 Español | 🇮🇷 Farsi | 🇫🇮 Suomi | 🇯🇵 日本語 | 🇳🇴 Norsk | 🇵🇹 Português | 🇷🇺 Русский | 🇦🇱 Shqip | 🇨🇳 中文 | git-lrc Free, Micro AI Code Reviews That Run on Commit AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free. See It In Action See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements git-lrc-intro-60s.mp4 Why 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production. 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong. 🔁 Build a… View on GitHub
5 days agoHello, 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. Star git-lrc to help devs discover the project. Do give it a try and share your feedback for improving the project. What I actually want is an ncdu-style file browser fully keyboard-driven, where I can hop through directories and open files straight into Nautilus, vim, Nemo, whatever, even preview images right in the terminal. No mouse, no leaving the keyboard. But that's a big pot to brew. So I started small and used it as an excuse to learn Bubble Tea, Charmbracelet's Go TUI framework. The result is peektea: a minimal version that, for now, just browses. Run it, arrow your way through directories, pop back up to the parent. That's the whole cup of tea so far. ~140 lines of Go: the opening-files-and-previewing-images part is where it's headed next. So what's Bubble Tea? Bubble Tea is a Go framework for building terminal UIs, built on the Elm Architecture. Which is a fancy way of saying your entire app boils down to three things: Model — the state of your program Update — a function that takes events and returns a new model View — a function that renders the model to a string No mutation, no spilled state. Update and View are pure functions. The framework handles the event loop, terminal I/O, and all the redrawing so you don't have to. You just describe what things should look like and it does the dishes. The model type model struct { dir string entries []os.DirEntry cursor int err error } That's the entire state of peektea. The current directory, what's in it, where the cursor sits, and whether something went sideways. When you navigate into a new directory you don't mutate anything in place, Update hands back a fresh model with the new values. The update loop (where the tea gets stirred) Every keypress shows up as a tea.KeyMsg. You pattern-match on it and return the next model: func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "right", "l", "enter": if len(m.entries) > 0 && m.entries[m.cursor].IsDir() { next := filepath.Join(m.dir, m.entries[m.cursor].Name()) entries, err := os.ReadDir(next) if err == nil { m.dir = next m.entries = entries m.cursor = 0 } } // ... } } return m, nil } That second return value, tea.Cmd, is a function that runs asynchronously and produces the next message. Here Update is fully synchronous, so we just return nil. But the moment you want to fetch data or read files in the background, Cmd is how you do it without blocking the UI. Think of it as putting the kettle on and getting pinged when it's ready, instead of standing there watching it. 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. It's just a little loop over the entries to find the matching name but it makes navigation feel natural instead of jarring. The view Rendering is a pure string transformation. Bubble Tea calls View() after every Update and redraws the terminal for you. Styling comes from Lipgloss, also from Charmbracelet (they really committed to the tea house aesthetic). You define styles once at the package level: var ( cursorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("212")).Bold(true) dirStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("39")) fileStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("252")) ) Then call .Render(s) on them anywhere in your view. Directories get a trailing / and a cyan tint, the cursor row gets a background highlight, and the selected entry gets a ▶ so you always know where you are. Wiring it up func main() { dir, _ := os.Getwd() p := tea.NewProgram(newModel(dir), tea.WithAltScreen()) p.Run() } The one line worth highlighting is tea.WithAltScreen(). It flips the terminal into the alternate screen buffer — the same trick vim and htop use. Your TUI takes over the whole terminal, and when you quit, your shell session comes back clean like nothing happened. Without it, your UI just dumps into the scrollback like any other output. Nobody wants tea stains on their terminal history. What I'd steep next This is where the ncdu-style dream actually starts brewing: Open files in your editor/app — enter on a file shells out to vim, or hands it to Nautilus/Nemo/xdg-open based on type Image previews in the terminal — render images inline via Kitty/iTerm protocols or chafa File previews — split the screen, show the selected file's content on the right Filtering — type to narrow the list (Bubble Tea ships a textinput in bubbles) Hidden file toggle — h to show/hide dotfiles All of it stays keyboard-driven no reaching for the mouse. As they land, they'll be in the repo. The nice thing is the framework makes each one refreshingly easy: you extend the model and handle new keys in Update. That's the whole pattern. AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.* Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use. ⭐ Star it on GitHub: HexmosTech / git-lrc Free, Micro AI Code Reviews That Run on Commit | 🇩🇰 Dansk | 🇪🇸 Español | 🇮🇷 Farsi | 🇫🇮 Suomi | 🇯🇵 日本語 | 🇳🇴 Norsk | 🇵🇹 Português | 🇷🇺 Русский | 🇦🇱 Shqip | 🇨🇳 中文 | git-lrc Free, Micro AI Code Reviews That Run on Commit AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production. git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free. See It In Action See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements git-lrc-intro-60s.mp4 Why 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production. 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong. 🔁 Build a… View on GitHub
1 week ago
TechRadar publishes daily Quordle hints and answers for multiple dates
TechRadar runs a series of daily posts providing help for the word game Quordle, including hints and the solution for sp...
NYT Connections and Strands puzzles: hints and answers published across multiple outlets
Several outlets publish daily walkthroughs for The New York Times puzzle games, including NYT Connections and NYT Strand...
NYT Strands daily guides provide hints, clues, and answers for multiple dates
Multiple outlets publish daily coverage for the New York Times word game “Strands,” offering players guidance to solve e...