Essential Claude Code Skills and Commands

I’ll admit it: when I first started using Claude Code, I mostly ignored the built-in skills. Everyone online was saying “go make your own skills,” so that’s what I did. I wrote custom skills for all sorts of things and I got plenty of things done with them. | Continue reading


@batsov.com | 19 hours ago

Emacs and Vim in the Age of AI

It’s tough to make predictions, especially about the future. – Yogi Berra | Continue reading


@batsov.com | 2 days ago

Learning OCaml: String Interpolation

Most programming languages I’ve used have some form of string interpolation. Ruby has "Hello, #{name}!", Python has f-strings, JavaScript has template literals, even Haskell has a few popular interpolation libraries. It’s one of those small conveniences you don’t think about unti … | Continue reading


@batsov.com | 8 days ago

Learning OCaml: PPX for Mere Mortals

When I started learning OCaml I kept running into code like this: | Continue reading


@batsov.com | 8 days ago

Learning OCaml: Printing Data Structures

If there’s one thing that frustrated me early on in my OCaml journey, it was printing stuff. In Ruby I can p anything and get a useful representation. In Clojure, prn just works on every data structure. In OCaml? There’s no generic print that works on any type – the type informat … | Continue reading


@batsov.com | 10 days ago

Learning OCaml: Working with Records

Records are one of those things that look almost identical across ML-family languages, so I didn’t expect many surprises when I started using them in OCaml. For the most part I was right – but there were a few things worth noting, especially if you’re coming from a language where … | Continue reading


@batsov.com | 10 days ago

Building Emacs Major Modes with TreeSitter: Lessons Learned

Over the past year I’ve been spending a lot of time building TreeSitter-powered major modes for Emacs – clojure-ts-mode (as co-maintainer), neocaml (from scratch), and asciidoc-mode (also from scratch). Between the three projects I’ve accumulated enough battle scars to write abou … | Continue reading


@batsov.com | 12 days ago

Setting up Emacs for OCaml Development: Neocaml Edition

A few years ago I wrote about setting up Emacs for OCaml development. Back then the recommended stack was tuareg-mode + merlin-mode, with Merlin providing the bulk of the IDE experience. A lot has changed since then – the OCaml tooling has evolved considerably, and I’ve been work … | Continue reading


@batsov.com | 15 days ago

Learning Vim in 3 Steps

Every now and then someone asks me how to learn Vim.1 My answer is always the same: it’s simpler than you think, but it takes longer than you’d like. Here’s my bulletproof 3-step plan. Just kidding – everyone asks me about learning Emacs. But here we are. ↩︎ | Continue reading


@batsov.com | 15 days ago

How to Vim: Auto-save on Activity

How to set up auto-saving in Vim, from simple autocommands to plugins, and why you might not need any of it. | Continue reading


@batsov.com | 15 days ago

How to Vim: To the Terminal and Back

Comparing Vim's two main approaches to shell access -- suspending with Ctrl-Z and the built-in terminal emulator. | Continue reading


@batsov.com | 17 days ago

How to Vim: Build your .vimrc from Scratch

You don't need a massive .vimrc to be productive in Vim. | Continue reading


@batsov.com | 17 days ago

Adding Empty Lines in Vim: Redux

All the ways to add blank lines above or below the cursor in Vim | Continue reading


@batsov.com | 17 days ago

Supercharging Claude Code with the Right (CLI) Tools

I’ve been using Claude Code quite a bit lately, and I got curious – what if I asked it directly which tools would make it more productive? Not the usual suspects like ripgrep, jq or git, but tools it wishes it had access to, tools that would genuinely extend its capabilities. | Continue reading


@batsov.com | 22 days ago

How to Vim: Many Ways to Paste

Most Vim users know p and P – paste after and before the cursor. Simple enough. But did you know that Vim actually has around a dozen paste commands, each with subtly different behavior? I certainly didn’t when I started using Vim, and I was surprised when I discovered the full p … | Continue reading


@batsov.com | 24 days ago

Neocaml 0.1: Ready for Action

neocaml 0.1 is finally out! Almost a year after I announced the project, I’m happy to report that it has matured to the point where I feel comfortable calling it ready for action. Even better - neocaml recently landed in MELPA, which means installing it is now as easy as: | Continue reading


@batsov.com | 25 days ago

A Fresh Look for the Blog: Switching to Jekyll’s Chirpy Theme

