<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Engineering on @zhisme :: signal over noise</title><link>https://zhisme.com/categories/engineering/</link><description>Recent content in Engineering on @zhisme :: signal over noise</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Wed, 10 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://zhisme.com/categories/engineering/index.xml" rel="self" type="application/rss+xml"/><item><title>The Constant Frozen at Boot Bug: A Ruby Exercise For An Interview</title><link>https://zhisme.com/articles/ruby-constant-frozen-at-boot/</link><pubDate>Wed, 10 Jun 2026 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/ruby-constant-frozen-at-boot/</guid><description>&lt;p>I like interview questions that come from real incidents instead of a puzzle book. You can&amp;rsquo;t google your way out of them, and the candidate&amp;rsquo;s reasoning maps directly onto the job. This one came from a payment service. It looks trivial. It is not.&lt;/p>
&lt;p>I&amp;rsquo;ve stripped the production code and rebuilt the same shape around a fake payment router. The bug is identical; the names are not.&lt;/p>
&lt;h2 id="the-question">The Question&lt;/h2>
&lt;blockquote>
&lt;p>Here is a class that routes payments to a gateway. Occasionally a charge is&lt;br>
written to the database with &lt;code>method_id = NULL&lt;/code>, even though the payment method&lt;br>
clearly exists in the &lt;code>payment_methods&lt;/code> table. No exception is raised. The only&lt;br>
thing that reliably fixes it is restarting the process. Find the bug.&lt;/p></description></item><item><title>Give Your LLM Brevity</title><link>https://zhisme.com/articles/give-your-llm-brevity/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/give-your-llm-brevity/</guid><description>&lt;blockquote>
 &lt;div class="blockquote-text">
 
Brevity is the Sister of Talent

 &lt;/div>
 &lt;div class="blockquote-author">
 &lt;div class="blockquote-author__pic">
 
 
 &lt;picture>
 &lt;source srcset="https://zhisme.com/articles/give-your-llm-brevity/chekhov.jpg">
 &lt;img src="https://zhisme.com/articles/give-your-llm-brevity/chekhov.jpg" alt="A.P. Chekhov">
 &lt;/picture>
 
 
 &lt;/div>
 &lt;div class="blockquote-author__content">
 &lt;div class="blockquote-author__name">A.P. Chekhov&lt;/div>
 &lt;div class="blockquote-author__position">&lt;/div>
 &lt;/div>
 &lt;/div>
&lt;/blockquote>

