A terminal-based mDNS service browser built with Rust, using ratatui for the TUI interface. For an alternative running as a desktop app, check out mDNS-Browser.
- Features
- Quick Start
- JSON State Dump
- Controls
- Architecture
- Project Structure
- Building
- Build Provenance
- Auditable Builds
- Immutable releases
- Future Enhancements
- License
- 🖥️ Interactive TUI: Full terminal UI with keyboard navigation
- 📊 Service Details: Display IP address, port, and TXT records
- 🔄 Real-time Updates: Async architecture for live service discovery
- 📈 Live Metrics: Comprehensive ServiceDaemon and application metrics
- 🎛️ Service Type Filtering: Browse different service types separately
- 🔍 Quick Filter: Text-based search across all service fields
- 📋 Advanced Sorting: Sort by Host, Type, Name, Port, Address, or Time in both directions
- ⚙️ Custom Service Discovery: Specify service types via CLI for hard-to-discover services
- 💾 JSON State Dump: Export complete application state to JSON with Ctrl+J
cargo runcargo build --releaseYou can install mdns-tui-browser from the Arch User Repository (AUR) using yay:
# Install using yay
yay -S mdns-tui-browserThis will install the latest version from the AUR and handle updates automatically with your regular system updates.
You can install mdns-tui-browser via Homebrew:
# Tap the repository first
brew tap hrzlgnm/tap
brew install --cask mdns-tui-browserOr install directly without tapping:
brew install --cask hrzlgnm/tap/mdns-tui-browserThis will install the latest version from the Homebrew tap and handle updates automatically with brew upgrade.
You can install mdns-tui-browser from Winget Packages using winget:
# Install using winget
winget install hrzlgnm.mdns-tui-browserThis will install the latest version from Winget Packages and handle updates automatically with your regular system updates.
You can install mdns-tui-browser from Snapcraft using snap:
# Install using snap
sudo snap install mdns-tui-browserThis will install the latest version from the snap store and handle updates automatically with snap refresh.
You can find the package on the Snapcraft store.
# Show version
mdns-tui-browser --version
mdns-tui-browser -V
# Show help
mdns-tui-browser --help
mdns-tui-browser -h
# Browse explicit service types, instead of auto-discovery
mdns-tui-browser --service-types "_http._tcp.local.,_ssh._tcp.local."
mdns-tui-browser -s "_printer._tcp.local."
# Browse with shortened service types (auto-completed)
mdns-tui-browser -s "_http,_ssh"
mdns-tui-browser -s "http,ssh"
mdns-tui-browser -s http -s ssh
# Use specific network interfaces
mdns-tui-browser -i en0
mdns-tui-browser --interfaces en0,eth0
# Disable IPv4 or IPv6 mDNS discovery
mdns-tui-browser --no-ipv4
mdns-tui-browser --no-ipv6
# Load state from a JSON file (view-only mode, no browsing)
mdns-tui-browser --load-state state-dump.json
mdns-tui-browser -l state-dump.jsonService types to browse for (e.g., http, _http._tcp, printer). Auto-completes (_)service, (_)sub, .(_)[tc|ud]p and .local. suffix.
Usage:
- Can be specified multiple times
- Accepts comma-separated list of mDNS service types
- Auto-completes various service type formats automatically
- Examples:
http,_http._tcp,printer
The application can export the complete current state to a JSON file for debugging and analysis purposes, and can also load a previously exported state file for inspection.
Press Ctrl+J in the TUI to trigger a state dump. The file will be saved with an ISO timestamp filename:
20260207T120102.089898-state-dump.json
To load a previously exported state file for inspection (view-only mode, no browsing):
mdns-tui-browser --load-state state-dump.json
mdns-tui-browser -l state-dump.jsonWhen loading a state file, no mDNS browsing is performed. The border color changes to a darker color to indicate view-only mode.
The exported JSON contains comprehensive information about the current application state:
{
"metadata": {
"dumpTimestamp": "2026-02-07T00:40:10.950885Z",
"applicationName": "mdns-tui-browser",
"version": "1.11.1"
},
"services": [
{
"host": "my-device.local",
"serviceType": "_http._tcp.local.",
"addresses": ["192.168.1.100"],
"port": 8080,
"txtRecords": ["path=/api"],
"isOnline": true,
"createdAt": "2026-02-07T11:30:00.123456Z",
"updatedAt": "2026-02-07T12:00:00.123456Z",
"lastOnlineAt": "2026-02-07T12:00:00.123456Z",
"sessionHistory": [
{
"startTime": "2026-02-07T00:39:53.820969Z",
"endTime": "2026-02-07T00:39:55.869714Z"
}
]
}
],
"serviceTypes": ["_http._tcp.local.", "_ssh._tcp.local."],
"metrics": {
"daemon_browse": 160,
"daemon_cache_refresh_addr": 0,
"daemon_cache_refresh_ptr": 0,
"daemon_cache_refresh_srv_txt": 0,
"daemon_cached_addr": 45,
"daemon_cached_nsec": 14,
"daemon_cached_ptr": 74,
"daemon_cached_srv": 42,
"daemon_cached_subtype": 1,
"daemon_cached_txt": 42,
"daemon_dns_registry_active": 0,
"daemon_dns_registry_name_change": 0,
"daemon_dns_registry_probe": 0,
"daemon_dns_registry_timer": 0,
"daemon_known_answer_suppression": 0,
"daemon_timer": 5607,
"service_types_discovered": 31,
"services_discovered": 38,
"services_marked_offline": 4,
"services_updated": 14
},
"filters": {
"query": "",
"activeServiceTypes": ["_http._tcp.local."]
},
"sorting": {
"field": "Host",
"direction": "Ascending"
}
}- ↑/↓ or j/k - Navigate services list
- ←/→ or h/l - Switch between service types
- H/L - Page through service types
- Ctrl+Home/End - Jump to first/last service type
- PageUp/PageDown or b/f or Space - Scroll services list by page
- Home/End - Jump to first/last service in list
- Enter - Open service URL in browser (_http._tcp or URL from TXT)
- s - Cycle sort field forward (Host → Type → Name → Port → Addr → Time)
- S - Cycle sort field backward (Time → Addr → Port → Name → Type → Host)
- o - Toggle sort direction (↑/↓)
- / - Enter quick filter mode (search across all service fields)
- a - Add new service type to browse
- n - Clear current filter
- d - Remove offline services
- D - Clear stale service types (service types with no services)
- m - Show service metrics
- Ctrl+J - Dump current state to JSON file
- Ctrl+Z - Suspend the application (Unix only)
- ? - Toggle help popup
- Shift+↑/↓ or J/K - Scroll service details
- q or Ctrl+c - Quit the application
- Shift+↑/↓ or J/K - Scroll service details
- ↑/↓ - Scroll help content
- r - Open release notes in browser
- Any other key - Close help popup
When in filter mode (activated with /):
- Enter - Apply filter
- Esc - Cancel filter input
- Backspace - Delete last character
- Any other key - Type search text (case-insensitive)
The quickfilter supports special keywords for filtering by service status:
online- Shows online services AND services containing "online" in any field (fullname, host, service type, TXT records, etc.)offline- Shows offline services AND services containing "offline" in any field (fullname, host, service type, TXT records, etc.)flapping- Shows services that are flapping (detected based on session history - at least 3 sessions with at least half shorter than 5 minutes)- Case-insensitive:
ONLINE,Online,offline,OFFLINE,FLAPPING,Flappingall work - Hybrid mode: Keywords match both by status AND text content
- Combined queries:
online httpshows online services with "http" in text fields
Examples:
# Press '/' then type:
online # Show online services + services with "online" in text
offline # Show offline services + services with "offline" in text
flapping # Show flapping services
online http # Show online HTTP services
offline printer # Show offline printer services
online flapping # Show services that are both online AND flapping
online offline # Shows all services (both keywords present)When in add service type mode (activated with a):
- Enter - Add the service type and start browsing
- Esc - Cancel input
- Backspace - Delete last character
- Any other key - Type service type name
The service type is automatically normalized (e.g., http becomes _http._tcp.local.).
The application is built with:
- Rust - Systems programming language (Safe Rust only - no unsafe blocks allowed)
- ratatui - Terminal UI framework
- tokio - Async runtime
- crossterm - Terminal handling
- flume - Async channel library for communication
- mdns-sd - mDNS service discovery library
- clap - Command line argument parsing library
- chrono - Date and time handling for local timestamp display
- serde - Serialization framework for JSON export
- serde_json - JSON serialization support
- if-addrs - Network interface enumeration
- nix - Unix system calls (signal handling for Ctrl+Z suspend)
- open - Cross-platform library to open URLs in the browser
- url - URL parsing and validation for URL extraction from TXT records
This project follows a Safe Rust Only policy:
- No
unsafeblocks are permitted in the codebase - All memory safety is guaranteed by Rust's compiler and runtime
- The codebase is configured to reject unsafe code
- This ensures maximum security and reliability for the mDNS service browser
- Extensible Design: Built for real mDNS service discovery
src/
├── main.rs # Entry point with CLI argument handling
├── tui_app.rs # Main TUI application logic
├── input.rs # User input handling (filter, service type)
├── popup.rs # Popup UI components (help, metrics)
├── scroll.rs # Scroll state management
├── models.rs # Data models
└── terminal.rs # Terminal management
The project uses Cargo for building:
cargo run- Run the TUI applicationcargo build --release- Build optimized release version
- ✓ Prohibited terms or links
- ✓ Repository eligibility
- ✓ slopscore.md paperwork
- ✓ Content policy
- ✓ Risk review

0 comments
log in to comment.