{"id":2812,"date":"2026-01-05T14:33:38","date_gmt":"2026-01-05T14:33:38","guid":{"rendered":"https:\/\/hauweele.net\/~gawen\/blog\/?p=2812"},"modified":"2026-01-05T14:33:38","modified_gmt":"2026-01-05T14:33:38","slug":"runrunrun-v0-1-0-first-release","status":"publish","type":"post","link":"https:\/\/hauweele.net\/~gawen\/blog\/?p=2812","title":{"rendered":"runrunrun v0.1.0 (first release)"},"content":{"rendered":"<p>I&#8217;m happy to announce the first release of <a href=\"https:\/\/github.com\/gawen947\/runrunrun\">runrunrun<\/a> (v0.1.0), a new file and URL opener that runs the right thing\u2014no surprises, no guesswork.<\/p>\n<h2>The Problem It Solves<\/h2>\n<p>If you&#8217;ve ever clicked on a text file only to have it open in Wine&#8217;s Notepad, or watched your carefully configured file associations get overridden by yet another desktop environment, you&#8217;ll understand the frustration. Every time I need to configure file associations with <code>xdg-open<\/code> and its cousins, something isn&#8217;t quite right.<\/p>\n<p>Traditional desktop openers work by making assumptions\u2014and that might be exactly what some users want. But for those who prefer explicit control, the current tools fall short. They guess your preferred browser based on your desktop environment, scatter configuration across countless <code>.desktop<\/code> files, and make debugging file associations unnecessarily complex.<\/p>\n<p>The goal of <code>runrunrun<\/code> is simple: make opening files and URL schemes straightforward and consistent.<\/p>\n<h2>What Makes runrunrun Different<\/h2>\n<p><code>runrunrun<\/code> (or <code>rrr<\/code> for short) takes a radically simple approach: explicit configuration through pattern matching. No MIME type cascades, no desktop file archaeology\u2014just straightforward rules that you control.<\/p>\n<p>Here&#8217;s what opening a PDF looks like in your config:<\/p>\n<pre><code>*.pdf    qpdf<\/code><\/pre>\n<p>That&#8217;s it. When you run <code>rrr document.pdf<\/code>, it opens in qpdf. No surprises.<\/p>\n<h2>Core Features in v0.1.0<\/h2>\n<p><strong>Simple Pattern Matching<\/strong>: Define what opens what using glob patterns for files and URLs:<\/p>\n<pre><code>*.jpg        feh\r\nhttps:\/\/*    firefox\r\nmailto:*     thunderbird<\/code><\/pre>\n<p><strong>Predictable Overrides<\/strong>: Later rules win, making customization straightforward:<\/p>\n<pre><code>*.txt    mousepad\r\n*.txt    vim    # This one wins<\/code><\/pre>\n<p><strong>Regex Support with Capture Groups<\/strong>: For more advanced matching, use regex patterns (prefixed with <code>~<\/code>) that can even extract and reuse parts of the match:<\/p>\n<pre><code>~^IMG_[0-9]+\\.png$  darktable\r\n~mailto:([^?]+)\\?subject=([^&]+)  \"true %s; thunderbird --compose \\\"to=%1,subject=%2\\\"\"<\/code><\/pre>\n<p><strong>Profiles for Different Contexts<\/strong>: Switch between configurations easily:<\/p>\n<pre><code>:profile work\r\nhttps:\/\/*    firefox-work-profile\r\n\r\n:profile personal\r\nhttps:\/\/*    brave<\/code><\/pre>\n<p><strong>Terminal-Friendly<\/strong>: Unlike desktop-centric tools, <code>rrr<\/code> works just as well in terminal environments as it does on a full desktop, making it suitable for servers and minimal setups.<\/p>\n<p><strong>Transparent Operation<\/strong>: Query mode (<code>rrr -q file.ext<\/code>) shows you exactly what would run, and dry-run mode (<code>rrr -n<\/code>) lets you test configurations safely.<\/p>\n<h2>Getting Started<\/h2>\n<p>The project is written in Rust and available on <a href=\"https:\/\/github.com\/gawen947\/runrunrun\">GitHub<\/a>. Configuration lives in simple text files at <code>\/etc\/rrr.conf<\/code> or <code>~\/.config\/rrr.conf<\/code>.<\/p>\n<h2>What&#8217;s Next<\/h2>\n<p>This first release includes the core functionality along with regex patterns and aliases for common applications. Future versions will add the ability to import existing <code>.desktop<\/code> files for those who want a migration path from their current setup.<\/p>\n<p>As with any first release, there are likely bugs to catch and behaviors that might need adjustment. Your feedback will help shape the direction of future releases.<\/p>\n<p>If you&#8217;re tired of fighting with file associations and want something that just works the way you configure it, give runrunrun a try. Your feedback and contributions are welcome!<\/p>\n<hr \/>\n<p><em>runrunrun is available at <a href=\"https:\/\/github.com\/gawen947\/runrunrun\">https:\/\/github.com\/gawen947\/runrunrun<\/a><\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m happy to announce the first release of runrunrun (v0.1.0), a new file and URL opener that runs the right thing\u2014no surprises, no guesswork. The Problem It Solves If you&#8217;ve ever clicked on a text file only to have it &hellip; <a href=\"https:\/\/hauweele.net\/~gawen\/blog\/?p=2812\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1194],"tags":[285,1200,678,1197,1196,1171,1195,1198,1199],"class_list":["post-2812","post","type-post","status-publish","format-standard","hentry","category-software","tag-desktop","tag-open","tag-release","tag-rrr","tag-runrunrun","tag-rust","tag-software","tag-v0-1-0","tag-xdg-open"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2812","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2812"}],"version-history":[{"count":0,"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2812\/revisions"}],"wp:attachment":[{"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2812"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2812"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hauweele.net\/~gawen\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2812"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}