# Leonid Svyatov > I'm Leonid, a software engineer. For 15+ years, I've worked with founders to figure out what they need, build it, and keep it running. I like asking questions before writing code and helping other developers grow. These days, I build with coding agents and share much of my work as open source. Personal site of Leonid Svyatov, Lead Software Engineer. Built with Astro, hosted on GitHub Pages. Full post bodies: https://svyatov.com/llms-full.txt ## Pages - [Home](https://svyatov.com/): who I am, stack, latest posts, selected projects - [Projects](https://svyatov.com/projects/): open-source libraries and tools I maintain - [Blog](https://svyatov.com/blog/): What I learn building software, fixing bugs, and testing the tools I rely on. - [CV](https://svyatov.com/cv/): work experience, skills, education - [Privacy](https://svyatov.com/privacy/): what the site collects about visitors ## Blog posts - [Five ways to build a save panel, three of them correct](https://svyatov.com/blog/five-ways-to-build-a-save-panel-three-of-them-correct/): Here is a save panel: a spinner, an error banner, a dirty marker, a confirm dialog, and a closed flag. Five booleans, so thirty-two combinations. Have you ever written down all thirty-two? (2026-08-07) - [Your agent writes Python. The Ruby rule cuts that by a third.](https://svyatov.com/blog/your-agent-writes-python-the-ruby-rule-cuts-that-by-a-third/): A controlled comparison of Ruby, Python, and shell scripts written by a coding agent, measuring output size, correctness, and the effect of instructions. (2026-08-06) - [I wrote down 61 rules, then failed my own repos](https://svyatov.com/blog/i-wrote-down-61-rules-then-failed-my-own-repos/): How oss-kit uses 61 repository maintenance rules and nine agent skills to audit documentation, security, CI, releases, and community files. (2026-08-04) - [Kubernetes earned its security badge in 2017 and never came back](https://svyatov.com/blog/kubernetes-earned-its-security-badge-in-2017-and-never-came-back/): An examination of OpenSSF Best Practices badges: their criteria, verification, stale entries, and what a badge can tell you about project security. (2026-07-31) - [Rails already ships class_names. I built clsx anyway.](https://svyatov.com/blog/rails-already-ships-classnames-i-built-clsx-anyway/): Compare Rails class_names with clsx: standalone Ruby use, empty values, accepted inputs, performance measurements, and optional Tailwind class merging. (2026-07-21) - [Ruby shipped the fix for SleeperGem 45 days before it happened](https://svyatov.com/blog/ruby-shipped-the-fix-for-sleepergem-45-days-before-it-happened/): How Bundler cooldown could have blocked the SleeperGem releases, what the published download figures mean, and where delayed updates cannot protect you. (2026-07-21) - [Learn Big O by measuring it, in Ruby](https://svyatov.com/blog/learn-big-o-by-measuring-it-in-ruby/): Measure algorithm growth in Ruby by doubling inputs, compare Big O classes, and learn where timing estimates fail and how to check complexity in CI. (2026-07-20) - [Keeping code alive on a DOM you don't own: 12-year Chrome extension story](https://svyatov.com/blog/keeping-code-alive-on-a-dom-you-dont-own-12-year-chrome-extension-story/): Lessons from maintaining Hacker News Sorted: resilient DOM selectors, failure reporting, daily compatibility checks, timestamps, and extension design. (2026-07-17) - [The four places a hand-rolled Ruby facade gives out](https://svyatov.com/blog/the-four-places-a-hand-rolled-ruby-facade-gives-out/): When a plain Ruby facade needs more: memoization, namespaces, reusable packs, and error handling, with examples from the briefly gem. (2026-07-16) - [The complete guide to `rails new` in Rails 8.1](https://svyatov.com/blog/the-complete-guide-to-rails-new-in-rails-81/): A guide to Rails 8.1 rails new options, covering databases, frontend tools, deployment, testing, skipped frameworks, and common application recipes. (2026-03-03) - [I got tired of looking up `rails new` flags, so I built a wizard for it](https://svyatov.com/blog/i-got-tired-of-looking-up-rails-new-flags-so-i-built-a-wizard-for-it/): Create Rails applications with an interactive CLI wizard that explains rails new options, remembers choices, saves presets, and shows the final command. (2026-02-27) - [clsx for Rails views](https://svyatov.com/blog/clsx-for-rails-views/): Build conditional CSS class strings in Rails views with clsx-rails, using strings, arrays, hashes, deduplication, and the shorter cn helper. (2024-03-03) - [How to hide Ruby 2.7 deprecation warnings system-wide](https://svyatov.com/blog/how-to-hide-ruby-2-7-deprecation-warnings-system-wide/): Are you using rbenv? Want to hide Ruby 2.7 deprecation warnings system-wide and not to deal with it on a per-project basis? This small tutorial is for you! (2020-04-24) - [Keep your Javascript dependencies under control](https://svyatov.com/blog/keep-your-javascript-dependencies-under-control/): The best way to explore the size and content of your frontend. (2019-03-04) - [Easier usage of Rails 5.2 credentials and app-specific configuration](https://svyatov.com/blog/easier-usage-of-rails-52-credentials-and-app-specific-configuration/): Have you ever thought “isn’t there a simpler, more concise way to write `Rails.application.credentials[:something]`?” This post suggests a solution to this problem. (2019-02-24) - [How to send Rails deprecation warnings to Airbrake](https://svyatov.com/blog/how-to-send-rails-deprecation-warnings-to-airbrake/): Send Rails production deprecation warnings to Airbrake with an ActiveSupport::Notifications subscriber that preserves the message and call stack. (2019-02-18) - [A bookmarklet for Tweetbot for Mac](https://svyatov.com/blog/tweetbot-bookmarklet-for-mac/): Two ways to share the current browser page to Tweetbot for Mac in one click: a tiny bookmarklet built on the Tweetbot URL scheme, and a Chrome extension for those who prefer not to bother. (2014-10-04) - [How to partition and format a drive with GNU Parted](https://svyatov.com/blog/partition-and-format-a-drive-with-gnu-parted/): Four commands in the parted shell are all it takes to repartition and format a drive on Linux: pick the disk from parted -l, create a gpt or msdos label, make one ext4 partition, and quit. (2014-08-12) - [Upload and download files on a remote server with iTerm2 and Z-Modem](https://svyatov.com/blog/upload-and-download-files-on-a-remote-server-with-iterm2-and-zmodem/): How to send files to a remote server and pull them back from inside an SSH session, without opening a separate scp session, using the Z-Modem protocol, lrzsz and iTerm2 triggers. (2014-07-16) - [Using unique option prefix pass instead of password is deprecated](https://svyatov.com/blog/using-unique-option-prefix-pass-instead-of-password-is-deprecated/): If MySQL or your cron logs suddenly started printing this warning, the culprit is most likely a shortened option name in your ~/.my.cnf. Here is the one-line fix. (2013-09-27) - [Nobody knows how to upload a file with Ruby Net::HTTP](https://svyatov.com/blog/nobody-knows-how-to-upload-a-file-with-ruby-net-http/): Every answer online tells you to reach for a wrapper gem or shell out to curl. Ruby's standard Net::HTTP can send a multipart/form-data file upload on its own, and here is how. (2013-09-16) - [Munin: LWP::UserAgent and Cache::Cache](https://svyatov.com/blog/munin-lwp-useragent-and-cache-cache/): Munin shows no MySQL or Nginx data on a fresh Debian install because two Perl libraries are missing. Here are the packages to install and the Nginx status config the plugin expects. (2013-09-02) - [Mac OS X: paste without the source formatting](https://svyatov.com/blog/mac-os-x-paste-without-source-formatting/): How to make Cmd+V paste plain text in every Mac OS X app, with no third-party tools and no terminal, by remapping the shortcut to Paste and Match Style in System Preferences. (2013-08-23) - [BetterErrors and RubyMine on Mac OS X](https://svyatov.com/blog/bettererrors-and-rubymine-on-mac-os-x/): How to make the BetterErrors gem open the offending file and line in RubyMine straight from the browser with a single click, using the x-mine URL scheme. (2013-03-28) - [Optimizing WordPress (and more) with Grunt](https://svyatov.com/blog/optimizing-wordpress-and-more-with-grunt/): How I used Grunt to concatenate, minify and gzip the styles and scripts of a WordPress theme, with a Gruntfile.coffee you can borrow and a fingerprint trick for cache busting. (2013-02-28) - [Tracking site errors with Ratchet.io](https://svyatov.com/blog/tracking-site-errors-with-ratchet-io/): Why Ratchet.io (soon to be Rollbar) beats Airbrake for small projects: official support for Rails, Python, PHP, Node.js and JavaScript, deploy tracking, GitHub integration and a free plan that is actually usable. (2013-02-14) ## Feeds - [RSS](https://svyatov.com/rss.xml) - [Atom](https://svyatov.com/atom.xml) - [JSON Feed](https://svyatov.com/feed.json)