Imported from devnullvoid/dms-web-search (
AGENTS.md). Install upstream withnpx skills add devnullvoid/dms-web-search. Copyright stays with the author.
AGENTS.md - DMS Web Search
Project Overview
A DankMaterialShell (DMS) launcher plugin for searching the web with 23+ built-in search engines and support for custom search engines, including integration with 13,000+ DuckDuckGo !bangs.
Language: QML (Qt Modeling Language)
Type: Launcher plugin for DankMaterialShell
Default Trigger: @
Version: 1.4.0
Recent Maintenance Notes (2026-03-17)
- Added DuckDuckGo !bang functionality (#14).
- Implemented
DDGBangWorker.jsfor off-thread bang filtering to maintain UI performance. - Added
DDGSyncHelper.jsfor fetching and local caching of the 13k+ DDG bang database. - Integrated sync UI and status in
WebSearchSettings.qml. - Added fallback logic in
WebSearch.qmlto handle!prefixed queries.
Architecture Overview
┌─────────────────────────────────────────────────────┐
│ Built-in Search Engines │
│ Defined in SearchEngines.qml │
│ 23+ engines with keywords and URL templates │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ DuckDuckGo !Bangs (Optional Sync) │
│ - Synced from duckduckgo.com/bang.js │
│ - Cached locally in plugin data │
│ - Filtered off-thread via DDGBangWorker.js │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ User Settings (Persistent Storage) │
│ - Custom search engines │
│ - Default engine preference │
│ - Trigger configuration │
│ - Synced DDG bangs and last sync timestamp │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ Query Processing │
│ 1. Check for '!' prefix (DDG Bangs) │
│ 2. Check for keyword prefix (e.g., "github rust") │
│ 3. Match to specific engine or use default │
│ 4. Generate search URL with encoded query │
│ 5. Launch in browser via xdg-open │
└─────────────────────────────────────────────────────┘
File Structure
Core Files
- plugin.json - Plugin metadata, version, trigger, capabilities
- WebSearch.qml - Main component (~400 lines)
- Core search orchestration
- Integrated
WorkerScriptfor DDG bangs - Browser launching logic
- WebSearchSettings.qml - Settings UI (~950 lines)
- Management of engines and trigger
- DDG Bang sync control
- SearchEngines.qml - Built-in engine definitions
- DDGBangWorker.js - Off-thread logic for filtering 13k+ bangs
- DDGSyncHelper.js - Utility for fetching and optimizing DDG bang JSON
Key Concepts
Search Engine Structure
Each search engine is defined as a JavaScript object:
{
id: "google", // Unique identifier
name: "Google", // Display name
icon: "material:travel_explore", // Icon (material: or unicode:)
url: "https://www.google.com/search?q=%s", // URL template with %s placeholder
keywords: ["google", "search"] // Keywords for quick access
}
DuckDuckGo !Bangs
Bangs are handled as a fallback mechanism:
- User types query starting with
!. WebSearch.qmlsends trigger part toDDGBangWorker.js.- Worker filters cached bangs (prioritizing exact matches and prefix matches).
- Suggestions are returned to the UI.
- Search execution bypasses DDG redirects by using the direct URL template.
Keyword Matching
The plugin supports keyword-based engine selection:
- User types:
@ github rust async - Plugin detects "github" keyword at start
- Matches to GitHub engine
- Searches for "rust async" on GitHub
If no keyword matches and it's not a ! query, the default engine is used.
Development Workflow
1. Adding Built-in Search Engines
Location: SearchEngines.qml
Add new engine to engines array:
{
id: "rustdoc",
name: "Rust Documentation",
icon: "unicode:🦀",
url: "https://doc.rust-lang.org/std/?search=%s",
keywords: ["rust", "docs", "documentation"]
}
2. Modifying Bang Logic
Location: DDGBangWorker.js
The worker handles the heavy lifting of searching 13,000+ items. Filtering should always prioritize:
- Exact trigger matches (
trigger === query) - Prefix matches (
trigger.startsWith(query)) - Name matches (
name.includes(query))
3. Testing Changes
Testing checklist:
- Sync DDG bangs successfully in Settings
-
!queries provide relevant suggestions instantly - Keyword matching works (e.g.,
@ github test) - Default engine used when no keyword/bang
- Browser launches successfully with correct URL
Important QML Details
WorkerScript Integration
In WebSearch.qml, the worker must be assigned to a property to avoid QtObject child assignment errors:
property WorkerScript bangWorker: WorkerScript {
source: "DDGBangWorker.js"
onMessage: (message) => { ... }
}
Settings Persistence
Settings include the massive ddgBangs array. Ensure PluginService can handle the data size (optimized in DDGSyncHelper.js by stripping unused fields).
Troubleshooting
Bangs not showing
- Verify "Last Sync" in Settings is not "Never".
- Check if query starts with
!(the trigger for bangs). - Ensure
DDGBangWorker.jsis correctly linked/available.
Slow UI during search
If the UI stutters while typing !, check that DDGBangWorker.js is actually running off-thread and not being called synchronously somehow.
Version Bumping
Location: plugin.json line 5
- 1.4.0: Added DDG Bangs integration.
Author
Maintainer: devnullvoid Last Updated: 2026-03-17 AI-Friendly: This document helps AI agents quickly understand the hybrid architecture of static engines + off-thread filtered dynamic bangs.