# Dopus Plugin for Keypirinha

**URL:** <https://resource.dopus.com/t/dopus-plugin-for-keypirinha/59667>\
**Category:** Tools\
**Created:** [June 9, 2026, 2:34am UTC](https://resource.dopus.com/t/dopus-plugin-for-keypirinha/59667 "2026-06-09T02:34:16Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![jfour18](https://resource.dopus.com/user_avatar/resource.dopus.com/jfour18/32/66032_2.png) [@jfour18](https://resource.dopus.com/u/jfour18)\
**Post date:** [June 9, 2026, 2:34am UTC](https://resource.dopus.com/t/dopus-plugin-for-keypirinha/59667/1 "2026-06-09T02:34:17Z")

</div>

A [Keypirinha](https://keypirinha.com/) plugin which dynamically imports DOpus aliases into the Keypirinha launcher at runtime (very fast).

Additional features:

- Allows you to browse through aliased folders using the tab key.
- Allows you to quickly launch/open aliased folders in DOpus
- Allows you to quickly open/launch files within aliased folders without opening DOpus.
- Allows you to preview files using the DOpus quickshow feature, as Keypirinha does not have a native previewer. Unfortunately, it does not currently appear possible to preview without closing the Keypirinha window.

 ![image](https://resource.dopus.com/uploads/default/original/3X/1/e/1e5515aabae3ef1dc3824d11520a9d6e23161934.png)

The .ini file and .py file need to be saved in the following location.  
`Keypirinha\portable\Profile\Packages\DOpusAliases\DOpusAliases.py`  
`Keypirinha\portable\Profile\Packages\DOpusAliases\DOpusAliases.ini`

Keypirinha  
└───portable  
│  
├───Profile  
│  
├───Packages  
├───DOpusAliases  
├───DOpusAliases.ini  
├───DOpusAliases.py

DOpusAliases.py

```auto
# Keypirinha package: DOpusAliases
# Imports Directory Opus folder aliases directly from folderaliases.oxc.
# Also provides native actions for browsed files, including DOpus QuickShow.

import keypirinha as kp
import keypirinha_util as kpu

import os
import traceback
import xml.etree.ElementTree as ET

class DOpusAliases(kp.Plugin):
    """Catalog Directory Opus folder aliases as native Keypirinha items."""

    ITEMCAT_ALIAS = kp.ItemCategory.USER_BASE + 1
    ITEMCAT_ALIAS_DIR = kp.ItemCategory.USER_BASE + 2
    ITEMCAT_ALIAS_FILE = kp.ItemCategory.USER_BASE + 3

    CONFIG_SECTION_MAIN = "main"
    CONFIG_SECTION_BROWSE = "browse"
    CONFIG_SECTION_QUICKSHOW = "quickshow"

    ACTION_OPEN_DOPUS = "open_dopus"
    ACTION_COPY_TARGET = "copy_target"
    ACTION_OPEN_EXPLORER = "open_explorer"

    ACTION_FILE_OPEN = "file_open"
    ACTION_FILE_QUICKSHOW = "file_quickshow"
    ACTION_FILE_VIEWER = "file_viewer"
    ACTION_FILE_COPY_PATH = "file_copy_path"
    ACTION_FILE_OPEN_PARENT_DOPUS = "file_open_parent_dopus"
    ACTION_FILE_OPEN_PARENT_EXPLORER = "file_open_parent_explorer"

    ACTION_DIR_OPEN_DOPUS = "dir_open_dopus"
    ACTION_DIR_OPEN_EXPLORER = "dir_open_explorer"
    ACTION_DIR_COPY_PATH = "dir_copy_path"

    DEFAULT_ALIAS_FILE = r"%APPDATA%\GPSoftware\Directory Opus\ConfigFiles\folderaliases.oxc"
    DEFAULT_DOPUSRT_EXE = r"C:\Program Files\GPSoftware\Directory Opus\dopusrt.exe"
    DEFAULT_ITEM_LABEL = r"/{alias_name}"
    DEFAULT_SHORT_DESC = r"DOpus alias: {target}"
    DEFAULT_HIDE_MISSING_TARGETS = False

    DEFAULT_ENABLE_BROWSE_CHAIN = True
    DEFAULT_SHOW_DIRS_FIRST = True
    DEFAULT_SHOW_HIDDEN_FILES = True
    DEFAULT_SHOW_SYSTEM_FILES = False
    DEFAULT_MAX_BROWSE_ITEMS = 500

    DEFAULT_QUICKSHOW_ARGUMENTS = "QUICKSHOW"
    DEFAULT_VIEWER_ARGUMENTS = "USEEXISTING=no"

    def __init__ (self):
        super(). __init__ ()

        self.alias_file = self.DEFAULT_ALIAS_FILE
        self.dopusrt_exe = self.DEFAULT_DOPUSRT_EXE
        self.item_label_format = self.DEFAULT_ITEM_LABEL
        self.short_desc_format = self.DEFAULT_SHORT_DESC
        self.hide_missing_targets = self.DEFAULT_HIDE_MISSING_TARGETS

        self.enable_browse_chain = self.DEFAULT_ENABLE_BROWSE_CHAIN
        self.show_dirs_first = self.DEFAULT_SHOW_DIRS_FIRST
        self.show_hidden_files = self.DEFAULT_SHOW_HIDDEN_FILES
        self.show_system_files = self.DEFAULT_SHOW_SYSTEM_FILES
        self.max_browse_items = self.DEFAULT_MAX_BROWSE_ITEMS

        self.quickshow_arguments = self.DEFAULT_QUICKSHOW_ARGUMENTS
        self.viewer_arguments = self.DEFAULT_VIEWER_ARGUMENTS

        self._last_alias_file_mtime = None
        self._alias_actions = []
        self._dir_actions = []
        self._file_actions = []

    def on_start(self):
        self._read_config()
        self._register_actions()

    def _register_actions(self):
        self._alias_actions = [
            self.create_action(
                name=self.ACTION_OPEN_DOPUS,
                label="Open in Directory Opus",
                short_desc="Open this alias target in Directory Opus"),
            self.create_action(
                name=self.ACTION_COPY_TARGET,
                label="Copy target path",
                short_desc="Copy the alias target path to the clipboard"),
            self.create_action(
                name=self.ACTION_OPEN_EXPLORER,
                label="Open in Explorer",
                short_desc="Open this alias target with Windows Explorer"),
        ]
        self.set_actions(self.ITEMCAT_ALIAS, self._alias_actions)

        self._dir_actions = [
            self.create_action(
                name=self.ACTION_DIR_OPEN_DOPUS,
                label="Open folder in Directory Opus",
                short_desc="Open this folder in Directory Opus"),
            self.create_action(
                name=self.ACTION_DIR_OPEN_EXPLORER,
                label="Open folder in Explorer",
                short_desc="Open this folder with Windows Explorer"),
            self.create_action(
                name=self.ACTION_DIR_COPY_PATH,
                label="Copy folder path",
                short_desc="Copy this folder path to the clipboard"),
        ]
        self.set_actions(self.ITEMCAT_ALIAS_DIR, self._dir_actions)

        self._file_actions = [
            self.create_action(
                name=self.ACTION_FILE_OPEN,
                label="Open",
                short_desc="Open this file with the default Windows action"),
            self.create_action(
                name=self.ACTION_FILE_QUICKSHOW,
                label="Preview with DOpus QuickShow",
                short_desc="Preview this file with Directory Opus QuickShow"),
            self.create_action(
                name=self.ACTION_FILE_VIEWER,
                label="Preview with DOpus Viewer",
                short_desc="Open this file in the persistent Directory Opus viewer"),
            self.create_action(
                name=self.ACTION_FILE_COPY_PATH,
                label="Copy path",
                short_desc="Copy this file path to the clipboard"),
            self.create_action(
                name=self.ACTION_FILE_OPEN_PARENT_DOPUS,
                label="Open containing folder in Directory Opus",
                short_desc="Open this file's containing folder in Directory Opus"),
            self.create_action(
                name=self.ACTION_FILE_OPEN_PARENT_EXPLORER,
                label="Open containing folder in Explorer",
                short_desc="Open this file's containing folder with Windows Explorer"),
        ]
        self.set_actions(self.ITEMCAT_ALIAS_FILE, self._file_actions)

    def on_catalog(self):
        self._read_config()

        alias_file = self._expand_path(self.alias_file)
        if not os.path.isfile(alias_file):
            self.warn("Directory Opus alias file not found: {}".format(alias_file))
            self.set_catalog([])
            self._last_alias_file_mtime = None
            return

        try:
            aliases = self._parse_aliases(alias_file)
        except Exception as exc:
            self.err("Failed to parse Directory Opus alias file: {}".format(alias_file))
            self.err(str(exc))
            traceback.print_exc()
            self.set_catalog([])
            return

        catalog = []
        display_names = self._unique_display_names([a[0] for a in aliases])

        for idx, alias in enumerate(aliases):
            alias_name, target = alias
            display_alias_name = display_names[idx]
            expanded_target = self._expand_path(target)

            if self.hide_missing_targets and not self._target_is_probably_valid(expanded_target):
                continue

            item_label = self._safe_format(
                self.item_label_format,
                alias_name=display_alias_name,
                raw_alias_name=alias_name,
                target=target,
                expanded_target=expanded_target,
                plugin_name=self.friendly_name())

            short_desc = self._safe_format(
                self.short_desc_format,
                alias_name=display_alias_name,
                raw_alias_name=alias_name,
                target=target,
                expanded_target=expanded_target,
                plugin_name=self.friendly_name())

            catalog.append(self.create_item(
                category=self.ITEMCAT_ALIAS,
                label=item_label,
                short_desc=short_desc,
                target=target,
                args_hint=kp.ItemArgsHint.ACCEPTED,
                hit_hint=kp.ItemHitHint.NOARGS,
                loop_on_suggest=True))

            if len(catalog) % 100 == 0 and self.should_terminate():
                return

        self.set_catalog(catalog)
        self._last_alias_file_mtime = self._safe_mtime(alias_file)
        self.info("Cataloged {} Directory Opus alias{} from {}".format(
            len(catalog), "" if len(catalog) == 1 else "es", alias_file))

    def on_suggest(self, user_input, items_chain):
        if not self.enable_browse_chain:
            return

        if not items_chain:
            return

        current_item = items_chain[-1]
        current_category = current_item.category()

        if current_category == self.ITEMCAT_ALIAS:
            base_dir = self._expand_path(current_item.target())
        elif current_category == self.ITEMCAT_ALIAS_DIR:
            base_dir = current_item.target()
        else:
            return

        if not os.path.isdir(base_dir):
            clone = current_item.clone()
            clone.set_args(user_input)
            clone.set_loop_on_suggest(False)
            self.set_suggestions([clone], kp.Match.ANY, kp.Sort.NONE)
            return

        suggestions = self._browse_dir(base_dir, user_input)
        self.set_suggestions(suggestions, kp.Match.ANY, kp.Sort.NONE)

    def on_execute(self, item, action):
        if not item:
            return

        category = item.category()
        action_name = action.name() if action else None

        if category == self.ITEMCAT_ALIAS:
            self._execute_alias(item, action_name)
            return

        if category == self.ITEMCAT_ALIAS_DIR:
            self._execute_dir(item, action_name)
            return

        if category == self.ITEMCAT_ALIAS_FILE:
            self._execute_file(item, action_name)
            return

    def on_events(self, flags):
        if flags & kp.Events.PACKCONFIG:
            self.on_catalog()

    def on_activated(self):
        # Keypirinha does not watch Directory Opus' private config file.
        # Re-catalog when the launcher is opened and folderaliases.oxc changed.
        alias_file = self._expand_path(self.alias_file)
        current_mtime = self._safe_mtime(alias_file)
        if current_mtime is not None and current_mtime != self._last_alias_file_mtime:
            self.on_catalog()

    def _execute_alias(self, item, action_name):
        target = item.target()
        expanded_target = self._expand_path(target)

        if action_name == self.ACTION_COPY_TARGET:
            kpu.set_clipboard(expanded_target)
            return

        if action_name == self.ACTION_OPEN_EXPLORER:
            self._open_in_explorer(expanded_target)
            return

        self._open_in_dopus(target)

    def _execute_dir(self, item, action_name):
        folder_path = item.target()

        if action_name == self.ACTION_DIR_COPY_PATH:
            kpu.set_clipboard(folder_path)
            return

        if action_name == self.ACTION_DIR_OPEN_EXPLORER:
            self._open_in_explorer(folder_path)
            return

        self._open_in_dopus(folder_path)

    def _execute_file(self, item, action_name):
        file_path = item.target()

        if action_name == self.ACTION_FILE_QUICKSHOW:
            self._show_in_dopus(file_path, self.quickshow_arguments)
            return

        if action_name == self.ACTION_FILE_VIEWER:
            self._show_in_dopus(file_path, self.viewer_arguments)
            return

        if action_name == self.ACTION_FILE_COPY_PATH:
            kpu.set_clipboard(file_path)
            return

        if action_name == self.ACTION_FILE_OPEN_PARENT_DOPUS:
            self._open_in_dopus(os.path.dirname(file_path))
            return

        if action_name == self.ACTION_FILE_OPEN_PARENT_EXPLORER:
            self._open_in_explorer(os.path.dirname(file_path))
            return

        self._open_file_default(file_path)

    def _browse_dir(self, base_dir, search_terms):
        search_terms = (search_terms or "").strip()
        suggestions = []

        try:
            names = os.listdir(base_dir)
        except OSError as exc:
            return [self.create_error_item(
                label="Cannot browse folder",
                short_desc="{}: {}".format(base_dir, exc))]

        dir_items = []
        file_items = []

        for name in names:
            if self.should_terminate():
                return []

            full_path = os.path.join(base_dir, name)

            try:
                st = os.stat(full_path)
            except OSError:
                continue

            if not self._should_show_path(name, full_path, st):
                continue

            match_score = None
            if search_terms:
                if search_terms.lower() in name.lower():
                    match_score = 100000 - len(name)
                else:
                    try:
                        fuzzy_score = kpu.fuzzy_score(search_terms, name)
                    except Exception:
                        fuzzy_score = None
                    if not fuzzy_score:
                        continue
                    match_score = fuzzy_score

            if os.path.isdir(full_path):
                dir_items.append((match_score, name.lower(), self.create_item(
                    category=self.ITEMCAT_ALIAS_DIR,
                    label=name,
                    short_desc=full_path,
                    target=full_path,
                    args_hint=kp.ItemArgsHint.ACCEPTED,
                    hit_hint=kp.ItemHitHint.KEEPALL,
                    loop_on_suggest=True)))
            else:
                file_items.append((match_score, name.lower(), self.create_item(
                    category=self.ITEMCAT_ALIAS_FILE,
                    label=name,
                    short_desc=full_path,
                    target=full_path,
                    args_hint=kp.ItemArgsHint.FORBIDDEN,
                    hit_hint=kp.ItemHitHint.KEEPALL,
                    loop_on_suggest=False)))

        if search_terms:
            dir_items.sort(key=lambda x: (-(x[0] or 0), x[1]))
            file_items.sort(key=lambda x: (-(x[0] or 0), x[1]))
        else:
            dir_items.sort(key=lambda x: x[1])
            file_items.sort(key=lambda x: x[1])

        if self.show_dirs_first:
            ordered = dir_items + file_items
        else:
            ordered = sorted(dir_items + file_items, key=lambda x: x[1])

        for _, __, item in ordered[:self.max_browse_items]:
            suggestions.append(item)

        return suggestions

    def _should_show_path(self, name, full_path, st):
        if name in (".", ".."):
            return False

        attrs = getattr(st, "st_file_attributes", 0)
        hidden = bool(attrs & 0x2)
        system = bool(attrs & 0x4)

        if hidden and not self.show_hidden_files:
            return False
        if system and not self.show_system_files:
            return False

        return True

    def _read_config(self):
        settings = self.load_settings()

        self.alias_file = settings.get_stripped(
            "alias_file", self.CONFIG_SECTION_MAIN, self.DEFAULT_ALIAS_FILE)
        self.dopusrt_exe = settings.get_stripped(
            "dopusrt_exe", self.CONFIG_SECTION_MAIN, self.DEFAULT_DOPUSRT_EXE)
        self.item_label_format = settings.get_stripped(
            "item_label", self.CONFIG_SECTION_MAIN, self.DEFAULT_ITEM_LABEL)
        self.short_desc_format = settings.get_stripped(
            "short_desc", self.CONFIG_SECTION_MAIN, self.DEFAULT_SHORT_DESC)
        self.hide_missing_targets = settings.get_bool(
            "hide_missing_targets", self.CONFIG_SECTION_MAIN, self.DEFAULT_HIDE_MISSING_TARGETS)

        self.enable_browse_chain = settings.get_bool(
            "enable_browse_chain", self.CONFIG_SECTION_BROWSE, self.DEFAULT_ENABLE_BROWSE_CHAIN)
        self.show_dirs_first = settings.get_bool(
            "show_dirs_first", self.CONFIG_SECTION_BROWSE, self.DEFAULT_SHOW_DIRS_FIRST)
        self.show_hidden_files = settings.get_bool(
            "show_hidden_files", self.CONFIG_SECTION_BROWSE, self.DEFAULT_SHOW_HIDDEN_FILES)
        self.show_system_files = settings.get_bool(
            "show_system_files", self.CONFIG_SECTION_BROWSE, self.DEFAULT_SHOW_SYSTEM_FILES)
        self.max_browse_items = settings.get_int(
            "max_browse_items", self.CONFIG_SECTION_BROWSE, self.DEFAULT_MAX_BROWSE_ITEMS,
            min=1, max=5000)

        self.quickshow_arguments = settings.get_stripped(
            "quickshow_arguments", self.CONFIG_SECTION_QUICKSHOW, self.DEFAULT_QUICKSHOW_ARGUMENTS)
        self.viewer_arguments = settings.get_stripped(
            "viewer_arguments", self.CONFIG_SECTION_QUICKSHOW, self.DEFAULT_VIEWER_ARGUMENTS)

    def _parse_aliases(self, alias_file):
        tree = ET.parse(alias_file)
        root = tree.getroot()

        aliases = []
        seen = set()

        for path_node in root.findall(".//path"):
            alias_name = (path_node.get("label") or path_node.get("name") or "").strip()
            if not alias_name:
                continue

            pathstring_node = path_node.find("./dir/pathstring")
            if pathstring_node is None or pathstring_node.text is None:
                continue

            target = pathstring_node.text.strip()
            if not target:
                continue

            key = (alias_name.casefold(), target.casefold())
            if key in seen:
                continue

            seen.add(key)
            aliases.append((alias_name, target))

            if len(aliases) % 100 == 0 and self.should_terminate():
                return []

        return aliases

    def _open_in_dopus(self, target):
        dopusrt = self._expand_path(self.dopusrt_exe)
        if not os.path.isfile(dopusrt):
            self.err("dopusrt.exe not found: {}".format(dopusrt))
            return

        try:
            kpu.shell_execute(
                dopusrt,
                args=["/cmd", "Go", target],
                verb="",
                detect_nongui=False)
        except Exception:
            self.err("Failed to open Directory Opus target: {}".format(target))
            traceback.print_exc()

    def _show_in_dopus(self, file_path, extra_arguments):
        dopusrt = self._expand_path(self.dopusrt_exe)
        if not os.path.isfile(dopusrt):
            self.err("dopusrt.exe not found: {}".format(dopusrt))
            return

        args = ["/cmd", "Show", file_path]
        args.extend(self._split_extra_args(extra_arguments))

        try:
            kpu.shell_execute(
                dopusrt,
                args=args,
                verb="",
                detect_nongui=False)
        except Exception:
            self.err("Failed to show file in Directory Opus: {}".format(file_path))
            traceback.print_exc()

    def _open_file_default(self, file_path):
        try:
            kpu.shell_execute(file_path, detect_nongui=False)
        except Exception:
            self.err("Failed to open file: {}".format(file_path))
            traceback.print_exc()

    def _open_in_explorer(self, path):
        try:
            kpu.shell_execute(path, detect_nongui=False)
        except Exception:
            self.err("Failed to open in Explorer: {}".format(path))
            traceback.print_exc()

    def _split_extra_args(self, value):
        value = (value or "").strip()
        if not value:
            return []
        try:
            return kpu.cmdline_split(value)
        except Exception:
            return value.split()

    def _expand_path(self, value):
        if value is None:
            return ""
        return os.path.normpath(os.path.expandvars(value.strip()))

    def _safe_mtime(self, path):
        try:
            return os.path.getmtime(path)
        except OSError:
            return None

    def _target_is_probably_valid(self, target):
        if not target:
            return False
        if target.startswith("::"):
            return True
        if ":" not in target and not target.startswith("\\\\"):
            return True
        return os.path.exists(target)

    def _safe_format(self, fmt, **kwargs):
        try:
            return fmt.format(**kwargs)
        except Exception:
            return fmt

    def _unique_display_names(self, names):
        used = {}
        result = []
        for name in names:
            base = name.strip() or "Unnamed Alias"
            key = base.casefold()
            count = used.get(key, 0) + 1
            used[key] = count
            if count == 1:
                result.append(base)
            else:
                result.append("{} {}".format(base, count))
        return result

```

DOpusAliases.ini

```auto
#
# DOpusAliases Package configuration file
# Imports Directory Opus folder aliases from folderaliases.oxc as native
# Keypirinha catalog items, with native file actions including DOpus QuickShow.
#

[main]
# Directory Opus folder alias config file.
# Default is the current user's normal DOpus config path.
#alias_file = %APPDATA%\GPSoftware\Directory Opus\ConfigFiles\folderaliases.oxc

# Directory Opus runtime executable.
#dopusrt_exe = C:\Program Files\GPSoftware\Directory Opus\dopusrt.exe

# Catalog item display. Useful default: type / in Keypirinha to surface aliases.
# Available placeholders:
# {alias_name} de-duplicated alias name
# {raw_alias_name} original alias name from folderaliases.oxc
# {target} raw target from folderaliases.oxc
# {expanded_target} target after environment expansion
# {plugin_name} package/plugin display name
item_label = /{alias_name}

# Description shown under each catalog item.
short_desc = DOpus alias: {target}

# If yes, normal filesystem aliases whose targets do not exist are skipped.
# DOpus virtual paths and namespaces are still kept.
hide_missing_targets = no

[browse]
# After selecting an alias or browsed folder, allow browsing its contents inside Keypirinha.
enable_browse_chain = yes
show_dirs_first = yes
show_hidden_files = yes
show_system_files = no
max_browse_items = 500

[quickshow]
# Arguments appended to: dopusrt.exe /cmd Show "<file>"
# For the transient DOpus QuickShow preview:
quickshow_arguments = QUICKSHOW

# For the persistent Directory Opus viewer:
viewer_arguments = USEEXISTING=no

[var]

[env]

```
