# How to Add Custom File Open Commands by Extension Using `open_with` in Superfile

> Learn to add custom file open commands by extension using open_with in Superfile. Map extensions in superfile.toml and open files with your preferred program instantly.

- Repository: [Yorukot/superfile](https://github.com/yorukot/superfile)
- Tags: how-to-guide
- Published: 2026-07-30

---

**Configure the `[open_with]` table in [`superfile.toml`](https://github.com/yorukot/superfile/blob/main/superfile.toml) to map file extensions to custom commands, then press Enter on any matching file to open it with your specified program instead of the system default.**

Superfile is a terminal-based file manager that allows you to override the default application associations on Linux and macOS using the `open_with` configuration option. By defining extension-to-command mappings, you can ensure that pressing **Enter** on a file automatically launches it with your preferred editor or viewer.

## Understanding the `open_with` Configuration Structure

The custom command mappings are stored in the **`ConfigType`** struct defined in [`src/internal/common/config_type.go`](https://github.com/yorukot/superfile/blob/main/src/internal/common/config_type.go). According to the source code, the relevant field is an **OpenWith** map with the signature `map[string]string` (lines 71-73), where keys are file extensions and values are shell commands.

When superfile initializes, it parses the [`superfile.toml`](https://github.com/yorukot/superfile/blob/main/superfile.toml) configuration file and populates this map. The feature is platform-aware: the lookup logic runs on **macOS** and **Linux**, while Windows relies on its native system handlers (though you can still manually configure entries for consistency).

### The TOML Syntax

In your [`superfile.toml`](https://github.com/yorukot/superfile/blob/main/superfile.toml) file, define an `[open_with]` table. Each key represents a file extension **without** the leading dot, and each value specifies the exact command that will receive the file path as its sole argument:

```toml
[open_with]
txt = "code --new-window"
md  = "code"
pdf = "zathura"

```

After saving the configuration, restart superfile or trigger a config reload to activate the new mappings.

## How Command Resolution Works

When you select a file and press **Enter**, the `model.enterPanel` method calls `model.executeOpenCommand` in [`src/internal/handle_panel_movement.go`](https://github.com/yorukot/superfile/blob/main/src/internal/handle_panel_movement.go) (lines 93-99). The function extracts the extension, normalizes it to lowercase, and checks for a custom match:

```go
ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(filePath), "."))
if extEditor, ok := common.Config.OpenWith[ext]; ok {
    openCommand = extEditor
}
cmd := exec.Command(openCommand, filePath)
utils.DetachFromTerminal(cmd)
cmd.Start()

```

The lookup strips the dot from `filepath.Ext()`, converts the result to lowercase for case-insensitive matching, and checks against `common.Config.OpenWith`. If a match exists, it replaces the default `xdg-open` (Linux) or `open` (macOS) command with your custom one. The command is then executed in a detached process so superfile remains responsive.

## Practical Configuration Examples

Here are common patterns for mapping extensions to specific applications:

**Open Markdown files in Visual Studio Code:**

```toml
[open_with]
md = "code"

```

**Open PDFs with Zathura on Linux:**

```toml
[open_with]
pdf = "zathura"

```

**Open plain text files with TextEdit on macOS:**

```toml
[open_with]
txt = "open -a TextEdit"

```

**Open JSON files with a specific IDE flags:**

```toml
[open_with]
json = "code --goto"

```

Note that the command string is passed directly to `exec.Command` with the file path as the final argument. You do not need to include placeholders like `%f` or `$1`; superfile automatically appends the target file path.

## Platform-Specific Behavior

The `open_with` feature is primarily implemented for **Unix-like systems**. On Linux and macOS, superfile uses the resolution logic shown above to determine whether to use a custom command or fall back to system defaults.

On **Windows**, the application relies on the operating system's file associations by default. However, the `OpenWith` map is still available in the configuration structure, and you can define entries for Windows-specific commands if you modify the execution flow or if future updates expand platform support. For cross-platform consistency, keeping your `[open_with]` table synchronized across all your configuration files ensures predictable behavior.

## Summary

- **Configuration Location**: The `OpenWith` map is defined in [`src/internal/common/config_type.go`](https://github.com/yorukot/superfile/blob/main/src/internal/common/config_type.go) and populated from [`superfile.toml`](https://github.com/yorukot/superfile/blob/main/superfile.toml).
- **Syntax**: Use the `[open_with]` TOML table with extension names (without dots) as keys and commands as values.
- **Execution**: The lookup occurs in [`src/internal/handle_panel_movement.go`](https://github.com/yorukot/superfile/blob/main/src/internal/handle_panel_movement.go) when pressing Enter, replacing the default `xdg-open` or `open` command with your custom entry.
- **Case Handling**: Extensions are normalized to lowercase automatically, so `PDF` and `pdf` entries are equivalent.
- **Reload Required**: Changes take effect only after restarting superfile or reloading the configuration.

## Frequently Asked Questions

### How do I open files with Neovim using `open_with`?

Add the extension and the terminal editor command to your [`superfile.toml`](https://github.com/yorukot/superfile/blob/main/superfile.toml). Since superfile detaches the process from the terminal, you should use a terminal emulator wrapper or a GUI version:

```toml
[open_with]
txt = "alacritty -e nvim"
md = "alacritty -e nvim"

```

The file path is appended automatically, so `nvim` receives the correct target.

### Does `open_with` support wildcard patterns or full filenames?

No. As implemented in [`src/internal/handle_panel_movement.go`](https://github.com/yorukot/superfile/blob/main/src/internal/handle_panel_movement.go), the lookup only matches against the file extension extracted by `filepath.Ext()`. It does not support glob patterns, regex, or full filename matching like `Makefile` or `Dockerfile`. You must specify the exact extension key (e.g., `mk` for Makefiles).

### Why isn't my custom command working on Windows?

The current implementation in the superfile source code routes Windows file opening through the native system handler before checking the `OpenWith` map in certain builds. Ensure you are running the latest version, and verify that your command is in the system PATH. For Windows-specific customization, you may need to use the Windows `start` command wrapper or wait for future platform parity updates.

### Can I pass multiple arguments to the command?

Yes. The value in the TOML table is split into the command name and arguments when passed to `exec.Command`. For example, `txt = "code --wait --new-window"` will pass `--wait`, `--new-window`, and the file path as separate arguments to the executable. Avoid shell-specific syntax like pipes or redirects, as the command is executed directly without a shell interpreter.