<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Software Development Tips]]></title><description><![CDATA[Short and practical tips for software developers covering topics like product specifications, code management, development environments, VSCode, command line, testing, documentation, software estimation and so on.]]></description><link>https://devtips.stribny.name</link><image><url>https://substackcdn.com/image/fetch/$s_!BRqX!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf3b0de4-0bcc-47b5-a5e3-99c1ca9ac52a_515x515.png</url><title>Software Development Tips</title><link>https://devtips.stribny.name</link></image><generator>Substack</generator><lastBuildDate>Wed, 06 May 2026 06:38:56 GMT</lastBuildDate><atom:link href="https://devtips.stribny.name/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Petr Stribny]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[efficientdev@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[efficientdev@substack.com]]></itunes:email><itunes:name><![CDATA[Petr Stribny]]></itunes:name></itunes:owner><itunes:author><![CDATA[Petr Stribny]]></itunes:author><googleplay:owner><![CDATA[efficientdev@substack.com]]></googleplay:owner><googleplay:email><![CDATA[efficientdev@substack.com]]></googleplay:email><googleplay:author><![CDATA[Petr Stribny]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Toggle any VS Code setting with keyboard shortcuts]]></title><description><![CDATA[Have you ever wanted to toggle your line numbers with a single keystroke, or hide the Activity Bar to reclaim screen real estate?]]></description><link>https://devtips.stribny.name/p/toggle-any-vs-code-setting-with-keyboard</link><guid isPermaLink="false">https://devtips.stribny.name/p/toggle-any-vs-code-setting-with-keyboard</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Mon, 26 Jan 2026 18:33:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!bf3v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever wanted to toggle your line numbers with a single keystroke, or hide the Activity Bar to reclaim screen real estate?</p><p>Visual Studio Code offers an incredible depth of customization, but not every setting has a dedicated "toggle" command. Some features are essential in one moment but become distracting clutter the next. My journey with this started when I wanted to use relative line numbers. I quickly realized there wasn't a native way to dynamically switch between relative and absolute numbers, or hide them on a whim.</p><p>Fortunately, there is a solution. The <a href="https://marketplace.visualstudio.com/items?itemName=hoovercj.vscode-settings-cycler">Settings Cycler</a> extension allows you to define a list of values for any setting and "cycle" through them using a custom keybinding:</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;67a3db57-a00a-4403-b135-8fa9864f8ccf&quot;,&quot;duration&quot;:null}"></div><p><strong>How it works:</strong></p><ol><li><p>Install the extension.</p></li><li><p>Define your &#8220;cycling&#8221; options in your <em>settings.json</em> file under &#8220;settings.cycle".</p></li><li><p>Open <em>Keyboard Shortcuts</em> and assign a key combo to your new command (e.g., <em>settings.cycle.lineNumbers</em><code> </code>to a <code>Caps Lock + L</code>).</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bf3v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bf3v!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png 424w, https://substackcdn.com/image/fetch/$s_!bf3v!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png 848w, https://substackcdn.com/image/fetch/$s_!bf3v!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png 1272w, https://substackcdn.com/image/fetch/$s_!bf3v!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bf3v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png" width="823" height="457" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:457,&quot;width&quot;:823,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:28669,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/185868029?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bf3v!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png 424w, https://substackcdn.com/image/fetch/$s_!bf3v!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png 848w, https://substackcdn.com/image/fetch/$s_!bf3v!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png 1272w, https://substackcdn.com/image/fetch/$s_!bf3v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54f89911-51fa-482f-bae9-58ac83ca9e28_823x457.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p>May the Force be with you.</p><p>&#8212;Petr</p>]]></content:encoded></item><item><title><![CDATA[Implicit requirements]]></title><description><![CDATA[Most people are, euphemistically speaking, economical with software requirements.]]></description><link>https://devtips.stribny.name/p/implicit-requirements</link><guid isPermaLink="false">https://devtips.stribny.name/p/implicit-requirements</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Mon, 12 Jan 2026 18:57:32 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!clzz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!clzz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!clzz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png 424w, https://substackcdn.com/image/fetch/$s_!clzz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png 848w, https://substackcdn.com/image/fetch/$s_!clzz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png 1272w, https://substackcdn.com/image/fetch/$s_!clzz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!clzz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png" width="1024" height="498" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:498,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:564231,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/176486506?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!clzz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png 424w, https://substackcdn.com/image/fetch/$s_!clzz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png 848w, https://substackcdn.com/image/fetch/$s_!clzz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png 1272w, https://substackcdn.com/image/fetch/$s_!clzz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76c80cb-351f-4d77-abb9-989ae95652f7_1024x498.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Most people are, euphemistically speaking, economical with software requirements.</p><p>Clients, users, product owners, team leaders, and other ticket-writers typically don&#8217;t obsess about details. While laziness and knowledge gaps play their role, it also happens due to implicit expectations.</p><p>Implicit requirements are unstated, but expected, features or characteristics, that are so fundamental they are not written down or discussed. For instance, a client asking for a mobile app most likely expects to find it in the app store, a ticket for dark theme support might imply automatic switching based on system preferences, or a request for multi-factor authentication might imply an admin area to restore access for users who lost their phone.</p><p>The trouble is, of course, that people don&#8217;t share a common mind. And while idea-makers can live in a fuzzy world, developers don&#8217;t have that luxury. Regardless of seniority, developers require clearer specifications on of what needs to be done.</p><p>Every time you accept a feature request or a ticket, either for yourself or for your team, it makes sense to stop and identify implicit requirements. Similarly, it is important to do the same when creating work for others.</p><p>Assumed requirements are a liability. They lead to:</p><ul><li><p>Inaccurate estimates</p></li><li><p>Invisible scope creep</p></li><li><p>"guess-driven development"</p></li><li><p>Testing gaps</p></li></ul><p>Ultimately, implicit requirements result in costly rework that leaves everyone unhappy.</p><p>So be cautious, ask more questions, and develop that product and industry intuition over time. It also works better with more people, so include others. If you are doing something like refinement sessions, invite testers and support folks too. The result will be the best, as nobody will have to guess anymore.</p><p>When you eliminate the guesswork, you eliminate the risk.</p><div><hr></div><p></p><p>PF 2026</p><p>&#8212;Petr</p>]]></content:encoded></item><item><title><![CDATA[Surround with snippets in VS Code]]></title><description><![CDATA[Who doesn&#8217;t like code snippets?]]></description><link>https://devtips.stribny.name/p/surround-with-snippets-in-vs-code</link><guid isPermaLink="false">https://devtips.stribny.name/p/surround-with-snippets-in-vs-code</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Sat, 11 Oct 2025 16:29:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!gO-_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Who doesn&#8217;t like code snippets? They are a quick, reliable, and accessible way to type less code.</p><p>&#8220;Surround with snippet&#8221; are a special type of code snippet that operate on selections. You can use them for many language constructs that typically have some code &#8220;inside&#8221; them, e.g., if statements, try/catch blocks, and so on. Many of these things are also available as &#8220;normal&#8221; code snippets, but using Surround with snippets makes it easier to turn already existing code into something else.</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;af2799b7-6c67-4abc-8dc5-b64893616183&quot;,&quot;duration&quot;:null}"></div><p>Visual Studio Code has them built in, although they don&#8217;t have a keybinding by default. You can access them under the <em>Snippets: Surround with Snippet</em> command in the command palette (F1) whenever some code is selected (multiple selections are supported too). Once run, you can then select which snippet you want to use:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gO-_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gO-_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png 424w, https://substackcdn.com/image/fetch/$s_!gO-_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png 848w, https://substackcdn.com/image/fetch/$s_!gO-_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png 1272w, https://substackcdn.com/image/fetch/$s_!gO-_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gO-_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png" width="1348" height="911" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:911,&quot;width&quot;:1348,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69361,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/175886795?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gO-_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png 424w, https://substackcdn.com/image/fetch/$s_!gO-_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png 848w, https://substackcdn.com/image/fetch/$s_!gO-_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png 1272w, https://substackcdn.com/image/fetch/$s_!gO-_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f64946d-76c9-4806-aa77-6aa6350e011e_1348x911.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Alternatively, set <em>Editor &gt; Snippets &gt; Code Actions: Enabled</em> to true. VS Code will then offer these snippets as code actions (CTRL + . whenever some code is selected).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7aYF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7aYF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png 424w, https://substackcdn.com/image/fetch/$s_!7aYF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png 848w, https://substackcdn.com/image/fetch/$s_!7aYF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png 1272w, https://substackcdn.com/image/fetch/$s_!7aYF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7aYF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png" width="1212" height="733" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:733,&quot;width&quot;:1212,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:75294,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/175886795?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7aYF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png 424w, https://substackcdn.com/image/fetch/$s_!7aYF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png 848w, https://substackcdn.com/image/fetch/$s_!7aYF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png 1272w, https://substackcdn.com/image/fetch/$s_!7aYF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F975932f9-3b2b-49a6-8d2f-153b9bdfab3f_1212x733.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4NS8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4NS8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png 424w, https://substackcdn.com/image/fetch/$s_!4NS8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png 848w, https://substackcdn.com/image/fetch/$s_!4NS8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png 1272w, https://substackcdn.com/image/fetch/$s_!4NS8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4NS8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png" width="1212" height="785" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/da5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:785,&quot;width&quot;:1212,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:79202,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/175886795?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4NS8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png 424w, https://substackcdn.com/image/fetch/$s_!4NS8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png 848w, https://substackcdn.com/image/fetch/$s_!4NS8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png 1272w, https://substackcdn.com/image/fetch/$s_!4NS8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda5391d5-888f-4e97-bc77-883aa4f9e9c0_1212x785.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Surround with snippets are like other snippets in Visual Studio Code: some come built-in, some through extensions, and you can create your own. The concept itself is general&#8212;you can find &#8220;surround with&#8221; snippets in other editors or other extensions under different names.</p><p>My favorite variation is actually built into VS Code already: <em>Emmet: Wrap Abbreviation</em> command makes it convenient to restructure HTML code:</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;39c1d13f-0866-479a-959a-e2c8797d7447&quot;,&quot;duration&quot;:null}"></div><div><hr></div><p>And that&#8217;s it. Happy weekend coding.</p><p>&#8212;Petr</p>]]></content:encoded></item><item><title><![CDATA[Documenting supported environments]]></title><description><![CDATA[Applications and entire software systems don&#8217;t run in a vacuum; they run in environments consisting of compatible hardware and software.]]></description><link>https://devtips.stribny.name/p/documenting-supported-environments</link><guid isPermaLink="false">https://devtips.stribny.name/p/documenting-supported-environments</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Thu, 02 Oct 2025 13:01:58 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Y_7T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Y_7T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Y_7T!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Y_7T!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Y_7T!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Y_7T!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Y_7T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2822459,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/175089842?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Y_7T!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Y_7T!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Y_7T!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Y_7T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74e19743-f461-4239-a23f-72acdb8d0b19_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Applications and entire software systems don&#8217;t run in a vacuum; they run in environments consisting of compatible hardware and software. Such environments can encompass a wide range of elements, from infrastructure like databases and cloud services, platform requirements (e.g., browser versions and operating systems), hardware requirements (e.g., memory and CPU requirements), and even network components.</p><p>Being clear on what the compatible environments look like can help software teams, customers, and users throughout the development lifecycle (planning, development, testing, and production use) to:</p><ul><li><p>understand the project&#8217;s scope</p></li><li><p><a href="https://devtips.stribny.name/p/the-difference-between-estimates">estimate the effort</a> required for development and testing (as more compatible environments directly increase the effort)</p></li><li><p>set up development, staging, and production environments</p></li><li><p>estimate costs to develop and run the software</p></li><li><p>make a test plan</p></li><li><p>triage bugs</p></li><li><p>(customers) make purchasing decisions or formulate requirements</p></li><li><p>(users) run applications correctly</p></li><li><p>&#8230;and probably many other things.</p></li></ul><p>For practical documentation, I recommend separating compatible environments into three main groups:</p><ul><li><p><strong>Tested</strong>: environments that are or will be directly used for testing, or which developers use during development. (Almost) guaranteed to work properly.</p></li><li><p><strong>Supported</strong>: environments that you want to support but don&#8217;t have the resources to test as part of the development lifecycle. If an application doesn&#8217;t run correctly in a supported environment, it is a bug.</p></li><li><p><strong>Recommended</strong>: the optimal configuration of hardware and software for achieving peak performance, security, and stability<strong>.</strong></p></li></ul><p>The most important category is supported environments, because it ultimately determines what is a bug. This helps users to know whether to <a href="https://devtips.stribny.name/p/minimal-bug-report-template">file a bug report</a> or software teams with development planning and bug triage. A whole lot of bug reports can often be completely dismissed by just examining the user&#8217;s environment.</p><p>Sometimes it is beneficial to warn or restrict users when the environment is incompatible. For example, streaming services will restrict users, refusing to play content in unsupported browsers. Conversely, server-side software may simply log a warning upon detecting a minor environmental incompatibility.</p><p>Documenting supported environments is practically a must-have for any serious software that ends up in the hands of customers and users, including client applications that require browser and operating system compatibility and self-hosted server software.</p><p>Tested environments help with forming a test plan. Specifically, they drive the strategy for test automation and regression testing, clarifying which software and hardware combinations must be covered before a release or deployment. Tested environments also provide guarantees to users and customers in the &#8220;If you want the software to work, use this&#8221; style. Many software libraries are tested against a matrix of various dependencies, for example.</p><p>The scope and format of the documentation are going to be dependent on your context. You might prefer text and warnings for customers, for instance, while tested environments might be simply captured by your CI pipelines and automated development environments. Regardless of the format, being clear ensures that the development team, customers, and users are always on the same page.</p><div><hr></div><p>&#8212;Petr</p>]]></content:encoded></item><item><title><![CDATA[Programmatic terminal tabs and windows]]></title><description><![CDATA[Terminal emulators with tab support (opening multiple shell sessions at once) can often be controlled programmatically.]]></description><link>https://devtips.stribny.name/p/programmatic-terminal-tabs-and-windows</link><guid isPermaLink="false">https://devtips.stribny.name/p/programmatic-terminal-tabs-and-windows</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Fri, 26 Sep 2025 22:33:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ekol!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ekol!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ekol!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!ekol!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!ekol!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!ekol!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ekol!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2805164,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/174652036?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ekol!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!ekol!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!ekol!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!ekol!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F721bb5a2-dfcc-4e8e-bea4-93b593e7f53f_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Terminal emulators with tab support (opening multiple shell sessions at once) can often be controlled programmatically. Terminals that don&#8217;t might still offer split-screen or the ability to start a completely new terminal window.</p><p>The usefulness of this feature lies in the ability to accept a command that will be started in the new shell session. This is similar to using shell-based terminal multiplexers like <a href="https://github.com/tmux/tmux">tmux</a>. In both cases the idea is to conveniently start multiple or separate things that can be controlled independently.</p><div><hr></div><p>As an example, think about enhancing a project entry point that uses Docker Compose. By default, Docker Compose starts all containers, and the output from all services is displayed together in the same terminal window. However, with programmatic tabs, you could also create independent terminal tabs that attach to each container.</p><p>With tabs attached to the running processes, you can kill and restart things in the containers just by navigating to their tab and ending a process using classic CTRL+C or starting it again with shell command history&#8212;without the need to deal with the containers externally. In fact, this is how the default development entry point script works in Baserow:</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;591db922-7991-4ddc-bf2b-cc2680331e21&quot;,&quot;duration&quot;:null}"></div><div><hr></div><p>Because the tab control differs across terminals, I recommend using a program like <a href="https://www.npmjs.com/package/ttab">ttab</a> that can handle a variety of terminals, although for personal use cases it might be enough to write terminal-specific commands. ttab also supports opening things in new terminal windows and split-screen setups for compatible terminals.</p><div><hr></div><p>I believe that programmatic terminal multiplexing is great for improving local development experiences. What about you?</p><p>Have a nice weekend,</p><p>&#8212;Petr</p><p>(And check out my <a href="https://commandline.stribny.name/">Command Line Handbook</a> for more command-line stuff if you haven&#8217;t yet.)</p>]]></content:encoded></item><item><title><![CDATA[Navigating between symbol highlights in Visual Studio Code]]></title><description><![CDATA[Learning to navigate code efficiently is always a good idea.]]></description><link>https://devtips.stribny.name/p/navigating-between-symbol-highlights</link><guid isPermaLink="false">https://devtips.stribny.name/p/navigating-between-symbol-highlights</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Thu, 18 Sep 2025 13:48:39 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BRqX!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf3b0de4-0bcc-47b5-a5e3-99c1ca9ac52a_515x515.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Learning to navigate code efficiently is always a good idea. I already wrote about <a href="https://devtips.stribny.name/p/navigating-between-edits-in-vscode">navigating between edits</a>. Now, let&#8217;s see why you might want to navigate between symbol highlights and how to do that.</p><p>Whenever a cursor is placed at a recognized symbol, VS Code will highlight all the symbol occurrences in the opened file. That&#8217;s great for visually identifying all the places the symbol is used, but also for selection and navigation.</p><p>Visual Studio Code allows you to navigate between these highlights using the <em>Go to Next Symbol Highlight</em> (default <code>F7</code>) and <em>Go to Previous Symbol Highlight</em> (default <code>Shift + F7</code>) commands. </p><p>This feature is ideal for quick, focused navigation within a single file, without the need to use search or a more complex approach. You can use it for a lot of things:</p><ul><li><p>Going from where a symbol is defined or imported to where it is used</p></li><li><p>Jumping between the children of a parent class (as you will typically have the same symbol defining the inheritance)</p></li><li><p>Tracking and tracing the usage of a variable in a class, method, or function</p></li><li><p>Going between opening and closing tags in HTML or XML</p></li><li><p>Cycling through the locations of the same word in a text or Markdown document</p></li></ul><p>Let&#8217;s see it in action:</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;f5266168-2b60-46a3-a9fa-02d0c37984d7&quot;,&quot;duration&quot;:null}"></div><p>Note that when you place your cursor on a variable name (or another language construct), it will highlight all its occurrences within the same scope. On the other hand, placing the cursor in a string, comment, or text document will highlight all the word occurrences in the file, as there isn&#8217;t any scope to restrict it. </p><p>For example, if a function's documentation mentions the function's name, you can jump from that documentation to the function's definition. However, the reverse is not possible; you cannot jump from the function's definition back to the documentation, unless the text occurrence was highlighted first.</p><div><hr></div><p>&#8212;Petr</p>]]></content:encoded></item><item><title><![CDATA[How documentation can improve everything]]></title><description><![CDATA[Today, I want to discuss a big benefit of writing documentation that is often ignored: driving improvements to confusing and convoluted solutions.]]></description><link>https://devtips.stribny.name/p/how-documentation-can-improve-everything</link><guid isPermaLink="false">https://devtips.stribny.name/p/how-documentation-can-improve-everything</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Fri, 12 Sep 2025 12:50:57 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Rofs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Rofs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Rofs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Rofs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Rofs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Rofs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Rofs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/30775274-4633-4090-a132-3c305826ccc6_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2160975,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/144264143?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Rofs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Rofs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Rofs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Rofs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30775274-4633-4090-a132-3c305826ccc6_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Today, I want to discuss a big benefit of writing documentation that is often ignored: driving improvements to confusing and convoluted solutions.</p><p>And by documentation, I really mean all kinds of documentation you can find in software development:</p><ul><li><p>Source code documentation</p></li><li><p>API documentation</p></li><li><p>Design and architecture documentation</p></li><li><p>Process documentation</p></li><li><p>User-facing documentation</p></li><li><p>&#8230;</p></li></ul><p>When you try explaining something to someone else, the flaws and gaps become obvious:</p><ul><li><p>If you dislike explaining how the combination of five parameters works together in a function signature documentation, perhaps you are missing a better abstraction in the code to express the complexity.</p></li><li><p>When writing a tutorial on how to use your external API to achieve a common use case takes several API calls, maybe the right solution is to add a use-case-specific endpoint.</p></li><li><p>If the documentation for handling tickets is 10 pages long, perhaps the process should be simplified.</p></li><li><p>Describing how to run a development environment using three commands is not fun. Just make a better entry point to the project.</p></li></ul><p>All these examples show that it doesn&#8217;t matter what the documentation is for. The process of writing documentation can trigger a re-evaluation of the solution itself, creating a continuous feedback loop: Document &#8594; Identify problems &#8594; Improve.</p><p>The ultimate goal is a solution so well-designed that its documentation becomes minimal and more self-explanatory, but to achieve this, it's often necessary to document the initial, more complex version first.</p><div><hr></div><p>&#8212;Petr</p><p></p>]]></content:encoded></item><item><title><![CDATA[Underrated Quick Fix smart actions]]></title><description><![CDATA[While AI chats and agents are all the rage, I think GitHub Copilot&#8217;s smart actions in VS Code deserve more attention.]]></description><link>https://devtips.stribny.name/p/underrated-quick-fix-smart-actions</link><guid isPermaLink="false">https://devtips.stribny.name/p/underrated-quick-fix-smart-actions</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Fri, 05 Sep 2025 15:59:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ghrw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While AI chats and agents are all the rage, I think <a href="https://marketplace.visualstudio.com/items?itemName=GitHub.copilot">GitHub Copilot</a>&#8217;s <em>smart actions</em> in VS Code deserve more attention. Smart actions are little convenience tools sprinkled in various places in the IDE that invoke AI tasks directly.</p><p>A subset of the smart actions are integrated into the Visual Studio Code Quick Fix menu, which has been Visual Studio Code&#8217;s solution to invoke various refactoring tasks (like Extract method, Move symbol, &#8230;) based on the cursor position in the code. The best way to invoke it is with a keyboard shortcut (by default <code>Ctrl + .</code>) or by clicking on the lightbulb icon &#128161;.</p><p>Smart actions are helpful whenever we aim for AI-assisted development where writing code manually blends with targeted use of AI tools.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ghrw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ghrw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png 424w, https://substackcdn.com/image/fetch/$s_!ghrw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png 848w, https://substackcdn.com/image/fetch/$s_!ghrw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png 1272w, https://substackcdn.com/image/fetch/$s_!ghrw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ghrw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:45552,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/172868603?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ghrw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png 424w, https://substackcdn.com/image/fetch/$s_!ghrw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png 848w, https://substackcdn.com/image/fetch/$s_!ghrw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png 1272w, https://substackcdn.com/image/fetch/$s_!ghrw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae6aab4d-9338-4f60-986c-a1fbd8a72aa0_902x321.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Quick Fix menu offering both refactoring and smart actions.</figcaption></figure></div><p>Depending on the context, the Quick Fix menu will typically offer some combination of the following smart actions: Generate, Modify, Review, Generate documentation, Generate tests, Explain, and Fix.</p><p>Some actions show a prompt dialog first to provide instructions (Generate&#8230;), and some show the same prompt dialog after the action is done (further prompting after action was taken). In both cases you can choose the model to use, use voice commands, or invoke slash commands when it makes sense:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IlYE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IlYE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png 424w, https://substackcdn.com/image/fetch/$s_!IlYE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png 848w, https://substackcdn.com/image/fetch/$s_!IlYE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png 1272w, https://substackcdn.com/image/fetch/$s_!IlYE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IlYE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png" width="1420" height="533" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:533,&quot;width&quot;:1420,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:76106,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/172868603?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IlYE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png 424w, https://substackcdn.com/image/fetch/$s_!IlYE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png 848w, https://substackcdn.com/image/fetch/$s_!IlYE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png 1272w, https://substackcdn.com/image/fetch/$s_!IlYE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3765d16b-d06d-4a0e-b4cc-95476e8a1527_1420x533.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Generate</strong></p><p>Generate smart action is available on blank lines for generating new code. This action is the same as any other &#8220;generate code&#8221; approach, but with the advantage of placing the new code exactly when you want it. Things like writing a new method for a class, adding some logic to an existing function, and so on. Writing new code using the Generate action is faster than using agents for smaller blocks of code.</p><p><strong>Modify</strong></p><p>Modify smart action is displayed whenever code is selected, perfect for in-place modification and code rewrites. It is like &#8220;AI refactoring,&#8221; where you can ask for renames (e.g., converting between camelCase and snake_case), rewriting classes to functions and back, converting divs into semantic HTML structure, and so on.</p><p><strong>Review</strong></p><p>Review smart action instructs the GitHub Copilot to provide a code review when some code has been selected. However, the result is not just textual feedback, but rather a series of proposed enhancements that you can go through. You can accept or reject each of them separately.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MPZf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MPZf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png 424w, https://substackcdn.com/image/fetch/$s_!MPZf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png 848w, https://substackcdn.com/image/fetch/$s_!MPZf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png 1272w, https://substackcdn.com/image/fetch/$s_!MPZf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MPZf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png" width="1456" height="574" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:574,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:77604,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/172868603?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MPZf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png 424w, https://substackcdn.com/image/fetch/$s_!MPZf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png 848w, https://substackcdn.com/image/fetch/$s_!MPZf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png 1272w, https://substackcdn.com/image/fetch/$s_!MPZf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021f12af-8b4f-498a-86a8-d36c9be28ba1_1918x756.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>One interesting use case for Review smart action is to run it on previously generated code to see if the AI code itself can be improved.</p><p><strong>Generate documentation</strong></p><p>Generate documentation action appears when the cursor is placed at a symbol that is typically documented (think class and function names). You can easily add language-specific descriptions in the form of, e.g., JSDoc for JavaScript or Python&#8217;s docstrings. It is handy when you don&#8217;t remember all the syntax for documenting function parameters and other specifics.</p><p><strong>Generate tests</strong></p><p>Generate tests is displayed when the cursor is placed at symbols that are typically unit tested, like method and function names. It will create one or more tests without providing any description first. After the test code is generated, you will get the ability to further prompt the model for modifications.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7rdc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7rdc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png 424w, https://substackcdn.com/image/fetch/$s_!7rdc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png 848w, https://substackcdn.com/image/fetch/$s_!7rdc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png 1272w, https://substackcdn.com/image/fetch/$s_!7rdc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7rdc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png" width="1197" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1197,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:89262,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/172868603?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7rdc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png 424w, https://substackcdn.com/image/fetch/$s_!7rdc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png 848w, https://substackcdn.com/image/fetch/$s_!7rdc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png 1272w, https://substackcdn.com/image/fetch/$s_!7rdc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe782bfbc-f458-49b0-a00a-b2930db04d08_1197x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Explain</strong></p><p>With the Explain action, you can directly get a short summary of what certain code does or explore problems highlighted in the editor. I find it strange that the Explain action is not offered when any code is selected, as it only appears when selected code has a problem identified within or when the cursor is placed directly at some problematic code.</p><p>Anyways, you can invoke the Explain action with a small detour even if it is not offered in the Quick Fix menu. Use the slash command <code>/explain</code> in the Modify smart action text area instead:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nNAm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nNAm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png 424w, https://substackcdn.com/image/fetch/$s_!nNAm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png 848w, https://substackcdn.com/image/fetch/$s_!nNAm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png 1272w, https://substackcdn.com/image/fetch/$s_!nNAm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nNAm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png" width="1381" height="408" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:408,&quot;width&quot;:1381,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:71303,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/172868603?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nNAm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png 424w, https://substackcdn.com/image/fetch/$s_!nNAm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png 848w, https://substackcdn.com/image/fetch/$s_!nNAm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png 1272w, https://substackcdn.com/image/fetch/$s_!nNAm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b4dba5b-2c74-4ce6-a9cf-12551980dc0b_1381x408.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Fix</strong></p><p>Fix action is similar to the Explain action as they are both available for code with already identified problems. So to invoke it, you will need the editor to be aware of the problem first.</p><p>There is also the <em>Fix test failure</em> action that can be invoked from within test code that failed. Again, the editor needs to be aware of the problem, so such action will be available only when using the integrated test runner.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!l8Rm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!l8Rm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png 424w, https://substackcdn.com/image/fetch/$s_!l8Rm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png 848w, https://substackcdn.com/image/fetch/$s_!l8Rm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png 1272w, https://substackcdn.com/image/fetch/$s_!l8Rm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!l8Rm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png" width="963" height="396" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:396,&quot;width&quot;:963,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:64657,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/172868603?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!l8Rm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png 424w, https://substackcdn.com/image/fetch/$s_!l8Rm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png 848w, https://substackcdn.com/image/fetch/$s_!l8Rm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png 1272w, https://substackcdn.com/image/fetch/$s_!l8Rm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd921c27-e34b-45f2-9d8c-0c5159e7d24c_963x396.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p>I am quite happy with Quick Fix smart actions, as it provides &#8220;AI assistance&#8221; when writing code manually without the need to resort to more complicated AI tools.</p><p>What is your experience?</p><p>&#8212;Petr</p>]]></content:encoded></item><item><title><![CDATA[Getting notified from the command line]]></title><description><![CDATA[When executing long-running commands in the terminal, it is useful to get notified when they are done, instead of checking the terminal manually.]]></description><link>https://devtips.stribny.name/p/getting-notified-from-the-command</link><guid isPermaLink="false">https://devtips.stribny.name/p/getting-notified-from-the-command</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Thu, 28 Aug 2025 16:29:07 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!GiiD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GiiD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GiiD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png 424w, https://substackcdn.com/image/fetch/$s_!GiiD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png 848w, https://substackcdn.com/image/fetch/$s_!GiiD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png 1272w, https://substackcdn.com/image/fetch/$s_!GiiD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GiiD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png" width="800" height="533" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:533,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:498991,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/172179078?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GiiD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png 424w, https://substackcdn.com/image/fetch/$s_!GiiD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png 848w, https://substackcdn.com/image/fetch/$s_!GiiD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png 1272w, https://substackcdn.com/image/fetch/$s_!GiiD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81fdefc2-1d52-47fc-a9ba-f70dd260cb5f_800x533.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When executing long-running commands in the terminal, it is useful to get notified when they are done, instead of checking the terminal manually.</p><p>Personally, I am using the Linux <a href="https://www.mankier.com/1/notify-send">notify-send</a> utility program to produce toast-style system notifications. In my desktop environment, notify-send produces notifications at the right level of intrusiveness, and the notification stays in the notification center in case I want to get away from the computer entirely. But nothing stops you from being creative here; macOS users can leverage the native <a href="https://ss64.com/mac/say.html">say</a> command to get an audio notification, for instance.</p><p>The basic pattern involves putting the notify command of your choice after your long-running task (notice the semicolon):</p><pre><code>&gt; ./takes-long.sh ; notify-send "Task finished"</code></pre><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bISH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bISH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png 424w, https://substackcdn.com/image/fetch/$s_!bISH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png 848w, https://substackcdn.com/image/fetch/$s_!bISH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png 1272w, https://substackcdn.com/image/fetch/$s_!bISH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bISH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png" width="640" height="163" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:163,&quot;width&quot;:640,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:10077,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/172179078?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bISH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png 424w, https://substackcdn.com/image/fetch/$s_!bISH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png 848w, https://substackcdn.com/image/fetch/$s_!bISH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png 1272w, https://substackcdn.com/image/fetch/$s_!bISH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf37c4cc-9abb-4b11-b243-876f0c7ee21e_640x163.png 1456w" sizes="100vw"></picture><div></div></div></a></figure></div><p>If you want, you can get notified only on success, on error, or have a different message for success and error:</p><pre><code>&gt; ./takes-long.sh &amp;&amp; notify-send "ended with success"

