<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Théophile Roos - My Blog</title>
      <link>https://theophileroos.xyz/blog/</link>
      <description>Théophile Roos is a France based engineer.</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://theophileroos.xyz/blog/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Sat, 28 Mar 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Reproducing MacOS&#x27; Aerospace &#x27;move-workspace-to-monitor --wrap-around next&#x27; in hyprland</title>
          <pubDate>Sat, 28 Mar 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://theophileroos.xyz/blog/hyprland-script-aerospace-move-workspace-to-next-screen/</link>
          <guid>https://theophileroos.xyz/blog/hyprland-script-aerospace-move-workspace-to-next-screen/</guid>
          <description xml:base="https://theophileroos.xyz/blog/hyprland-script-aerospace-move-workspace-to-next-screen/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nikitabobko&#x2F;AeroSpace&quot;&gt;Aerospace&lt;&#x2F;a&gt; is a tiling window manager for MacOS. One of its handy features is &lt;code&gt;move-workspace-to-monitor --wrap-around next&lt;&#x2F;code&gt;, which moves the current workspace to the next monitor and wraps around when reaching the last one.&lt;&#x2F;p&gt;
&lt;p&gt;This guide (more like me dumping this script on the internet) shows you how to replicate this behavior in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hyprwm&#x2F;Hyprland&quot;&gt;Hyprland&lt;&#x2F;a&gt;, a dynamic tiling Wayland compositor.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hyprland&lt;&#x2F;strong&gt; - includes &lt;code&gt;hyprctl&lt;&#x2F;code&gt; by default&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;jq&lt;&#x2F;strong&gt; - JSON processor used to parse &lt;code&gt;hyprctl&lt;&#x2F;code&gt; output&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-script&quot;&gt;The Script&lt;&#x2F;h2&gt;
&lt;p&gt;Add this script somewhere on your system, and make it executable.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ACTIVE_WS_JSON&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;hyprctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; activeworkspace -j&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;WS_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;$ACTIVE_WS_JSON&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; jq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; -r&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;.id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;CURRENT_MON&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;$ACTIVE_WS_JSON&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; jq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; -r&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;.monitor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;# read lines and put in array MONITORS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;mapfile&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; -t MONITORS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;lt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;hyprctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; monitors -j&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; jq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; -r&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;.[].name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;${!&lt;&#x2F;span&gt;&lt;span&gt;MONITORS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; [[ &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;MONITORS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;$i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;$CURRENT_MON&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot; ]]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    CURRENT_INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;$i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    break&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;  fi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NEXT_INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;$(( (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;CURRENT_INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; ${#&lt;&#x2F;span&gt;&lt;span&gt;MONITORS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; ))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;NEXT_MON&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;MONITORS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;$NEXT_INDEX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;hyprctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; dispatch moveworkspacetomonitor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;$WS_ID&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;$NEXT_MON&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;how-it-works&quot;&gt;How It Works&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Get active workspace info: &lt;code&gt;hyprctl activeworkspace -j&lt;&#x2F;code&gt; returns JSON with the current workspace ID and monitor name&lt;&#x2F;li&gt;
&lt;li&gt;Extract workspace ID and monitor: &lt;code&gt;jq&lt;&#x2F;code&gt; parses the JSON to get &lt;code&gt;.id&lt;&#x2F;code&gt; and &lt;code&gt;.monitor&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Build monitor list: &lt;code&gt;hyprctl monitors -j&lt;&#x2F;code&gt; returns all connected monitors, which we store in an array&lt;&#x2F;li&gt;
&lt;li&gt;Find current monitor index: Loop through the array to find where the current monitor is positioned&lt;&#x2F;li&gt;
&lt;li&gt;Calculate next monitor: Using modulo arithmetic &lt;code&gt;(current + 1) % total&lt;&#x2F;code&gt; gives us the next index, wrapping around to 0 when at the end&lt;&#x2F;li&gt;
&lt;li&gt;Move workspace: &lt;code&gt;hyprctl dispatch moveworkspacetomonitor&lt;&#x2F;code&gt; moves the workspace to the target monitor&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;keybinding&quot;&gt;Keybinding&lt;&#x2F;h2&gt;
&lt;p&gt;Then bind it to a keyboard shortcut:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$mainMod = ALT # Sets &amp;quot;ALT&amp;quot; key as main modifier&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;bind = $mainMod SHIFT, TAB, exec, &amp;lt;SCRIPT_FOLDER&amp;gt;&#x2F;move_workspace_to_next_monitor.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# now ALT + SHIFT + TAB will move your current workspace to the next screen.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</description>
      </item>
      <item>
          <title>How to create python GRPC stub with buf with local plugins</title>
          <pubDate>Thu, 05 Jun 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://theophileroos.xyz/blog/buf-python-grpc-local-plugin/</link>
          <guid>https://theophileroos.xyz/blog/buf-python-grpc-local-plugin/</guid>
          <description xml:base="https://theophileroos.xyz/blog/buf-python-grpc-local-plugin/">&lt;p&gt;Recently, I spent quite a bit of time traveling on French high-speed trains. While it&#x27;s one of the best rail experiences in the world, I often use that time to work on personal or company projects.&lt;&#x2F;p&gt;