&lt;h2 id="why">Why?!&lt;/h2>
&lt;p>I don&amp;rsquo;t want to read invented machinery poems from an LLM about why it chose &lt;code>BigDecimal(0.5)&lt;/code> instead of a literal &lt;code>0.5&lt;/code> and writes 3 paragraphs defending a choice I didn&amp;rsquo;t ask about.&lt;br>
I don&amp;rsquo;t want to read invented nonsense that I have no time for.&lt;br>
If I don&amp;rsquo;t like something, I&amp;rsquo;ll ask to reimplement/refactor, or in rare cases request elaboration.&lt;br>
Then I will cover it with the needed tests until it satisfies me.&lt;br>
If you&amp;rsquo;re like me, you don&amp;rsquo;t want to spend time on that.&lt;/p></description></item><item><title>Multiple Git Configs Per Directory</title><link>https://zhisme.com/articles/multiple-git-configs-per-directory/</link><pubDate>Mon, 30 Mar 2026 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/multiple-git-configs-per-directory/</guid><description>&lt;h2 id="the-problem">The Problem&lt;/h2>
&lt;p>You have a personal GitHub and a work GitLab (or multiple work accounts). Your global &lt;code>~/.gitconfig&lt;/code> has your personal email. You clone a work repo, make a commit, push — and now your personal email is in the company git history. haha-haha classic..&lt;/p>
&lt;p>You could run &lt;code>git config user.email&lt;/code> in every new repo you clone. But you&amp;rsquo;ll forget. You always forget. But this is a boring routine, why do this?&lt;/p></description></item><item><title>Practical Useful Commands for Claude</title><link>https://zhisme.com/articles/practical-useful-commands-for-claude/</link><pubDate>Tue, 17 Mar 2026 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/practical-useful-commands-for-claude/</guid><description>&lt;p>These are commands I use often and see a lot of value from. I advise you at least to consider using them in case you haven&amp;rsquo;t tried them yet.&lt;/p>
&lt;h2 id="commands">Commands&lt;/h2>
&lt;ol>
&lt;li>&lt;code>claude --worktree&lt;/code> or &lt;code>claude -w&lt;/code>&lt;/li>
&lt;/ol>
&lt;p>In case you want multiple agents to run simultaneously, this option was designed for it. Each Claude agent gets its own version of the repo so they won&amp;rsquo;t interfere with each other. Where can you use it? Let&amp;rsquo;s say you&amp;rsquo;re migrating something to a new architecture and there are multiple services that need changes, but they&amp;rsquo;re located in a monorepo. With this option, each agent will be moving its own service or &amp;ldquo;folder&amp;rdquo; if you want, without getting conflicts with others.&lt;/p></description></item><item><title>Disable Co-Authored-By Claude in Git Commits</title><link>https://zhisme.com/articles/disable-co-authored-by-claude-in-git-commits/</link><pubDate>Fri, 27 Feb 2026 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/disable-co-authored-by-claude-in-git-commits/</guid><description>&lt;h2 id="solution">Solution&lt;/h2>
&lt;p>Open &lt;code>~/.claude/settings.json&lt;/code> with your favorite editor and add this to your json config. This is taken from Claude docs&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>&lt;/p>
&lt;pre>&lt;code class="language-json">{
 // ...
 &amp;quot;attribution&amp;quot;: {
 &amp;quot;commit&amp;quot;: &amp;quot;&amp;quot;,
 &amp;quot;pr&amp;quot;: &amp;quot;&amp;quot;
 }
}
&lt;/code>&lt;/pre>
&lt;h2 id="why">Why&lt;/h2>
&lt;p>This actually makes no sense and I agree with Rob Pike&amp;rsquo;s take on that&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>. It just adds non-readable boilerplate that does not add any value to the git commit. If it was committed by some guy I expect him to take responsibility of that commit, not some excuse like &amp;ldquo;that was written by Claude, sorry I didn&amp;rsquo;t check&amp;rdquo;. So it makes &lt;strong>no sense&lt;/strong> at all, we are blind to that string anyway. Git commits should be atomic, simple and readable, not overwhelmed by nonsense. The trick above will help you with that.&lt;/p></description></item><item><title>How to Set Up Browser MCP in Claude Code</title><link>https://zhisme.com/articles/setup-browser-mcp-claude/</link><pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/setup-browser-mcp-claude/</guid><description>&lt;h2 id="how-to-set-up-mcp-for-browser">How to set up MCP for browser&lt;/h2>
&lt;ol>
&lt;li>Create &lt;code>.mcp.json&lt;/code> in your project directory with the following content:&lt;/li>
&lt;/ol>
&lt;pre>&lt;code class="language-json">{
 &amp;quot;mcpServers&amp;quot;: {
 &amp;quot;chrome-devtools&amp;quot;: {
 &amp;quot;command&amp;quot;: &amp;quot;npx&amp;quot;,
 &amp;quot;args&amp;quot;: [&amp;quot;-y&amp;quot;, &amp;quot;chrome-devtools-mcp@latest&amp;quot;]
 }
 }
}
&lt;/code>&lt;/pre>
&lt;ol start="2">
&lt;li>Then run the following command in your terminal:&lt;/li>
&lt;/ol>
&lt;pre>&lt;code class="language-sh">claude mcp add chrome-devtools --scope user npx chrome-devtools-mcp@latest
&lt;/code>&lt;/pre>
&lt;ol start="3">
&lt;li>Then in Claude Code, run &lt;code>/mcp&lt;/code> to verify the connection:&lt;/li>
&lt;/ol>
&lt;pre>&lt;code class="language-sh"># start claude code cli
claude
# run /mcp inside cli
/mcp
─────────────────────────────────────────────────────────────────────────────────
 Manage MCP servers
 2 servers

 Project MCPs (/Users/zhisme/projects/my-project/.mcp.json)
 ❯ chrome-devtools · ✔ connected
&lt;/code>&lt;/pre>
&lt;ol start="4">
&lt;li>Afterwards, run a sample command to verify that the browser MCP can start:&lt;/li>
&lt;/ol>
&lt;pre>&lt;code class="language-sh"> ▐▛███▜▌ Claude Code v2.1.17
▝▜█████▛▘ Opus 4.5 · Claude Max
 ▘▘ ▝▝ ~/dev/projects/new-magtuner/mt-editor

❯ open with browser mcp url google.com

