A DankMaterialShell (DMS) launcher plugin for executing shell commands directly from the launcher with history tracking and preset shortcuts.
Language: QML (Qt Modeling Language)
Type: Launcher plugin for DankMaterialShell
Default Trigger: >
Version: 1.1.2
- The
Always Active/noTriggersetting has been removed from settings UI. - Trigger configuration is always visible and trigger-based usage is now the expected path.
- Legacy empty trigger values are normalized to
>in settings initialization.
┌─────────────────────────────────────────────────────┐
│ User Input │
│ "> htop" │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ Command Processing │
│ - Parse command │
│ - Check history for suggestions │
│ - Generate action items: │
│ • Run in terminal │
│ • Run in background │
│ • Copy to clipboard │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ Execution Methods │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ Terminal │ │ Background │ │ Clipboard │ │
│ │ │ │ │ │ │ │
│ │ terminal -e │ │ sh -c cmd │ │ wl-copy │ │
│ │ + wrapper │ │ (detached) │ │ │ │
│ └──────────────┘ └──────────────┘ └───────────┘ │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ History Tracking │
│ - Add to history (most recent first) │
│ - Limit to maxHistoryItems │
│ - Persist to DMS settings │
└─────────────────────────────────────────────────────┘
- plugin.json - Plugin metadata, version, trigger, capabilities
- CommandRunner.qml - Main component (~165 lines)
- Command parsing and execution
- History management
- Terminal/background/clipboard actions
- CommandRunnerSettings.qml - Settings UI (~200 lines)
- Terminal configuration
- History management
- Trigger configuration
Runs command in user's configured terminal with a wrapper:
const wrappedCommand = command + "; echo '\nPress Enter to close...'; read";
Quickshell.execDetached([terminal.cmd, terminal.execFlag, "sh", "-c", wrappedCommand]);Wrapper purpose:
- Keeps terminal open after command completes
- Prevents terminal from closing immediately
- Allows user to review output
Runs command silently without opening terminal:
Quickshell.execDetached(["sh", "-c", command]);Use cases: Fire-and-forget commands, system services, background tasks
Copies command to clipboard using wl-copy:
Quickshell.execDetached(["sh", "-c", "echo -n '" + text + "' | wl-copy"]);Storage: DMS plugin settings (commandRunner.history)
Max items: Configurable (1-100, default 20)
Order: Most recent first (LIFO)
Deduplication: When command is re-executed, it's moved to top:
function addToHistory(command) {
const index = commandHistory.indexOf(command);
if (index > -1) {
commandHistory.splice(index, 1); // Remove old entry
}
commandHistory.unshift(command); // Add to front
// Trim to max size
if (commandHistory.length > maxHistoryItems) {
commandHistory = commandHistory.slice(0, maxHistoryItems);
}
}Users must configure their terminal before first use:
Common configurations:
kittywith-eflagalacrittywith-eflagfootwith-eflagweztermwithstartflaggnome-terminalwith--flag
Storage:
commandRunner.terminal- Terminal command (e.g., "kitty")commandRunner.execFlag- Execution flag (e.g., "-e")
Location: CommandRunner.qml lines 102-114
Terminal execution (runCommand):
- Wraps command with pause/read
- Launches in configured terminal
- Adds to history
Background execution (runBackground):
- No terminal, direct shell execution
- Adds to history
Security consideration: Commands are passed to sh -c, which can execute arbitrary code. This is intentional but means:
- No validation/sanitization
- Full shell features available (pipes, redirects, etc.)
- User responsibility for command safety
Location: CommandRunnerSettings.qml
The settings UI includes a list of common commands that appear when no query is entered. To add more:
- These are generated dynamically from history
- Or could be hardcoded in
getItems()when query is empty - Consider adding a "favorites" feature for pinned commands
Location: CommandRunner.qml lines 139-156
Options to customize:
- Change max history items (currently 20)
- Add history search/filtering
- Implement history categories
- Add timestamp tracking
- Export/import history
After modifying CommandRunner.qml:
- Save changes
- Restart DMS
- Test with
> [command]in launcher - Verify:
- Terminal opens for "Run: command"
- Background execution works silently
- Clipboard copy works
- History tracking works
- Toast notifications appear
Testing checklist:
- Terminal execution opens terminal
- Command runs and terminal stays open
- Background execution runs silently
- Clipboard copy works (test with paste)
- History updates correctly
- History suggestions filter by query
- Settings persist across restarts
- Document in README.md's terminal table
- Users configure via Settings UI
- No code changes needed (terminal is configurable)
Location: CommandRunner.qml line 12
property int maxHistoryItems: 20 // Change thisLocation: CommandRunner.qml line 105
const wrappedCommand = command + "; echo '\nPress Enter to close...'; read";Alternatives:
; exec $SHELL- Keep terminal open in shell; sleep 5- Auto-close after delay- Remove wrapper - Terminal closes immediately
Add before execution:
function runCommand(command) {
// Validate command exists
if (!isCommandValid(command)) {
showToast("Command not found: " + command);
return;
}
// ... rest of execution
}- Add
favoritesproperty and settings storage - Add "star" action to
getItems() - Show favorites at top of results
- Persist to settings
Location: Lines 16-22, 158-163
Settings are loaded/saved via pluginService:
Component.onCompleted: {
trigger = pluginService.loadPluginData("commandRunner", "trigger", ">");
commandHistory = pluginService.loadPluginData("commandRunner", "history", []);
maxHistoryItems = pluginService.loadPluginData("commandRunner", "maxHistoryItems", 20);
}History auto-saves when updated:
if (pluginService) {
pluginService.savePluginData("commandRunner", "history", commandHistory);
}Location: Lines 122-137
Falls back to kitty with -e if no configuration:
function getTerminalCommand() {
// Try to load from settings
const terminal = pluginService.loadPluginData("commandRunner", "terminal", "kitty");
const execFlag = pluginService.loadPluginData("commandRunner", "execFlag", "-e");
// Return configured or default
return { cmd: terminal, execFlag: execFlag };
}Location: Lines 73-95
Actions are encoded as type:command:
run:htop- Run in terminalbackground:systemctl restart service- Run in backgroundcopy:git status- Copy to clipboard
Parsed via:
const actionParts = item.action.split(":");
const actionType = actionParts[0];
const command = actionParts.slice(1).join(":"); // Rejoin in case command has ":"- Check terminal is installed:
which kitty - Verify terminal setting in plugin config
- Test terminal manually:
kitty -e echo test
- Verify exec flag matches terminal
- Test:
kitty -e sh -c "echo test; read" - Check terminal documentation for correct flag
- Verify
pluginServiceis available - Check settings storage: DMS settings file
- Verify
maxHistoryItems> 0
- Check
wl-copyinstalled:which wl-copy - Install wl-clipboard package
- Test manually:
echo test | wl-copy
- Background commands don't show output
- Check terminal for errors:
journalctl -f - Verify command actually ran (check side effects)
- id:
commandRunner - trigger:
>(configurable by user) - type:
launcher - capabilities:
["command-execution", "shell"]
commandRunner.trigger- Trigger character/stringcommandRunner.terminal- Terminal emulator commandcommandRunner.execFlag- Terminal execution flagcommandRunner.history- Array of command stringscommandRunner.maxHistoryItems- Max history size (1-100)
Commands are executed via sh -c with no sanitization:
Quickshell.execDetached(["sh", "-c", command]);This is intentional to allow:
- Shell features (pipes, redirects, variables)
- Complex command chains
- Full shell scripting
User responsibility:
- Don't run untrusted commands
- Review before executing
- Understand shell metacharacters
Commands run with user's privileges. No sudo/doas handling:
- Users must include
sudoin command if needed - No password prompting in GUI
- Terminal handles authentication
Location: plugin.json line 5
Versioning scheme: Semantic versioning
- Patch (1.1.x): Bug fixes, minor improvements
- Minor (1.x.0): New features, UI enhancements
- Major (x.0.0): Breaking changes, architecture changes
Runtime:
- DankMaterialShell >= 0.1.0
- Terminal emulator (kitty, alacritty, foot, etc.)
- wl-copy (wl-clipboard package) - for clipboard support
- Wayland compositor
Build: None (pure QML, no build process)
Use conventional commits:
feat:- New features, execution modesfix:- Bug fixes, terminal compatibilitydocs:- Documentation updatesrefactor:- Code improvements
# Add new feature
git commit -m "feat: add command favorites/pinning
Allows users to pin frequently used commands
to the top of results list."
# Fix terminal issue
git commit -m "fix: support terminals with non-standard exec flags
Adds support for wezterm's 'start' flag and
gnome-terminal's '--' flag."- Command favorites/pinning - Star commands to keep at top
- Command templates - Parameterized commands with placeholders
- Command categories - Group commands by type (system, dev, network)
- Command aliases - Short names for long commands
- Multi-command sequences - Chain multiple commands
- Working directory - Set CWD for command execution
- Environment variables - Pass custom env vars
- Output capture - Show command output in launcher
- Command validation - Check if command exists before running
- Sudo integration - Handle password prompts
- Command scheduling - Run at specific time/interval
- Terminal execution works with common terminals
- Background execution runs silently
- Clipboard copy works
- History tracking works
- History filters by query
- Settings persist across restarts
- Toast notifications appear
- Trigger configuration works
- Max history items setting works
- History clear function works
htop,btop,top- Process monitorsjournalctl -f- Live system logsdf -h,free -h- Disk/memory usage
ranger,lf- File managersncdu- Disk usage analyzerfzf- Fuzzy file finder
nmtui- Network manager TUIping 8.8.8.8- Network testip addr- Network interfaces
vim,nvim- Editorsgit status- Git operationsnpm install,cargo build- Build commands
Last Updated: 2026-01-30 Maintainer: devnullvoid AI-Friendly: This document helps AI agents quickly understand and work with this plugin.