&gt; ./takes-long.sh || notify-send "ended with error"

&gt; ./takes-long.sh &amp;&amp; notify-send "ended with success" || notify-send "ended in error"

&gt; if ./takes-long.sh; then notify-send "ended with success"; else notify-send "ended in error"; fi</code></pre><p>While not bulletproof, combining short-circuiting operators &amp;&amp; and || together will work as expected as long as the <code>notify-send</code> command works properly. This style is less verbose than the proper if-else structure shown in the last example.</p><p>I also like to alias notify-send to just <em>notify</em>. You might want to do something similar. You can find more about aliases and short-circuiting operators in my <a href="https://commandline.stribny.name/">Command Line Handbook</a>.</p><p>&#8212;Petr</p>]]></content:encoded></item><item><title><![CDATA[From best practices to sensible defaults]]></title><description><![CDATA[The tech industry is obsessed with &#8220;best practices.&#8221; People are constantly on the hunt for the latest and greatest processes, tools, and technologies.]]></description><link>https://devtips.stribny.name/p/from-best-practices-to-sensible-defaults</link><guid isPermaLink="false">https://devtips.stribny.name/p/from-best-practices-to-sensible-defaults</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Fri, 22 Aug 2025 10:30:52 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!JNAl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JNAl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JNAl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png 424w, https://substackcdn.com/image/fetch/$s_!JNAl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png 848w, https://substackcdn.com/image/fetch/$s_!JNAl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png 1272w, https://substackcdn.com/image/fetch/$s_!JNAl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JNAl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png" width="1024" height="559" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:559,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:861888,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/171633596?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!JNAl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png 424w, https://substackcdn.com/image/fetch/$s_!JNAl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png 848w, https://substackcdn.com/image/fetch/$s_!JNAl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png 1272w, https://substackcdn.com/image/fetch/$s_!JNAl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953e9515-a451-4bb2-be6f-46b691c46f62_1024x559.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The tech industry is obsessed with &#8220;best practices.&#8221; People are constantly on the hunt for the latest and greatest processes, tools, and technologies. And yet, despite all the preaching and debate (&#8230;and thousands of influencer videos), you will hardly find anything &#8220;the best.&#8221;</p><p>The problem is not just that &#8220;the best&#8221; is a moving target in the fast-paced technology world, but that it's always a context-specific decision.</p><p>What is best for a solo developer, agency, startup, or an established enterprise will be very different. The ideal technology for game development won't translate to better web development, and a developer who needs specific editor integrations won't benefit from using Vim if their plugin is only for VS Code.</p><p>The obsession with &#8220;best practices&#8221; prevents people from developing decisions for themselves. Because if something is the best, why would anyone do or use anything else?</p><p>Still, people seek guidance. There are too many decisions to make in any software development endeavor. Nobody should completely ignore the lessons of people that came before. But what we need is guidance that assists in decision-making, rather than replacing it entirely.</p><p>This is where the concept of a <strong>"sensible default"</strong> comes in. A sensible default is a flexible starting point&#8212;a well-reasoned choice that we can use if we don&#8217;t have a better idea yet.</p><p>I heard the term recently on the <a href="https://www.thoughtworks.com/insights/podcasts/technology-podcasts/sensible-defaults-way-think-technology-practices">Thoughtworks&#8217; podcast</a>. I really like it. And I think that every person, team, and company can develop their own &#8220;sensible defaults&#8221; that streamlines decision-making.</p><p>Ultimately, I&#8217;d like to see more of this in the industry. Let&#8217;s bring more nuance to our decisions, mention the context behind our choices, and acknowledge our blind spots. That, in my opinion, would be for the best.</p><div><hr></div><p>&#8212;Petr</p>]]></content:encoded></item><item><title><![CDATA[The use cases of global Git excludes file ]]></title><description><![CDATA[Git excludes file, often referred to as &#8220;global .gitignore,&#8221; is a file that defines global ignore rules for tracking files across all local Git repositories.]]></description><link>https://devtips.stribny.name/p/the-use-cases-of-global-git-excludes</link><guid isPermaLink="false">https://devtips.stribny.name/p/the-use-cases-of-global-git-excludes</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Tue, 12 Aug 2025 12:52:15 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Lm3r!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Lm3r!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Lm3r!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Lm3r!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Lm3r!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Lm3r!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Lm3r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2680538,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/170764913?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Lm3r!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Lm3r!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Lm3r!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Lm3r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d17b67-a431-4bb6-b5e5-3350f7ca7b16_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Git excludes file, often referred to as &#8220;global .gitignore,&#8221; is a file that defines global ignore rules for tracking files across all local Git repositories.</p><p>We can use it to add some extra files in the tracked folders to enhance our local experience without affecting other users:</p><ul><li><p><strong>Custom entry points</strong></p><ul><li><p>Using different tools to run things. For example, using <a href="https://github.com/casey/just">just files</a> instead of the default project&#8217;s task runner.</p></li><li><p>Configuring additional tasks for local workflow.</p></li></ul></li><li><p><strong>Custom environment</strong></p><ul><li><p>Adding a <a href="https://github.com/jdx/mise">mise.toml</a> file to automatically install correct runtime dependencies even if the rest of the team prefers other tools.</p></li><li><p>Avoiding the clutter of environment-specific files, like <code>.DS_Store</code> files on MacOS.</p></li></ul></li><li><p><strong>Custom editor configuration</strong></p><ul><li><p><code>.vscode/</code>, <code>.idea/</code>, and other editor-specific configs.</p></li></ul></li><li><p><strong>Personal documentation</strong></p><ul><li><p>Personal README and other doc files directly where you need them.</p></li></ul></li><li><p><strong>Custom tests and configuration</strong></p><ul><li><p>Working with custom and ad hoc tests by having our own test files. For example, using  *.http files with <a href="https://marketplace.visualstudio.com/items?itemName=humao.rest-client">REST Client</a> extension to test API endpoints during development.</p></li><li><p>Using custom test configuration for a test runner.</p></li></ul></li><li><p><strong>Temporary files and folders</strong></p><ul><li><p>Being able to store temporary exports for testing import/export functionality.</p></li><li><p>Storing uncommitted, personal test data, e.g., images, directly in the project folder.</p></li><li><p>Scratch files for custom scripts.</p></li></ul></li><li><p><strong>Sensitive files</strong></p><ul><li><p>Keys, passwords, and so on.</p></li></ul></li></ul><p>While having custom files in the project folder can be awesome, it is good to mention that Git ignore rules should still be placed in the project&#8217;s <code>.gitignore</code> file whenever it makes sense:</p><ul><li><p>When it is expected that developers will want to adjust some behavior, provide the proper rules right away. For example, a dev.sh script with entry points can automatically source untracked pre- and post- user scripts so that the behavior can be customized.</p></li><li><p>It is still better to make sure common OS and editor files are ignored in the project itself to prevent accidents.</p></li><li><p>The project&#8217;s .gitignore file should always cover any project files that affect everyone, including build, dependency, and log directories, generated docs or test output, cache files, and so on.</p></li></ul><p>When a project&#8217;s entry points or documentation are not sufficient, it almost always makes sense to try to improve the experience for everybody in the project first; custom files in the project folder are the last resort, in my opinion.</p><div><hr></div><p>The rules in Git excludes file follow the same concepts and syntax as standard <code>.gitignore</code> files, they just act as a &#8220;parent&#8221; for all of them. </p><p>The default location of the excludes file will depend on your environment. On Linux, it will be <em>~/.config/git/ignore</em>. It can also be set to a custom location:</p><pre><code># check if custom location of excludes file is set
git config --global core.excludesFile

