runrunrun v0.3.0: I would use that

Another week, another release, runrunrun v0.3.0 is here. This release adds all the features I actually needed to start using this project myself on a daily basis.

What’s New

Fallback: The new -f/--fallback option (or RRR_FALLBACK=true) enables automatic fallback to previous matching rules when commands fail. This is useful when some commands aren’t found on the system:

https://* lynx
https://* chromium
https://* firefox

With fallback enabled, rrr -f https://example.com will try firefox first, then chromium, then lynx until one succeeds.

Alias redefinition: Redefining an alias now updates all rules using it, including previous ones:

[video] vlc
*.mkv [video]
*.mp4 [video]

# Now .mkv and .mp4 both use mplayer
[video] mplayer
*.avi [video]

Fix in desktop file support: Added support for more format specifiers (%f, %F, %u, %U) in desktop files (previously we only supported %U).

As always, feedback and contributions are welcome!


runrunrun is available at https://github.com/gawen947/runrunrun

runrunrun v0.2.0: desktop file import and more

Just one week after the initial release, here comes runrunrun v0.2.0 with a key feature from the roadmap: desktop file import.

What’s New

Desktop File Import: The :import directive can now read .desktop files and automatically generate rules from their MIME types:

:import /usr/local/share/applications/gimp.desktop
:import /usr/share/applications

This extracts the Exec and MimeTypes attributes, infers file extensions, and creates the appropriate glob patterns automatically. It’s a great bridge for migrating from existing desktop configurations.

Path Expansion: Configuration files now support tilde (~) and environment variable expansion:

:include ~/.config/rrr/work.conf
:include ~/$DOTFILES/rrr/common.conf

Include Loop Protection: Fixed a bug where circular includes would cause infinite loops. Now if a file has already been included, it’s simply skipped.

Performance: The config parser now only loads rules for the requested profile, improving startup time for large configurations.

Getting Started with Import

If you want to import your existing desktop file associations:

# Import a specific application
:import /usr/share/applications/firefox.desktop

# Import everything
:import /usr/share/applications
:import ~/.local/share/applications

Desktop files without Exec or MimeTypes are silently skipped, so you can safely import entire directories.

Next Steps

With desktop file import now available, migrating from traditional file association systems is much easier. As always, feedback and contributions are welcome!


runrunrun is available at https://github.com/gawen947/runrunrun

runrunrun v0.1.0 (first release)

I’m happy to announce the first release of runrunrun (v0.1.0), a new file and URL opener that runs the right thing—no surprises, no guesswork.

The Problem It Solves

If you’ve ever clicked on a text file only to have it open in Wine’s Notepad, or watched your carefully configured file associations get overridden by yet another desktop environment, you’ll understand the frustration. Every time I need to configure file associations with xdg-open and its cousins, something isn’t quite right.

Traditional desktop openers work by making assumptions—and 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 .desktop files, and make debugging file associations unnecessarily complex.

The goal of runrunrun is simple: make opening files and URL schemes straightforward and consistent.

What Makes runrunrun Different

runrunrun (or rrr for short) takes a radically simple approach: explicit configuration through pattern matching. No MIME type cascades, no desktop file archaeology—just straightforward rules that you control.

Here’s what opening a PDF looks like in your config:

*.pdf    qpdf

That’s it. When you run rrr document.pdf, it opens in qpdf. No surprises.

Core Features in v0.1.0

Simple Pattern Matching: Define what opens what using glob patterns for files and URLs:

*.jpg        feh
https://*    firefox
mailto:*     thunderbird

Predictable Overrides: Later rules win, making customization straightforward:

*.txt    mousepad
*.txt    vim    # This one wins

Regex Support with Capture Groups: For more advanced matching, use regex patterns (prefixed with ~) that can even extract and reuse parts of the match:

~^IMG_[0-9]+\.png$  darktable
~mailto:([^?]+)\?subject=([^&]+)  "true %s; thunderbird --compose \"to=%1,subject=%2\""

Profiles for Different Contexts: Switch between configurations easily:

:profile work
https://*    firefox-work-profile

:profile personal
https://*    brave

Terminal-Friendly: Unlike desktop-centric tools, rrr works just as well in terminal environments as it does on a full desktop, making it suitable for servers and minimal setups.

Transparent Operation: Query mode (rrr -q file.ext) shows you exactly what would run, and dry-run mode (rrr -n) lets you test configurations safely.

Getting Started

The project is written in Rust and available on GitHub. Configuration lives in simple text files at /etc/rrr.conf or ~/.config/rrr.conf.

What’s Next

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 .desktop files for those who want a migration path from their current setup.

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.

If you’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!


runrunrun is available at https://github.com/gawen947/runrunrun

Disable RustAnalyzer warnings

Currently, I mainly use Neovim to code in Rust (and pretty much any other language). The problem is that when you start a new Rust project and begin creating structs and functions all over the place, you get flooded with warnings about “unused this” and “unused that”.

Maybe many of you probably already know this, but a quick trick to avoid those warnings is to simply run:
export RUSTFLAGS="-Awarnings".

This will disable all warnings, but it can be very convenient during early development.

Avoid rebuilding rust for FreeBSD ports

Today I tried to rebuild a rust-based port on FreeBSD. It tried to build lang/rust from scratch even though it was already installed. The problem was that the latest binary package for rust was 1.86.0 and the latest version in the ports was 1.87.0. Digging in /usr/ports/Mk/Uses/cargo.mk there is:

CARGO_BUILDDEP?=··yes
.  if ${CARGO_BUILDDEP:tl} == "yes"
BUILD_DEPENDS+=·${RUST_DEFAULT}>=1.87.0:lang/${RUST_DEFAULT}
.  elif ${CARGO_BUILDDEP:tl} == "any-version"
BUILD_DEPENDS+=·${RUST_DEFAULT}>=0:lang/${RUST_DEFAULT}
.  endif

That’s the bit actually enforcing the build dependency. But as you can see, it’s easy to bypass this dependency with export CARGO_BUILDDEP=no. Just ensure that you have rust installed either with rustup or from the packages.