It’s been over 4 years since I last updated the look of my blog - in late 2021 I switched to the popular at the time “Minimal Mistakes” theme. It served we well, but like so many Jekyll themes it got abandoned in recent years, so I’ve been shopping recently for a good actively-ma … | Continue reading


@batsov.com | 1 month ago

Tips on Using Mastodon

I’ve started using Mastodon over 3 years ago, in the aftermath of Twitter’s meltdown. At first I didn’t like it much, as there were a few things about it I found frustrating: | Continue reading


@batsov.com | 1 month ago

How to Vim: Navigating Prose in Style

I don’t know about you, but I’m not using Vim solely for programming. I also write documentation in it, plus most of my blog posts (like this one). | Continue reading


@batsov.com | 2 months ago

How to Vim: Alternative Approach to Find and Replace

The classic way to do “find and replace” in Vim is pretty well known: | Continue reading


@batsov.com | 2 months ago

How to Vim: Insert Thing at Point in Command Mode

Most Vim users probably know that they can use Ctrl-R to insert the contents of registers, while typing some command. For instance - you can insert the clipboard contents with Ctrl-R +. | Continue reading


@batsov.com | 2 months ago

How to Vim: Using Effectively the Command History

One of the frustrating aspects of Vim for me is that in insert mode you’re quite limited in what you can do. That’s fine most of the time, except when you’re in command-line mode (meaning you’re typing something like :s). In command-line mode there’s no way to switch to normal mo … | Continue reading


@batsov.com | 2 months ago

How to Vim: Joining Lines

Joining adjacent lines is something that comes up often while editing text/code. That’s why it should come as no surprise that this is something well supported by Vim. You have two ways to join lines at your disposal: | Continue reading


@batsov.com | 2 months ago

Burst-driven Development: My Approach to OSS Projects Maintenance

I’ve been working on OSS projects for almost 15 years now. Things are simple in the beginning - you’ve got a single project, no users to worry about and all the time and the focus in world. Things changed quite a bit for me over the years and today I’m the maintainer of a couple … | Continue reading


@batsov.com | 3 months ago

Rust: Embrace Captured Identifier in Format Strings

While playing with Rust recently I’ve noticed that most Rust tutorials suggest writing code like this: | Continue reading


@batsov.com | 3 months ago

Configure Quick Terminal Size in Ghostty

I’m a very heavy quick (dropdown) terminal user, so after adopting Ghostty one of the points of frustration for me was that I could not specify a default size for my quick terminal. Instead I had to adjust the size every time I started Ghostty. | Continue reading


@batsov.com | 3 months ago

Why I Chose Ruby over Python

This year I spent a bit of time playing with Python, after having mostly ignored it since 2005 when was learning it originally. I did like Python back then, but a few years afterwards I discovered Ruby and quickly focused my entire attention on it. | Continue reading


@batsov.com | 6 months ago

Wayward Predicates in Ruby

Recently I’ve been wondering how to name Ruby methods that have predicate looking names (e.g. foo?), but don’t behave like predicates - namely they return other values besides the canonical true and false.1 This came up in the context of RuboCop, in case someone’s wondering. ↩ | Continue reading


@batsov.com | 6 months ago

How to Vim: Fixing Typos

Here’s another small Vim tip - how to deal with typos quickly. Generally, most people do something along those lines: | Continue reading


@batsov.com | 6 months ago

How to Vim: Take Control of Split Positioning

One of my pet peeves with Vim is that by default the buffer splitting behaves a bit weird: | Continue reading


@batsov.com | 6 months ago

Learning OCaml: Having Fun with the Fun Module

When I started to play with OCaml I was kind of surprised that there was no id (identity) function that was available out-of-box (in Stdlib module, that’s auto-opened). A quick search lead me to the Fun module, which is part of the standard library and is nested under Stdlib. It … | Continue reading


@batsov.com | 7 months ago

Learning OCaml: Numerical Type Conversions

Today I’m going to cover a very basic topic - conversions between OCaml’s primary numeric types int and float. I guess most of you are wondering if such a basic topic deserves a special treatment, but if you read on I promise that it will be worth it. | Continue reading


@batsov.com | 7 months ago

zoxide: tips and tricks

zoxide is a smart and fast alternative to cd that learns your directory usage patterns and allows you to jump to directories quickly. It’s one of my favorite command-line tools and it’s an essential part of my workflow. | Continue reading