# set custom excludes file location
git config --global core.excludesFile ~/.globalgitignore</code></pre><p>If you happen to use a custom location, I recommend not naming the file <em>.gitignore</em> if you want to keep it under version control. In any case, it is a good idea to <a href="https://devtips.stribny.name/p/managing-dotfiles-with-stow">track the file in your dotfiles directory</a>.</p><div><hr></div><p>Some useful things to know:</p><ul><li><p>If you happen to work in a Git repository and you want to commit an ignored file, you can always start tracking the file by invoking <code>git add</code> with <code>&#8212;force or -f</code> flag (<code>git add -f ignoredfile.txt</code>). This is useful for cases where you cannot or don&#8217;t want to modify the ignore rules for some reason. The file will be tracked from that point on in the repository despite the rules.</p></li><li><p>The use cases of the global Git excludes file can be similar to using repository-specific setting <code>.git/info/exclude</code> inside each Git repository. In both cases the ignore rules are personal and not shared with other users, but a big advantage of Git excludes file is the ability to be easily tracked in your own repository. <code>.git/info/exclude</code> could be useful for quick, ad hoc ignore rules.</p></li></ul><div><hr></div><p>And that&#8217;s it.</p><p>&#8212; Petr</p><p></p>]]></content:encoded></item><item><title><![CDATA[Visualize older and newer code with GitLens File Heatmap]]></title><description><![CDATA[Visual Studio Code already comes with plenty of Git-related features, but there are still some neat features hiding in various extensions like GitLens. One of my favorites from GitLens is File Heatmap, a tool to visually separate older and newer code lines for any Git-tracked file.]]></description><link>https://devtips.stribny.name/p/visualize-older-and-newer-code-with</link><guid isPermaLink="false">https://devtips.stribny.name/p/visualize-older-and-newer-code-with</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Fri, 01 Aug 2025 21:08:45 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!PoRK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Visual Studio Code already comes with plenty of Git-related features, but there are still some neat features hiding in various extensions like <a href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens">GitLens</a>. One of my favorites from GitLens is <em>File Heatmap</em>, a tool to visually separate older and newer code lines for any Git-tracked file.</p><p>This feature can be toggled when a file is open with the command <em>GitLens: Toggle File Heatmap</em> or by using the <em>File Annotations</em> menu:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6ym1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6ym1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png 424w, https://substackcdn.com/image/fetch/$s_!6ym1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png 848w, https://substackcdn.com/image/fetch/$s_!6ym1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png 1272w, https://substackcdn.com/image/fetch/$s_!6ym1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6ym1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png" width="1161" height="867" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:867,&quot;width&quot;:1161,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:192628,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/169881379?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6ym1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png 424w, https://substackcdn.com/image/fetch/$s_!6ym1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png 848w, https://substackcdn.com/image/fetch/$s_!6ym1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png 1272w, https://substackcdn.com/image/fetch/$s_!6ym1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f9323e2-17e1-401c-8676-2cdd4434d97d_1161x867.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When the heatmap is turned on, GitLens will add a color-coded bar with bright colors representing the newer lines of code and dim colors representing the older lines of code. The code itself is nicely dimmed according to its age as well:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PoRK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PoRK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png 424w, https://substackcdn.com/image/fetch/$s_!PoRK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png 848w, https://substackcdn.com/image/fetch/$s_!PoRK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png 1272w, https://substackcdn.com/image/fetch/$s_!PoRK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PoRK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png" width="1161" height="867" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:867,&quot;width&quot;:1161,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:168030,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/169881379?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PoRK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png 424w, https://substackcdn.com/image/fetch/$s_!PoRK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png 848w, https://substackcdn.com/image/fetch/$s_!PoRK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png 1272w, https://substackcdn.com/image/fetch/$s_!PoRK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ba533b-000e-4159-9dde-32ddeb9b8e0c_1161x867.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">GitLens highlights newer lines of code. Brightness adjusts dynamically based on the median age of all changes in the file.</figcaption></figure></div><p>As you can see, highlighting newer code makes it possible to quickly skim the file to get updated about the latest changes in general or to track down a recent bug.</p><p>The colors and the main threshold for the old and new age can be configured in the <a href="https://help.gitkraken.com/gitlens/settings/#gutter-heatmap-settings">settings</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TnY7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TnY7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png 424w, https://substackcdn.com/image/fetch/$s_!TnY7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png 848w, https://substackcdn.com/image/fetch/$s_!TnY7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png 1272w, https://substackcdn.com/image/fetch/$s_!TnY7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TnY7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png" width="1161" height="867" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:867,&quot;width&quot;:1161,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:117636,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/169881379?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TnY7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png 424w, https://substackcdn.com/image/fetch/$s_!TnY7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png 848w, https://substackcdn.com/image/fetch/$s_!TnY7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png 1272w, https://substackcdn.com/image/fetch/$s_!TnY7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff378cf0b-2082-4094-98e9-c5ebfc17e9fe_1161x867.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p>I hope you have a nice weekend and find the File Heatmap useful.</p><p>Petr</p>]]></content:encoded></item><item><title><![CDATA[Solving Git merge conflicts with three-way merge view]]></title><description><![CDATA[Merging two versions of the same file results in a conflict when the version control system cannot decide how to reconcile the two versions.]]></description><link>https://devtips.stribny.name/p/git-merge-conflicts-three-way-merge</link><guid isPermaLink="false">https://devtips.stribny.name/p/git-merge-conflicts-three-way-merge</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Wed, 23 Jul 2025 13:53:30 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!JpTm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Merging two versions of the same file results in a conflict when the version control system cannot decide how to reconcile the two versions. If Git cannot automatically perform a merge, it annotates the conflicting lines with special markers. By default, Git produces a <em>two-way merge </em>view of the files, directly comparing these two distinct versions:</p><pre><code>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD
Banana
=======
Apple
&gt;&gt;&gt;&gt;&gt;&gt;&gt; fruit-feature
Orange
Mango</code></pre><p>In the situation above, we can see that the <code>HEAD</code> contains the line &#8220;Banana&#8221; on the first line, while the branch <code>fruit-feature</code> contains &#8220;Apple&#8221; instead. </p><p>We can solve the conflict manually, without using any special merge tools, by removing the markers and keeping the code we want in any text editor.</p><p>The problem with merging, though, is almost never about the mechanics of the editing but rather about figuring out what the result should look like. Should we keep the banana, apple, both, or none?</p><p>One of the best ways to help us get the context of the merge is to use <em>three-way merge</em> view, because it will produce a base revision (nearest common parent) along the two versions:</p><pre><code>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD
Banana
||||||| c0e4389
Apple
Banana
=======
Apple
&gt;&gt;&gt;&gt;&gt;&gt;&gt; fruit-feature
Orange
Mango</code></pre><p>As we can see, the original parent <code>c0e4389</code> has both &#8220;Apple&#8221; and &#8220;Banana&#8221;, effectively showing that the branches were both deleting items and the conflict should be resolved by deleting both entries.</p><p>You can tell Git to use three-way merge by setting <code>merge.conflictstyle</code> to <code>diff3</code> in the Git configuration:</p><pre><code># in .gitconfig
[merge]                                                                                                                                                                                                                         
    conflictstyle = diff3</code></pre><p>Code editors can also color-code the lines when viewing conflicting files. Here is how it looks like in Visual Studio Code:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JpTm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JpTm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png 424w, https://substackcdn.com/image/fetch/$s_!JpTm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png 848w, https://substackcdn.com/image/fetch/$s_!JpTm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png 1272w, https://substackcdn.com/image/fetch/$s_!JpTm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JpTm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png" width="804" height="579" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:579,&quot;width&quot;:804,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:58070,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/169042440?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!JpTm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png 424w, https://substackcdn.com/image/fetch/$s_!JpTm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png 848w, https://substackcdn.com/image/fetch/$s_!JpTm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png 1272w, https://substackcdn.com/image/fetch/$s_!JpTm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65034f94-7976-4dc0-a9c3-a45e38d0f9e2_804x579.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Using three-way merge view has been the single biggest improvement in my ability to resolve conflicts. If you are not using it yet, take it for a spin.</p><div><hr></div><p>Petr</p>]]></content:encoded></item><item><title><![CDATA[Command Line Handbook]]></title><description><![CDATA[Today is a special edition of my Software Development Tips newsletter.]]></description><link>https://devtips.stribny.name/p/command-line-handbook</link><guid isPermaLink="false">https://devtips.stribny.name/p/command-line-handbook</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Thu, 29 May 2025 12:23:13 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!_HhG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today is a special edition of my Software Development Tips newsletter.</p><p>I just finished a major update to my Linux command line ebook and decided to make it available to a wider audience. So, until further notice, you can get my <a href="https://commandline.stribny.name/">Command Line Handbook</a> for any price you want.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_HhG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_HhG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!_HhG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!_HhG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!_HhG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_HhG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:124443,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://devtips.stribny.name/i/164717316?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_HhG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!_HhG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!_HhG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!_HhG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd89725ab-dbfb-4bd4-b0a9-48da11fe1b78_1200x630.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>If you didn&#8217;t know I attempted to make a modern command line introduction in PDF form or couldn&#8217;t justify paying the full price before, now is the time to get it.</p><p>I spent a lot of time making this book. It isn&#8217;t perfect, nothing is. But I sincerely believe it is useful. </p><p>Oh, and my favorite page is page 32.</p><p>Let me know what you think,</p><p>Petr</p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Navigating between edits in VSCode]]></title><description><![CDATA[Navigating code in programming editors typically involves operations based on text or code semantics.]]></description><link>https://devtips.stribny.name/p/navigating-between-edits-in-vscode</link><guid isPermaLink="false">https://devtips.stribny.name/p/navigating-between-edits-in-vscode</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Thu, 08 May 2025 04:58:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!y0gz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Navigating code in programming editors typically involves operations based on text or code semantics. However, we can also utilize source version control integrations to jump between in-progress edits.</p><p>In Visual Studio Code, the Git gutter (the colorized vertical line shown next to code) is not only a visual indicator of new and changed lines but also has an integrated &#8220;peek&#8221; dialog with additional features.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y0gz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y0gz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png 424w, https://substackcdn.com/image/fetch/$s_!y0gz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png 848w, https://substackcdn.com/image/fetch/$s_!y0gz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png 1272w, https://substackcdn.com/image/fetch/$s_!y0gz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y0gz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png" width="1110" height="826" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:826,&quot;width&quot;:1110,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:145633,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://efficientdev.substack.com/i/163108376?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!y0gz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png 424w, https://substackcdn.com/image/fetch/$s_!y0gz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png 848w, https://substackcdn.com/image/fetch/$s_!y0gz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png 1272w, https://substackcdn.com/image/fetch/$s_!y0gz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf2f3e8f-751e-4c7d-be82-2b44def16215_1110x826.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Git gutter with integrated peek dialog.</figcaption></figure></div><p>In particular, the <em>Show Next Change</em> (default <code>Alt + F3</code>) and <em>Show Previous Change</em> (<code>Shift + Alt + F3</code>) are helpful when making separate changes in long code files. The dialog can be opened by clicking on the Git gutters or by using the <em>Show Next Change</em> keyboard shortcut.</p><p>Because the actions to move between changes have keyboard bindings, we get fast navigation between edits in the open file. Pressing <code>Esc</code> will hide the dialog. The video demonstrates the process:</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;f1305ecb-035e-4500-afb1-abd0517dbe10&quot;,&quot;duration&quot;:null}"></div><div><hr></div><p>Have a nice rest of the week,</p><p>Petr</p>]]></content:encoded></item><item><title><![CDATA[Stacked pull requests with git rebase --update-refs]]></title><description><![CDATA[If you are using pull/merge requests as your code integration strategy, you will run into situations where multiple PRs will depend on one another.]]></description><link>https://devtips.stribny.name/p/stacked-pull-requests-with-git-rebase</link><guid isPermaLink="false">https://devtips.stribny.name/p/stacked-pull-requests-with-git-rebase</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Fri, 11 Apr 2025 06:18:01 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!pn_q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you are using pull/merge requests as your code integration strategy, you will run into situations where multiple PRs will depend on one another. This can happen when PRs grow too big and need to be split up, the PR depends on another feature branch, or anytime you want to submit a PR for review but still continue to work without waiting.</p><p>When you end up with multiple PRs that depend on one another, you get <em>stacked pull requests</em>. The image below illustrates the situation:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pn_q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pn_q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png 424w, https://substackcdn.com/image/fetch/$s_!pn_q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png 848w, https://substackcdn.com/image/fetch/$s_!pn_q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png 1272w, https://substackcdn.com/image/fetch/$s_!pn_q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pn_q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png" width="541" height="441" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:441,&quot;width&quot;:541,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:21289,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://efficientdev.substack.com/i/143436429?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pn_q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png 424w, https://substackcdn.com/image/fetch/$s_!pn_q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png 848w, https://substackcdn.com/image/fetch/$s_!pn_q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png 1272w, https://substackcdn.com/image/fetch/$s_!pn_q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7be8ba-123f-4803-b0de-d1537cfe78c7_541x441.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Creating stacked PRs is simple, and one has to only go and create new branches from the correct parent, so that <code>pr-1</code> would be based on <code>main</code>, <code>pr-2</code> would be based on <code>pr-1</code>, and so on.</p><p>The trouble comes when branches in such a chain start to change or open pull requests from these branches get merged. When this happens, some branches will be left in a bad state, pointing to the wrong commits. Our goal is to always have the correct commits pointing to each other so that the whole chain of commits makes sense.</p><p>There are multiple approaches to deal with updating the branches in the stack: updating each branch one by one or using <code>--update-refs</code> to do it in one go.</p><p>We can always update each branch individually&#8212;one by one&#8212;following the chain (e.g., by updating, <code>pr-2</code> before <code>pr-3</code> and <code>pr-3</code> before <code>pr-4</code>):</p><ul><li><p>Using `<code>git rebase &lt;parent&gt;</code>` when the parent branch introduces changes unrelated to commits in our branch. This is the simplest case, and it is the same `rebase` you would do without dealing with stacked branches.</p></li><li><p>Using `<code>git rebase --onto &lt;parent&gt; &lt;original parent&gt;</code>` in situations where the original parent branch gets merged. For example, if <code>pr-1</code> gets merged into <code>main</code>, we want to change our <code>pr-2</code> parent from <code>pr-1</code> to <code>main</code> (`<code>git rebase --onto main pr-1</code>`).</p></li></ul><p>(Please note that the examples above assume that you have currently checked out the branch you want to update.)</p><p>Depending on the situation, this might be a lot of work, since some manual steps are required to be done for each branch in the chain. I used both approaches in the past, and there is nothing wrong with them, especially if you manage one or two stacked branches.</p><p>The <code>rebase --onto</code> can also be useful when changing parents outside of stacked PRs (&#8220;take the last 2 commits and move them on top of feature-x&#8221; can be as simple as `<code>git rebase --onto feature-x HEAD~2</code>`).</p><p>Fortunately, Git makes it possible to directly update all branches in the stack by using <code>rebase --update-refs</code>. To use it:</p><ul><li><p>Check out the last branch in the chain, like <code>pr-3</code></p></li><li><p>Run <code>rebase main --update-refs</code></p></li></ul><p>If, for instance, the <code>pr-1</code> branch is already merged into <code>main</code>, Git recognizes that and updates all references from <code>pr-2</code> to <code>main</code> and <code>pr-3</code> to the new <code>pr-2</code>. This makes it seamless to keep your stacked PRs in sync, although these steps don&#8217;t cover pushing the updated branches upstream. You will still have to do that yourself.</p><div><hr></div><p>Happy stacking and have a nice weekend,</p><p>&#8212;Petr</p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[On using relative line numbers]]></title><description><![CDATA[Working with relative line numbers (as opposed to absolute line numbers) is a popular technique commonly used in command-line modal editors. The most common operations performed using relative line numbers are:]]></description><link>https://devtips.stribny.name/p/on-using-relative-line-numbers</link><guid isPermaLink="false">https://devtips.stribny.name/p/on-using-relative-line-numbers</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Tue, 25 Mar 2025 07:42:54 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!4nde!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Working with relative line numbers (as opposed to absolute line numbers) is a popular technique commonly used in <a href="https://efficientdev.substack.com/p/get-yourself-a-good-terminal-text">command-line modal editors</a>. The most common operations performed using relative line numbers are:</p><ul><li><p>Jumping to the relative line (e.g., moving the cursor 5 lines above or below in the editor).</p></li><li><p>Making a selection (e.g., select the 5 lines above or below the cursor).</p></li></ul><p>Visual Studio Code supports working with line numbers only in a limited way, but it can be extended to support these operations.</p><p>The first step is to display the relative line numbers in the editor, which provides context for selecting the lines later on. This can be achieved by setting <em>Editor: Line Numbers</em> to <em>relative</em> in VSCode Settings for <em>Text Editor</em> (you can just open settings and type &#8220;line numbers&#8221;):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!smBN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!smBN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png 424w, https://substackcdn.com/image/fetch/$s_!smBN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png 848w, https://substackcdn.com/image/fetch/$s_!smBN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png 1272w, https://substackcdn.com/image/fetch/$s_!smBN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!smBN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png" width="488" height="292" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/be4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:292,&quot;width&quot;:488,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:26691,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://efficientdev.substack.com/i/159810246?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!smBN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png 424w, https://substackcdn.com/image/fetch/$s_!smBN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png 848w, https://substackcdn.com/image/fetch/$s_!smBN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png 1272w, https://substackcdn.com/image/fetch/$s_!smBN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe4fb416-fc32-4970-b04c-2231108e5eb5_488x292.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>To have the same operations for jumping and selecting we will need to install an extension. I am using <a href="https://marketplace.visualstudio.com/items?itemName=EnkelDigital.relative-goto">relative goto</a> that provides exactly these two operations.</p><p>After installation I recommend to check or edit the keyboard shortcuts for these new operations. <code>Alt + G</code> (jump) and <code>Alt + S</code> (selection) should be the default:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4nde!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4nde!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png 424w, https://substackcdn.com/image/fetch/$s_!4nde!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png 848w, https://substackcdn.com/image/fetch/$s_!4nde!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png 1272w, https://substackcdn.com/image/fetch/$s_!4nde!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4nde!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png" width="1155" height="491" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:491,&quot;width&quot;:1155,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:65080,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://efficientdev.substack.com/i/159810246?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4nde!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png 424w, https://substackcdn.com/image/fetch/$s_!4nde!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png 848w, https://substackcdn.com/image/fetch/$s_!4nde!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png 1272w, https://substackcdn.com/image/fetch/$s_!4nde!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a604fe-dac2-4cb7-8807-6ac32cc416ac_1155x491.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Once done, these operations open a dialog where you can enter the desired relative line number, similar to <em>Go to Line</em> command for absolute numbers. Use minus (-) to select previous lines.</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;2d04bcb6-4f02-4ba8-9b86-becdb2220206&quot;,&quot;duration&quot;:null}"></div><p>And that&#8217;s it! I use relative goto occasionally, but I&#8217;d prefer if there was native support instead. Do you use relative line numbers? Do you use any other extension? Let me know.</p><p>&#8212; Petr</p><p></p>]]></content:encoded></item><item><title><![CDATA[Config aliases]]></title><description><![CDATA[Some of my most used shell aliases are aliases for editing configuration files.]]></description><link>https://devtips.stribny.name/p/config-aliases</link><guid isPermaLink="false">https://devtips.stribny.name/p/config-aliases</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Fri, 24 Jan 2025 22:20:56 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!z1t1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Some of my most used shell aliases are aliases for editing configuration files.</p><p>Many programs can be configured via text files, but it can be annoying to remember where to find a particular config file or to repeatedly jump to a configuration file when testing changes. Programs like shells themselves, editors, locally installed databases and other utilities need to be (re)configured from time to time. Fortunately, shell aliases can help.</p><p>Let&#8217;s say you want to be able to quickly configure a text editor like <a href="https://efficientdev.substack.com/p/get-yourself-a-good-terminal-text">Helix</a>. To do so you will need to know the path to the config file (but you only have to look it up once!) and decide which program to use for editing it. In my case, I use Helix (abbreviated as <code>hx</code>) and the default helix configuration file is at <code>~/.config/helix/config.toml.</code>Hence, the shell alias would look like this:</p><pre><code>alias hxconf="hx ~/.config/helix/config.toml"</code></pre><p>Such an alias will work in both Bash and Z shells (Zsh) and you only need to place it in the appropriate Bash/Zsh config file. For example, in the case of Z shell it is <code>~/.zshrc</code> on Linux. In fact, I suggest that you create a <code>zshconf</code> or <code>bashconf</code> alias while you are at it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!z1t1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!z1t1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png 424w, https://substackcdn.com/image/fetch/$s_!z1t1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png 848w, https://substackcdn.com/image/fetch/$s_!z1t1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png 1272w, https://substackcdn.com/image/fetch/$s_!z1t1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!z1t1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png" width="901" height="533" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c517113-a95c-44da-8339-d215d1436a4a_901x533.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:533,&quot;width&quot;:901,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:52730,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!z1t1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png 424w, https://substackcdn.com/image/fetch/$s_!z1t1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png 848w, https://substackcdn.com/image/fetch/$s_!z1t1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png 1272w, https://substackcdn.com/image/fetch/$s_!z1t1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c517113-a95c-44da-8339-d215d1436a4a_901x533.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Thanks to the alias, hxconf command will now open the Helix configuration in Helix.</figcaption></figure></div><p>It doesn&#8217;t matter whether you prefer to edit configuration files in the terminal, using VSCode, or need to open a different program altogether. In any case, opening the configuration directly from the command line is very convenient. I use config aliases for their ergonomics even though most configs I edit are in my separate <a href="https://efficientdev.substack.com/p/managing-dotfiles-with-stow">dotfiles directory</a>.</p><p>Some examples from my <code>~/.zshrc</code>:</p><pre><code>alias zshconf="hx ~/dotfiles/.zshrc"