&lt;p&gt;Many of these projects involve Golang backends and Python clients that communicate using Protobuf. I’ve introduced &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;buf.build&quot;&gt;Buf&lt;&#x2F;a&gt; into some of them, which significantly improved the way we manage our Protobuf definitions. However, I quickly ran into an issue for the Python gRPC clients: we had been relying on the Python CLI packaged in &lt;code&gt;grpcio&lt;&#x2F;code&gt; and &lt;code&gt;grpcio-tools&lt;&#x2F;code&gt; to build our stubs and there was no easy way to call this CLI as a protoc plugin in a buf.gen.yaml file.&lt;&#x2F;p&gt;
&lt;p&gt;Buf supports remote plugins, but when I (or any teammate) am stuck with unreliable internet on a train, it becomes a real limitation.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately, there&#x27;s a great solution: the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;wasilibs&quot;&gt;Wasilib&lt;&#x2F;a&gt; project, and more specifically, this repository: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;wasilibs&#x2F;protoc&quot;&gt;&lt;em&gt;wasilibs&#x2F;protoc&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;wasilibs&#x2F;protoc&lt;&#x2F;em&gt; provides Go-based CLI tools that run C-based &lt;code&gt;protoc&lt;&#x2F;code&gt; plugins using WebAssembly (WASM). This means we can run the &lt;code&gt;python_grpc&lt;&#x2F;code&gt; plugin locally, without relying on &lt;code&gt;protoc&lt;&#x2F;code&gt; directly. It simplifies converting traditional Makefile-based build setups into Buf configurations.&lt;&#x2F;p&gt;
&lt;p&gt;Here is an example of &lt;code&gt;buf.gen.yaml&lt;&#x2F;code&gt; using the Wasilib project.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; v2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;plugins&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; local&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; go&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; github.com&#x2F;wasilibs&#x2F;go-protoc-gen-grpc&#x2F;cmd&#x2F;protoc-gen-grpc_python@latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;    out&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; out&#x2F;python&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</description>
      </item>
      <item>
          <title>Configuring udev rules for the ZSA voyager on nixos</title>
          <pubDate>Sat, 28 Dec 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://theophileroos.xyz/blog/configuring-udev-rules-on-nixos-for-the-zsa-voyager/</link>
          <guid>https://theophileroos.xyz/blog/configuring-udev-rules-on-nixos-for-the-zsa-voyager/</guid>
          <description xml:base="https://theophileroos.xyz/blog/configuring-udev-rules-on-nixos-for-the-zsa-voyager/">&lt;p&gt;I just got the ZSA Voyager and I want to use their configurator Oryx.
I use mainly Macos for work and exclusively nixos at home.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;theophileroos.xyz&#x2F;blog&#x2F;configuring-udev-rules-on-nixos-for-the-zsa-voyager&#x2F;case_unopened.jpeg&quot; alt=&quot;the case I received from ZSA&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;By default nixos does not allow the browser to communicate directly with the keyboard through the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WebHID_API&quot;&gt;WebHID&lt;&#x2F;a&gt; API. To allow Oryx to communicate with the voyager we have to set some udev rules.&lt;&#x2F;p&gt;
&lt;p&gt;The udev rules are kindly provided by ZSA on their website so we could just copy the rules into our config using this nixos options: &lt;code&gt;services.udev.*&lt;&#x2F;code&gt; but the rules were already packaged by a nixpkgs contributor (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;search.nixos.org&#x2F;packages?channel=unstable&amp;amp;show=zsa-udev-rules&amp;amp;from=0&amp;amp;size=50&amp;amp;sort=relevance&amp;amp;type=packages&amp;amp;query=zsa&quot;&gt;zsa-udev-rules&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Then all that is left to do is to add this to our nix config:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot;&gt;&lt;code data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  services&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;udev&lt;&#x2F;span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;packages&lt;&#x2F;span&gt;&lt;span style=&quot;background-color: #BF616A;&quot;&gt; = with&lt;&#x2F;span&gt;&lt;span&gt; pkgs&lt;&#x2F;span&gt;&lt;span style=&quot;background-color: #BF616A;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    zsa-udev-rules&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;  ]&lt;&#x2F;span&gt;&lt;span style=&quot;background-color: #BF616A;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rebuild your config and you are done.&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