@batsov.com | 9 months ago

How to Fish: Moving Between Recent Directories

I love Fish, because it makes a lot of common everyday tasks easier and more convenient. One such task is moving (switching) between folders you’ve visited recently. In my case I often jump between project directories, configuration directories, etc. Historically I’ve used things … | Continue reading


@batsov.com | 9 months ago

How to Vim: Proper Ways to Escape

ESC (Escape) is one of the most central key in the world of Vim. It takes you from Insert mode to Normal mode and it also serves to interrupt operations in progress in Vim. You’ll be using it a lot! | Continue reading


@batsov.com | 9 months ago

How to Vim: Reloading File Buffers

In Vim (and many other editors) we interact with the contents of files via the “file buffer” abstraction. Basically, that’s the in-memory representation of a file within a text editor, that occasionally gets synchronized with the disk one (the actual file). | Continue reading


@batsov.com | 9 months ago

How to Vim: Jump Around

One of the most important aspects of effective editing is to be able to quickly move where you want to go in a buffer - e.g. to a specific line, paragraph, character, word, etc. | Continue reading


@batsov.com | 9 months ago

How to Vim: Toggle Comments

One if the things that had initially frustrated me about Vim is that out-of-the-box there’s no way to toggle comments on and off in programming languages. This definitely struck me as something odd, given that almost all of Vim’s users are programmers and we have to deal with com … | Continue reading


@batsov.com | 9 months ago

How to Vim: Toggle Comments

One if the things that had initially frustrated me about Vim is that out-of-the-box there’s no way to toggle comments on and off in programming languages. This definitely struck me as something odd, given that almost all of Vim’s users are programmers and we have to deal with com … | Continue reading


@batsov.com | 9 months ago

How to Vim: Format Lines

When writing long code comments or prose (e.g. in Markdown) I like to have lines neatly formatted to fit the textwidth setting.1 There are two common operators we can use in Vim to achieve this - gq and gw. Most of the time you’d use: I normally aim for line-length limit of eithe … | Continue reading


@batsov.com | 9 months ago

The origin of the pipeline operator (|>)

These days a lot of programming languages (especially those leaning towards functional programming) offer a pipeline operator (|>), that allows you to feed some data through a “pipeline” of transformation steps.1 Here’s a trivial example in F#: Funny enough, even Ruby has a pipel … | Continue reading


@batsov.com | 9 months ago

Remove Stale Labels Instantly with GitHub Actions

I maintain a lot of OSS projects and often I struggle to keep up with all the tickets and pull requests they receive. That’s why I’m fond of the stale GHA workflow that automatically marks issues and PRs as stale after a (configurable) period of inactivity. This serves to remind … | Continue reading


@batsov.com | 9 months ago

Rediscovering Vim

Most people who know me and follow my open-source work are likely going to be surprised that I’m writing an article about Vim. After all, I’ve been a devout member of the Church of Emacs for 20 years now, and I’ve spent a lot of time preaching the gospel of Emacs and building ext … | Continue reading


@batsov.com | 9 months ago

Switching from Zsh to Fish

Recently I’ve switched from Z Shell (aka Zsh) to Fish, after being a Zsh user since 2008. The experience has been pretty good overall and here I’ll share a few tips for everyone looking to make the change. | Continue reading


@batsov.com | 9 months ago

Using use-package the right way

I recently wrote that Emacs startup time doesn’t matter and I got quite a lot of heat for it. I totally stand by everything I said there, but I acknowledge that different people have different use-cases and perspectives when it comes to this. | Continue reading


@batsov.com | 10 months ago

My favorite tilde keybindings

I’m a big fan of the ~ (tilde) key and I make heavy use of it every day. That’s why I’ve never been fond of keyboards that move its position for whatever reason.1 The famous HHKB being the most notable example. ↩ | Continue reading


@batsov.com | 10 months ago

Emacs Startup Time Doesn’t Matter

Every now and then I see people discussion one of the following: | Continue reading


@batsov.com | 11 months ago

Learning OCaml: Module Aliases

OCaml is famous for allow you to do a lot of things like modules. Like really a lot! Advanced features like functors, aside, it’s really common to either alias module names to something shorter or localize open Module_name to a smaller scope: | Continue reading


@batsov.com | 11 months ago