alias starshipconf="hx ~/.config/starship.toml"
alias hxconf="hx ~/dotfiles/.config/helix/config.toml"
alias tmuxconf="hx ~/dotfiles/.tmux.conf"
alias gitconf="hx ~/dotfiles/.gitconfig"
alias pgservice="hx ~/dotfiles/.pg_service.conf"
alias pgpass="hx ~/dotfiles/.pgpass"
alias zellijconf="hx ~/dotfiles/.config/zellij/config.kdl"</code></pre><p>Instead of invoking the editing program directly, you can also use $EDITOR if you have it set to the correct program. It will make the configuration more flexible when changing the default editor (unless you need a specific program for a particular conf file). </p><div><hr></div><p>May your aliases serve you well,</p><p>Petr</p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Why 100% code coverage is not the goal]]></title><description><![CDATA[Code coverage is a metric of how many percent of lines of code were executed during a test run.]]></description><link>https://devtips.stribny.name/p/why-100-code-coverage-is-not-the</link><guid isPermaLink="false">https://devtips.stribny.name/p/why-100-code-coverage-is-not-the</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Sun, 15 Dec 2024 16:54:46 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BRqX!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf3b0de4-0bcc-47b5-a5e3-99c1ca9ac52a_515x515.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Code coverage is a metric of how many percent of lines of code were executed during a test run. Typically, code coverage would be collected during the execution of a complete test suite (running all the automated tests that were written) to get an overall number of lines of &#8220;tested&#8221; code in the codebase.</p><p>While code coverage is certainly a useful metric to discover untested code, simply aiming for 100% of lines of code covered by tests is not a worthy goal in a test strategy on its own.</p><p>To demonstrate that, let&#8217;s start with a simple code example <em>(it is valid Python but consider it to be just a pseudocode for the purpose of the demonstration to avoid discussing how such a function should be written in Python)</em>:</p><pre><code>def is_even(number):
    if number % 2 == 0:
        return True
    else:
        return False