⏺ chrome-devtools - navigate_page (MCP)(type: &amp;quot;url&amp;quot;, url:
 &amp;quot;https://www.google.com&amp;quot;)
 ⎿  # navigate_page response
 Successfully navigated to https://www.google.com.
 ## Pages
 1: https://www.google.com/ [selected]

⏺ Opened google.com in the browser. The page is loaded and selected.
&lt;/code>&lt;/pre>
&lt;p>If you see a Google Chrome for Testing window like in the screenshot below, then everything is set up correctly. You can now tell Claude to visually verify your rendered pages.&lt;br>
&lt;figure>&lt;img src="https://zhisme.com/articles/setup-browser-mcp-claude/browsermcp.png"
 alt="Google chrome via browser mcp">&lt;figcaption>
 &lt;p>Google chrome via browser mcp&lt;/p></description></item><item><title>Ruby IO buffering</title><link>https://zhisme.com/articles/ruby-io-buffering/</link><pubDate>Fri, 16 Jan 2026 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/ruby-io-buffering/</guid><description>&lt;p>Your Kibana/Cloudwatch/Grafana have different timestamps, you don&amp;rsquo;t see recent logs from your application. Why is that? You may ask. Some QA reports that your application is not working/was not deployed, asking you to review the deploy process. Or even worse: asking your devops colleagues to &amp;ldquo;something went wrong&amp;rdquo; with last deployment could you check?&lt;/p>
&lt;p>You login into your shell running &lt;code>kubectl get pods&lt;/code> to verify timestamps update or checking Helm releases &lt;code>helm ls&lt;/code>. But everything seems fine, everything deployed. CI/CD is green, all timestamps updated. But yet. QA does not see the logs. Where have they gone?&lt;/p></description></item><item><title>copy_with_context.nvim v3 Released</title><link>https://zhisme.com/articles/copy-with-context-v3-released/</link><pubDate>Mon, 24 Nov 2025 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/copy-with-context-v3-released/</guid><description>&lt;p>Previous post on original release is available at &lt;a href="https://zhisme.com/articles/copy-with-context-nvim">copy_with_context.nvim plugin released&lt;/a>.&lt;/p>
&lt;h2 id="whats-new-in-v3">What&amp;rsquo;s New in v3&lt;/h2>
&lt;h3 id="automatic-repository-url-generation">Automatic Repository URL Generation&lt;/h3>
&lt;p>The headline feature: when you copy code, the plugin now automatically includes a direct permalink to the code in your repository. No manual URL construction, no hunting for the right commit SHA—it just works.&lt;/p>
&lt;pre>&lt;code class="language-lua">-- When you copy this code, you get:
function authenticate(user)
 validate_credentials(user)
end

-- Output automatically includes:
-- app/controllers/auth_controller.rb:45-47
-- https://github.com/username/repo/blob/abc1234/app/controllers/auth_controller.rb#L45-L47
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>What it does:&lt;/strong>&lt;/p></description></item><item><title>You Don’t Need Types in Ruby</title><link>https://zhisme.com/articles/you-dont-need-types-in-ruby/</link><pubDate>Wed, 29 Oct 2025 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/you-dont-need-types-in-ruby/</guid><description>&lt;p>There was a lively discussion on Hacker News &lt;a href="https://news.ycombinator.com/item?id=43938400">here&lt;/a> about &lt;a href="https://sorbet.org/">Sorbet&lt;/a> and static typing in Ruby that inspired this post.&lt;/p>
&lt;p>It’s fascinating how people try to make Ruby &lt;em>look&lt;/em> like a statically typed language. But this isn’t the first attempt — and every time, it ends up fighting against what Ruby fundamentally is.&lt;/p>
&lt;p>Turning Ruby into Java isn’t progress. It’s a step backward.&lt;br>
Let me explain why.&lt;/p>
&lt;h2 id="how-ruby-deals-with-types">How Ruby Deals with Types&lt;/h2>
&lt;p>Ruby is a dynamically typed, object-oriented language designed around message passing — an idea borrowed from &lt;a href="https://en.wikipedia.org/wiki/Smalltalk">Smalltalk&lt;/a>.&lt;/p></description></item><item><title>copy_with_context.nvim plugin released</title><link>https://zhisme.com/articles/copy-with-context-nvim/</link><pubDate>Sun, 13 Apr 2025 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/copy-with-context-nvim/</guid><description>&lt;p>I&amp;rsquo;m excited to announce the release of my new Neovim plugin, &lt;a href="https://github.com/zhisme/copy_with_context.nvim">copy_with_context.nvim&lt;/a>&lt;/p>
&lt;p>When sharing code snippets, it&amp;rsquo;s often useful to include the file path and line number for context. This plugin makes it easy to copy lines with this metadata. It is easier to understand the context of the code snippet when the file path and line number are included. Otherwise you have to do it manually. Copying snippet, then adding the line number &lt;em>(what if it is long config file? it is boring)&lt;/em>. We can automate it and do not waste our time.&lt;/p></description></item><item><title>lazy_names gem, how much time do you spend in console?</title><link>https://zhisme.com/articles/lazy-names/</link><pubDate>Sun, 12 Jan 2020 00:00:00 +0000</pubDate><guid>https://zhisme.com/articles/lazy-names/</guid><description>&lt;p>I&amp;rsquo;m happy to share the &lt;a href="https://github.com/zhisme/lazy_names?tab=readme-ov-file#lazy_names">lazy_names&lt;/a> gem!&lt;br>
This gem allows you to define a config file that maps long, namespaced constants to something simpler and more intuitive:&lt;/p>
&lt;pre>&lt;code class="language-yml">'Models::Users::CreditCard': 'UserCard'
&lt;/code>&lt;/pre>
&lt;p>I spend a lot of time in the console, which is why I originally wrote this gem. Here’s a quick look at my most frequently run commands from my Zsh history:&lt;/p>
&lt;pre>&lt;code class="language-sh">$: history | awk '{$1=&amp;quot;&amp;quot;; print $0}' | sort | uniq -c | sort -nr
 647 gs
 135 rc # rails console
 135 ls
 134 gd
 ...
&lt;/code>&lt;/pre>
&lt;p>Do you use the Ruby console much while developing? I personally like to check my code directly in the console — calling methods to inspect return values — especially in the early development stage before tests are written. Sometimes, I need to drop records from the database or build some structs on the fly.&lt;/p></description></item></channel></rss>