Skip to content

mihailfox/helix-url-handler

Repository files navigation

Helix URL Handler

This project packages a small helper that registers the helix:// URL scheme with the Helix terminal editor. Installing the handler lets links open directly in Helix from browsers, terminals, or other applications that support custom URL handlers.

Table of contents

Supported URL formats

  • Structured query form – helix://open?file=src/main.rs&line=12&col=4
    • Parsed into <file>:<line>:<col> so Helix jumps straight to the location.
  • Shorthand form – helix://path/to/file%20name.rs
    • Decoded into a plain path and forwarded to Helix unchanged (e.g. helix://path/file%20name.rs:10:2 opens path/file name.rs at 10:2).

Examples

Input Result
helix://open?file=src/lib.rs&line=42 Opens src/lib.rs at line 42.
helix://open?file=src/lib.rs&line=42&column=8 Accepts col or column query parameters for column hints.
helix://~/notes/today.md Expands to the literal path ~/notes/today.md (no shell expansion).
helix://projects/demo%20app/main.py:15 Decodes URL-escaped characters and honors trailing :line[:col].
file:///home/alex/project/todo.txt Treated like a file URL and forwarded without the file:// prefix.
plain.txt Non-URL arguments pass through untouched; mixed invocations still work.

What gets installed

  • A managed Desktop Entry (helix-url-handler.desktop) marking Helix as the handler for the helix:// scheme.
  • An hx-url wrapper script that decodes Helix URLs and forwards them to the hx (or helix) binary with the appropriate file, line, and column arguments.

Both artifacts are created either in the current user’s home directory or system-wide, depending on the chosen scope.

Prerequisites

The installation script requires a POSIX environment with the following commands available:

  • gio (usually in libglib2.0-bin or glib2)
  • xdg-mime (part of xdg-utils)
  • update-desktop-database (from desktop-file-utils)
  • install, sed, grep (coreutils/GNU tools)
Distribution Install command
Debian / Ubuntu sudo apt install libglib2.0-bin xdg-utils desktop-file-utils
Fedora sudo dnf install glib2 xdg-utils desktop-file-utils

Make sure the hx (or helix) binary is on your PATH or pass --hx-bin /path/to/hx during installation.

Quick start

  1. Install for the current user (default scope):

    ./src/helix-url-handler.sh --install
  2. Install system-wide (requires root):

    sudo ./src/helix-url-handler.sh --install --scope system --visible

Prebuilt packages

GitHub releases publish ready-to-install bundles. Pick the artifact that fits your environment:

Artifact Install command
Portable tarball (helix-url-handler-<version>.tar.gz) tar -xf helix-url-handler-<version>.tar.gz && ./helix-url-handler/helix-url-handler.sh --install
Debian / Ubuntu (helix-url-handler_<version>_all.deb) sudo dpkg -i helix-url-handler_<version>_all.deb
Fedora / RHEL (helix-url-handler-<version>-1.noarch.rpm) sudo rpm -i helix-url-handler-<version>-1.noarch.rpm

All packages install the tool under /usr/lib/helix-url-handler and expose a helix-url-handler binary on your PATH. After installation, run helix-url-handler --install (or --uninstall) just like the source checkout. Each release also ships a SHASUMS256.txt file so you can verify downloads.

The DEB declares libglib2.0-bin, xdg-utils, and desktop-file-utils alongside bash; the RPM pulls the equivalent glib2, xdg-utils, and desktop-file-utils packages. Your package manager resolves these automatically.

Prefer building locally? Use make dist VERSION=<x.y.z> to generate every package, or make dist-<tgz|deb|rpm> VERSION=<x.y.z> to build a single format. Need a CI dry run? Trigger the Release workflow manually, deselect publish_release, and tick only the artifact formats you care about.

Useful flags

  • --visible – show the handler in graphical launchers.
  • --takeover – back up and replace existing handler files that are not managed by this tool.
  • --allow-missing-hx – allow system-scope installs even if hx is not yet available.
  • --hx-bin /custom/hx – specify where the Helix binary lives (useful in non-standard setups).
  • --user-home DIR – override the target home when running as root with --scope user.

Uninstall

./src/helix-url-handler.sh --uninstall

Add --scope system when removing a system-wide install, and optionally --keep-hx-url to retain the URL wrapper script.

Uninstalling removes the .desktop launcher, the optional hx-url wrapper (unless kept), and scrubs helix-url-handler.desktop entries from mimeapps.list so the helix:// scheme returns to its previous handler.

Running in the dev container

The repo ships a single helper entry point at scripts/devcontainer/launcher.sh that wraps every host-side workflow:

# Launch VS Code and attach a shell once the workspace is ready
scripts/devcontainer/launcher.sh vscode

# Attach a TUI session (defaults to helix) inside the running devcontainer
scripts/devcontainer/launcher.sh tui --command hx

# Run the devcontainer CLI within the lightweight helper image
scripts/devcontainer/launcher.sh helper -- up --workspace-folder /workspaces/helix-url-handler

The helper keeps the previous behaviour of detecting an available terminal before spawning docker exec, waits for the container to come online, and automatically forwards any ${localEnv:...} variables referenced by .devcontainer/devcontainer.json when invoking the CLI wrapper.

If you prefer Make targets, the default make devcontainer now shells out to the same launcher. Override the mode at call time to jump straight into a TUI session:

make devcontainer DEVCONTAINER_MODE=tui DEVCONTAINER_ARGS="--command hx"

On first boot the devcontainer provisioning performs:

  • Starts an explainshell stack on the host network:
    • Launches explainshell_mongodb (MongoDB 7) and explainshell_app containers.
    • Downloads the official DB dump and restores it in the background.
    • Containers are configured with --restart unless-stopped.
  • Installs the codex CLI into ~/.local/bin/codex and marks it executable.
  • Upgrades global npm and installs common CLI tools:
    • ripgrep, fd, lsd, bat, git-delta, and bash-language-server.

You can access explainshell at: http://localhost:5000.

Host file mounts

Tip: Run scripts/devcontainer/launcher.sh vscode from the repository root to launch VS Code, wait for the container, and drop into a shell automatically.

The devcontainer binds host files into the container to persist local state across rebuilds and reuse your Git identity:

// .devcontainer/devcontainer.json
{
  "mounts": [
    "source=${localEnv:HOME}/.codex,target=/home/node/.codex,type=bind,consistency=cached",
    "source=${localEnv:HOME}/.bash_history,target=/home/node/.bash_history,type=bind,consistency=cached",
    "source=${localEnv:HOME}/.gitconfig,target=/home/node/.gitconfig,type=bind,consistency=cached",
    "source=${localEnv:HOME}/.git-credentials,target=/home/node/.git-credentials,type=bind,consistency=cached"
  ]
}

Note: If any of the host paths do not exist, create an empty file or remove the corresponding entry before rebuilding to avoid mount warnings.

Requirements

  • Docker must be available on the host for the explainshell containers.
  • Optionally export GH_PAT (also used as GITHUB_TOKEN) in your local environment for authenticated GitHub operations; these are forwarded into the container by devcontainer.json.

Tests

A basic smoke-test suite verifies the hx-url wrapper’s parsing logic and the installer’s ability to register the handler in an isolated environment.

make check

make check runs shellcheck across every shell script and executes ./tests/smoke-tests.sh, which creates temporary directories and stubs desktop/xdg commands so it is safe outside a graphical session. You can launch the suite directly with ./tests/smoke-tests.sh if you prefer.

Package end-to-end smoke tests

To exercise the platform packages in clean environments, use the Docker-backed harness:

# Run the full matrix (Ubuntu 24.04, Debian 12, Fedora 42, Rocky Linux 9)
scripts/e2e/package-test.sh

# Target a single distribution
scripts/e2e/package-test.sh --distro fedora

The script builds ephemeral containers, installs Helix (default HELIX_VERSION=25.07.1), installs the requested package from dist/, and asserts that the installed hx-url wrapper invokes Helix with the expected arguments (including exercising xdg-open). Docker must be available locally.

The Makefile wraps these flows:

# Build every package format for VERSION and run the full matrix
make test-packages VERSION=0.1.0

# Target a specific distro (still requires VERSION to build packages)
make test-packages-fedora VERSION=0.1.0

# Remove generated artifacts and labeled test containers/images (requires CONFIRM=1)
make clean-packages CONFIRM=1

Each make test-packages* invocation depends on make dist VERSION=…, so ensure the version matches the artifacts you intend to validate.

Contributing

See CONTRIBUTING.md for the branching strategy, development workflow, and release process.

License

This project is free software licensed under the GNU General Public License v3.0 or later.