<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Jujutsu on MoskitoHero</title><link>/tags/jujutsu/</link><description>Recent content in Jujutsu on MoskitoHero</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Tue, 30 Jun 2026 09:29:19 +0200</lastBuildDate><atom:link href="/tags/jujutsu/index.xml" rel="self" type="application/rss+xml"/><item><title>How I Use JuJutsu Revisions to Plan My Work Ahead</title><link>/post/2026-06-30-how-i-use-jj-revisions-to-plan-my-work/</link><pubDate>Tue, 30 Jun 2026 09:29:19 +0200</pubDate><guid>/post/2026-06-30-how-i-use-jj-revisions-to-plan-my-work/</guid><description>JuJutsu VCS gives me planning superpowers. Here is how I use its revisions and flexible workflow to plan my work ahead and keep track of my progress.</description><content:encoded><![CDATA[<div class="paragraph">
<p><a href="https://www.jj-vcs.dev/latest/">JuJutsu</a> is a distributed version control system that allows you to manage your codebase and collaborate with others. One
of its features is the ability to create revisions, which are snapshots of your code at a specific point in time. In
this post, I will share how I use JuJutsu revisions to plan my work ahead.</p>
</div>
<div class="paragraph">
<p>When I start working on a new ticket, I usually create a new revision for it, with the ticket number and description,
along with a bookmark, like I described <a href="https://moskitohero.com/post/2026-06-23-nujutsu-custom-jujutsu-commands-in-nushell-with-a-neovim-twist">in my previous post</a>.</p>
</div>
<div class="paragraph">
<p>The next step is to start planning my work ahead. And JuJutsu makes it easier by allowing me to split my ticket into
multiple sub-tasks, each matched to its own revision. That way, I can start working on one sub-task, then the next one,
and so on.</p>
</div>
<div class="paragraph">
<p>This is what it can look like in practice:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="/assets/img/jj-planning-ahead.png" alt="Planning Ahead with JuJutsu Revisions"/>
</div>
</div>
<div class="paragraph">
<p>Keeping that habit is very useful because it forces me to think things through before I start coding. When working with
an agent, it also gives it the context of the piece of work I am doing, and allows it to focus on the right sub-task,
instead of trying to solve the whole ticket at once.</p>
</div>
<div class="paragraph">
<p>What often happens it that when editing a revision, I realize that I have to change something I had not anticipated in
the previous one. In that case, I just go back to it and edit it. If that change is important and requires a lot of work,
I usually create a new revision on top of the previous one, and squash it once I am happy with the result.</p>
</div>
<div class="paragraph">
<p>The icing on the JJ cake is that if those changes lead up to conflicts, <a href="https://www.jj-vcs.dev/latest/conflicts/">they do not block me</a>. I can follow my train of
thought, and resolve the conflicts later, when I have more time / energy to devote to it.</p>
</div>
<div class="paragraph">
<p>Once everything is done, I can squash all the revisions into one, or keep a few of them as logical milestones in my work
if I want to keep track of the progress I made.</p>
</div>
]]></content:encoded></item><item><title>Nujutsu Custom Jujutsu Commands in Nushell (With a Neovim Twist)</title><link>/post/2026-06-23-nujutsu-custom-jujutsu-commands-in-nushell-with-a-neovim-twist/</link><pubDate>Tue, 23 Jun 2026 06:40:13 +0200</pubDate><guid>/post/2026-06-23-nujutsu-custom-jujutsu-commands-in-nushell-with-a-neovim-twist/</guid><description>A couple of small Nu functions I use daily at work to make my life easier with JuJutsu and Nushell.</description><content:encoded><![CDATA[<div class="paragraph">
<p>I use <a href="https://www.nushell.sh">Nushell</a> as my main shell. I love it for the UX, the UI, and the syntax. I do sometimes hate it for not being POSIX, but since that’s the whole point of the thing, I cannot really complain.</p>
</div>
<div class="paragraph">
<p>I also use <a href="https://www.jj-vcs.dev/latest/">JuJutsu</a> as my main VCS. I love it for the UX, the UI, and the commands.</p>
</div>
<div class="paragraph">
<p>Say what you want, I’m a tech romantic.</p>
</div>
<div class="paragraph">
<p>So let me share a little bit of <strong>NuJutsu</strong> love with those two small Nu functions I use daily at work:</p>
</div>
<div class="sect1">
<h2 id="jj-desc"><a class="anchor" href="#jj-desc"></a>jj-desc</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This one interactively asks me for the JIRA ticket number, and the title of issue. It builds a formatted description out of it.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="ruby"> <span class="k">def</span> <span class="nf">jj</span><span class="o">-</span><span class="n">desc</span> <span class="p">[]</span> <span class="p">{</span>
    <span class="n">let</span> <span class="n">ticket</span> <span class="o">=</span> <span class="n">input</span> <span class="s2">&#34;Ticket number: &#34;</span>
    <span class="n">let</span> <span class="n">title</span> <span class="o">=</span> <span class="n">input</span> <span class="s2">&#34;Title: &#34;</span>
    <span class="n">jj</span> <span class="n">desc</span> <span class="o">-</span><span class="n">m</span> <span class="vg">$&#34;</span><span class="p">[(</span><span class="vg">$ticket</span><span class="p">)]</span> <span class="p">(</span><span class="vg">$title</span><span class="p">)</span><span class="s2">&#34;
  }
</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jj-bookmark-from-desc"><a class="anchor" href="#jj-bookmark-from-desc"></a>jj-bookmark-from-desc</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This one creates a bookmark from the current JJ description — provided it uses the correct format specified above, so <code>[PROJ-12345] Add feature A to project C</code> will yield a bookmark like <code>feature/proj-12345-add-feature-a-to-project-c</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="ruby"><span class="k">def</span> <span class="nf">jj</span><span class="o">-</span><span class="n">bookmark</span><span class="o">-</span><span class="n">from</span><span class="o">-</span><span class="n">desc</span> <span class="p">[]</span> <span class="p">{</span>
      <span class="n">let</span> <span class="n">desc</span> <span class="o">=</span> <span class="p">(</span><span class="n">jj</span> <span class="n">log</span> <span class="o">-</span><span class="n">r</span> <span class="err">@</span> <span class="o">--</span><span class="n">no</span><span class="o">-</span><span class="n">graph</span> <span class="o">-</span><span class="no">T</span> <span class="s1">&#39;description.first_line()&#39;</span><span class="p">)</span>
      <span class="n">let</span> <span class="n">bookmark</span> <span class="o">=</span> <span class="p">(</span><span class="vg">$desc</span>
        <span class="o">|</span> <span class="n">str</span> <span class="n">downcase</span>
        <span class="o">|</span> <span class="n">str</span> <span class="n">replace</span> <span class="o">--</span><span class="n">all</span> <span class="o">--</span><span class="n">regex</span> <span class="s1">&#39;[^a-z0-9\s-]&#39;</span> <span class="s1">&#39;&#39;</span>
        <span class="o">|</span> <span class="n">str</span> <span class="n">replace</span> <span class="o">--</span><span class="n">all</span> <span class="o">--</span><span class="n">regex</span> <span class="s1">&#39;\s+&#39;</span> <span class="s1">&#39;-&#39;</span>
        <span class="o">|</span> <span class="n">str</span> <span class="n">replace</span> <span class="o">--</span><span class="n">all</span> <span class="o">--</span><span class="n">regex</span> <span class="s1">&#39;-+&#39;</span> <span class="s1">&#39;-&#39;</span>
        <span class="o">|</span> <span class="n">str</span> <span class="n">trim</span> <span class="o">--</span><span class="n">right</span> <span class="o">--</span><span class="n">char</span> <span class="s1">&#39;-&#39;</span><span class="p">)</span>
      <span class="n">jj</span> <span class="n">bookmark</span> <span class="n">create</span> <span class="vg">$&#34;</span><span class="n">feature</span><span class="o">/</span><span class="p">(</span><span class="vg">$bookmark</span><span class="p">)</span><span class="s2">&#34;
    }</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the-icing-on-the-cake-neovim-counterparts"><a class="anchor" href="#the-icing-on-the-cake-neovim-counterparts"></a>The icing on the cake: Neovim counterparts</h2>
<div class="sectionbody">
<div class="paragraph">
<p>I use [jj.nvim] to manage my JJ log in Neovim.</p>
</div>
<div class="paragraph">
<p>Here is part of my LazyVim plugin definition:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="lua"><span class="k">return</span> <span class="p">{</span>
  <span class="s2">&#34;nicolasgb/jj.nvim&#34;</span><span class="p">,</span>
  <span class="n">branch</span> <span class="o">=</span> <span class="s2">&#34;main&#34;</span><span class="p">,</span>
  <span class="n">lazy</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span>
  <span class="n">config</span> <span class="o">=</span> <span class="k">function</span><span class="p">()</span>
    <span class="nb">require</span><span class="p">(</span><span class="s2">&#34;jj&#34;</span><span class="p">).</span><span class="n">setup</span><span class="p">({})</span>
    <span class="kd">local</span> <span class="n">cmd</span> <span class="o">=</span> <span class="nb">require</span><span class="p">(</span><span class="s2">&#34;jj.cmd&#34;</span><span class="p">)</span>
    <span class="n">vim</span><span class="p">.</span><span class="n">keymap</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;leader&gt;ji&#34;</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span>
      <span class="k">if</span> <span class="ow">not</span> <span class="n">utils</span><span class="p">.</span><span class="n">is_jj_repo</span><span class="p">()</span> <span class="k">then</span>
        <span class="n">vim</span><span class="p">.</span><span class="n">notify</span><span class="p">(</span><span class="s2">&#34;Not in a jj repository&#34;</span><span class="p">,</span> <span class="n">vim</span><span class="p">.</span><span class="n">log</span><span class="p">.</span><span class="n">levels</span><span class="p">.</span><span class="n">WARN</span><span class="p">)</span>
        <span class="k">return</span>
      <span class="k">end</span>
      <span class="n">vim</span><span class="p">.</span><span class="n">ui</span><span class="p">.</span><span class="n">input</span><span class="p">({</span> <span class="n">prompt</span> <span class="o">=</span> <span class="s2">&#34;Jira ticket: &#34;</span> <span class="p">},</span> <span class="k">function</span><span class="p">(</span><span class="n">ticket</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">ticket</span> <span class="k">then</span> <span class="k">return</span> <span class="k">end</span>
        <span class="n">vim</span><span class="p">.</span><span class="n">ui</span><span class="p">.</span><span class="n">input</span><span class="p">({</span> <span class="n">prompt</span> <span class="o">=</span> <span class="s2">&#34;Title: &#34;</span> <span class="p">},</span> <span class="k">function</span><span class="p">(</span><span class="n">title</span><span class="p">)</span>
          <span class="k">if</span> <span class="ow">not</span> <span class="n">title</span> <span class="k">then</span> <span class="k">return</span> <span class="k">end</span>
          <span class="n">cmd</span><span class="p">.</span><span class="n">describe</span><span class="p">(</span><span class="nb">string.format</span><span class="p">(</span><span class="s2">&#34;[%s] %s&#34;</span><span class="p">,</span> <span class="n">ticket</span><span class="p">,</span> <span class="n">title</span><span class="p">))</span>
        <span class="k">end</span><span class="p">)</span>
      <span class="k">end</span><span class="p">)</span>
    <span class="k">end</span><span class="p">,</span> <span class="p">{</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;JJ describe interactive&#34;</span> <span class="p">})</span>
    <span class="n">vim</span><span class="p">.</span><span class="n">keymap</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;leader&gt;jc&#34;</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span>
      <span class="k">if</span> <span class="ow">not</span> <span class="n">utils</span><span class="p">.</span><span class="n">is_jj_repo</span><span class="p">()</span> <span class="k">then</span>
        <span class="n">vim</span><span class="p">.</span><span class="n">notify</span><span class="p">(</span><span class="s2">&#34;Not in a jj repository&#34;</span><span class="p">,</span> <span class="n">vim</span><span class="p">.</span><span class="n">log</span><span class="p">.</span><span class="n">levels</span><span class="p">.</span><span class="n">WARN</span><span class="p">)</span>
        <span class="k">return</span>
      <span class="k">end</span>
      <span class="n">vim</span><span class="p">.</span><span class="n">cmd</span><span class="p">(</span><span class="s2">&#34;!nu -lc jj-bookmark-from-desc&#34;</span><span class="p">)</span>
    <span class="k">end</span><span class="p">,</span> <span class="p">{</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;JJ bookmark from desc&#34;</span> <span class="p">})</span>
  <span class="k">end</span><span class="p">,</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>jj-desc</code> command is rewritten in lua and gets a nice UX with two prompts popping up in your face when you launch it.</p>
</div>
<div class="paragraph">
<p>The <code>jj-bookmark-from-desc</code> command is just a plain keybinding.</p>
</div>
<div class="paragraph">
<p>In Emacs, I tend to open Vterm more often, so I just use my custom Nushell functions from there.</p>
</div>
</div>
</div>
]]></content:encoded></item><item><title>Directory-based git config rules</title><link>/post/directory-based-git-config-rules/</link><pubDate>Mon, 01 Jun 2026 16:22:00 +0200</pubDate><guid>/post/directory-based-git-config-rules/</guid><description>I have found a way to alter my git config based on the directory I am working from. Pretty simple, yet very handy.</description><content:encoded><![CDATA[<div class="paragraph">
<p>Like most devs, I use Git both for personal and work stuff, but I need to use distinct user details in each case to sign-off my commits. I have a global <code>.gitconfig</code> that define my personal email as <code>user.email</code>, but whenever I need to pull a new work project, I have to remember to set it to a different value locally. Which I keep forgetting to do.</p>
</div>
<div class="paragraph">
<p>So I have found a way to alter my git config based on the directory I am working from. All you need to do is add these lines to your <code>~/.gitconfig</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="toml"><span class="k">[</span><span class="n">user</span><span class="k">]</span>
  <span class="n">name</span> <span class="o">=</span><span class="w"> </span><span class="err">My Name
  email = personal@email.com

# Use work email for repositories under ~/dev/work
</span><span class="p">[</span><span class="err">includeIf </span><span class="s">&#34;gitdir:~/dev/work/&#34;</span><span class="p">]</span>
  <span class="n">path</span> <span class="o">=</span><span class="w"> </span><span class="err">~/.gitconfig-work</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>And edit <code>.gitconfig-work</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="toml"><span class="k">[</span><span class="n">user</span><span class="k">]</span>
  <span class="n">email</span> <span class="o">=</span><span class="w"> </span><span class="err">work-email@mycompany.com</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>I think this also applies to other git config values, so feel free to experiment!</p>
</div>
]]></content:encoded></item><item><title>Make Your Vcs Fly With Jujutsu</title><link>/post/make-your-vcs-fly-with-jujutsu/</link><pubDate>Thu, 21 May 2026 08:23:11 +0200</pubDate><guid>/post/make-your-vcs-fly-with-jujutsu/</guid><description>I am always attracted by new tools that promise to make my life easier. I recently started using Jujutsu, a version control system that makes your git workflow much more flexible.</description><content:encoded><![CDATA[<div class="paragraph">
<p>I like to try things out. I like new, shiny, alternative stuff that is not hype yet. I created my first Twitter account when you could see the world timeline of tweets refresh in real time on the home page. I also like new ideas that build upon great systems in order to improve them or take them a few steps further. That’s why I use <a href="https://zellij.dev">Zellij</a>, not Tmux. That’s why I use <a href="https://www.nushell.sh/">Nushell</a>, not bash, or zsh, as my main terminal shell. And that’s why I started using <a href="https://www.jj-vcs.dev">Jujutsu</a> to version control my code.</p>
</div>
<div class="paragraph">
<p>Jujutsu is a version control system UX that builds upon multiple VCS backends (Git, Mercurial, Breezy…​). Jujutsu (or JJ) provides a user-facing abstraction that makes your git workflow much more flexible.</p>
</div>
<div class="paragraph">
<p>For instance, there is no such things as branches. The closest equivalent is bookmarks. But bookmarks are more akin to mutable git tags. Git commits belong to a branch, and move when the branch gets merged into another. JJ puts this the other way round: bookmarks behave the way you’d expect a bookmark to behave: they can be moved around revsets (the jj equivalent of git commits). This alone opens a wide range of possibilities.</p>
</div>
<div class="paragraph">
<p>One of the key difference with Git is that you do not have a staging area. Instead, you tend to use revsets as throwaway commits to keep track of your work in progress. You can then squash them, or move them around, or abandon them. You can come back to an earlier revision and edit it! It’s as simple as calling <code>jj edit nf</code> (<code>nf</code> being the shortcode of the revision you wish to edit) and go modify your code. No commit needed. The revision is edited as is.</p>
</div>
<div class="paragraph">
<p>No stashes either. I have a list of bookmarks with a <code>stash</code> prefix that I use as stashes, but they are just revsets that I can move around and manipulate as I wish.</p>
</div>
<div class="paragraph">
<p>Other killer feature: conflicts are not blockers. You can have a conflict in your code, but you can still commit and move on, dealing with the conflict later on. Especially useful when you are working on a feature branch and want to keep up with the main branch. You can just merge the main branch into your feature branch, and deal with the conflicts later on, when you have more time to focus on them.</p>
</div>
<div class="paragraph">
<p>The icing on the cake is the undo/redo feature. Yes, you read that right. JJ provides an operation log (<code>jj op log</code>) that tracks all your operations, including commits, merges, rebases, splits, etc. Calling <code>jj undo</code> will undo the last operation.</p>
</div>
<div class="paragraph">
<p>JJ lives on top / besides of your git repo. All you have to do after you install JJ is cd into your repository and run <code>jj git init</code>. Voilà, you can now use JJ with your git backend.</p>
</div>
<div class="paragraph">
<p>It provides you with home-made, yet efficient diff and merge tool, but you can also use your own (Meld, Neovim, Ediff, you name it). It is designed to be very user-friendly from the command line — much more than git — but a few TUI clients and IDE integrations also exist. More on that in a later post.</p>
</div>
<div class="paragraph">
<p>I started using JJ a few weeks ago, and I never looked back. I really feels it makes my VCS workflow much less of a burden.</p>
</div>
<div class="paragraph">
<p>I will probably post more about the way I use it day-to-day, along with configuration tips and tools. Stay tuned!</p>
</div>
]]></content:encoded></item></channel></rss>