def test_is_even():
    assert is_even(2) == True
    assert is_even(3) == False</code></pre><p>The code snippet is a function that should return True or False if the provided number is even or not, followed by a test for said function. After the test is executed the test runner will report 100% code coverage because all lines of code were touched during the test run:</p><pre><code>---------- coverage -----------
Name               Stmts   Miss  Cover
--------------------------------------
test_coverage.py       7      0   100%
--------------------------------------
TOTAL                  7      0   100%</code></pre><p>Unfortunately, 100% test coverage didn&#8217;t help us make sure our code or the tests were any good. The test is not testing whether the function returns correct results for all numbers nor it is testing if the function works with different data types or null values. And because the test doesn&#8217;t test things correctly, the function under test might be all wrong too.</p><p>There are other situations where the code coverage lies to us a little bit. For instance, a valid code path can be completely missed because multiple tests touch all lines of code, but some specific lines of code are not touched in the right order - missing an edge case.</p><p>We might also miss the forest for the trees with the focus on full code coverage. Even if the code and tests are correct from a code perspective, code coverage will never tell you if the program does what it should, based on functional and other requirements.</p><div><hr></div><p>All in all, code coverage is a useful tool to uncover untested code (for instance, during a code review), but it doesn&#8217;t make any real guarantees about the tests and, therefore, the code under test as well. That&#8217;s why aiming for 100% code coverage might not be worth it: there are probably other things to prioritize over it.</p><div><hr></div><p>Have a nice rest of the weekend,</p><p>Petr</p>]]></content:encoded></item><item><title><![CDATA[Terminal as an open editor in VSCode]]></title><description><![CDATA[There are many great terminal applications, but sometimes it is more convenient to use the Visual Studio Code&#8217;s integrated terminal.]]></description><link>https://devtips.stribny.name/p/terminal-as-an-open-editor-in-vscode</link><guid isPermaLink="false">https://devtips.stribny.name/p/terminal-as-an-open-editor-in-vscode</guid><dc:creator><![CDATA[Petr Stribny]]></dc:creator><pubDate>Sat, 28 Sep 2024 11:30:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ADq6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are many great terminal applications, but sometimes it is more convenient to use the Visual Studio Code&#8217;s integrated terminal. The integrated terminal is improving over time and already has some convenient features.</p><p>Today, we will explore the ability to work with a terminal the same way as we would with an open file: by using it as an open editor, aka a tab:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ADq6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ADq6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png 424w, https://substackcdn.com/image/fetch/$s_!ADq6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png 848w, https://substackcdn.com/image/fetch/$s_!ADq6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png 1272w, https://substackcdn.com/image/fetch/$s_!ADq6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ADq6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png" width="1209" height="766" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:766,&quot;width&quot;:1209,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:180982,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ADq6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png 424w, https://substackcdn.com/image/fetch/$s_!ADq6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png 848w, https://substackcdn.com/image/fetch/$s_!ADq6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png 1272w, https://substackcdn.com/image/fetch/$s_!ADq6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01cebfe6-1cc6-41b4-8327-04bfe78ac768_1209x766.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Multiple terminals opened as open editors in VSCode</figcaption></figure></div><p>By default, the integrated terminal is housed in a separate panel that can be opened with the command called <em>View: Toggle Terminal </em>(shortcut <code>Ctrl + `</code>). This allows you to use the terminal on the side (with the panel positioned to the top, bottom, left, or right of the editor).</p><p>There are, however, some advantages to using the terminal as an open editor. The first one is that it makes it easy to cycle through one or multiple terminals easily in the same way as we would with open files (and together with the open files). The second advantage is that it offers a little more space to see the output without the need to keep the panel maximized for other tasks.</p><p>Opening a new terminal as an open editor can be done with the command <em>Terminal: New Terminal in Editor Area</em> or its variation that can open the editor on the side of the current file.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xJ4h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xJ4h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png 424w, https://substackcdn.com/image/fetch/$s_!xJ4h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png 848w, https://substackcdn.com/image/fetch/$s_!xJ4h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png 1272w, https://substackcdn.com/image/fetch/$s_!xJ4h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xJ4h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png" width="721" height="132" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:132,&quot;width&quot;:721,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:18342,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xJ4h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png 424w, https://substackcdn.com/image/fetch/$s_!xJ4h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png 848w, https://substackcdn.com/image/fetch/$s_!xJ4h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png 1272w, https://substackcdn.com/image/fetch/$s_!xJ4h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ef33eaa-0317-4dfe-9104-bac7b1bcb39a_721x132.png 1456w" sizes="100vw"></picture><div></div></div></a></figure></div><p>We can also make this style the default by setting <em>Terminal &gt; Integrated &gt; Default Location</em> to <em>editor</em>. With this setting, a new terminal can be opened with the <em>Terminal: Create New Terminal</em> command directly (shortcut Ctrl + Shift + `).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yCL6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yCL6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png 424w, https://substackcdn.com/image/fetch/$s_!yCL6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png 848w, https://substackcdn.com/image/fetch/$s_!yCL6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png 1272w, https://substackcdn.com/image/fetch/$s_!yCL6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yCL6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png" width="1237" height="617" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:617,&quot;width&quot;:1237,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:66502,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yCL6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png 424w, https://substackcdn.com/image/fetch/$s_!yCL6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png 848w, https://substackcdn.com/image/fetch/$s_!yCL6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png 1272w, https://substackcdn.com/image/fetch/$s_!yCL6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faed4e9c3-a446-46d2-bc9b-e515052b5e89_1237x617.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><p>Have a nice weekend,</p><p>Petr</p>]]></content:encoded></item></channel></rss>