config | ||
modules | ||
config.toml | ||
config.toml.priv | ||
go.mod | ||
go.sum | ||
main.go | ||
Makefile | ||
README.md |
Waybar Stats Daemon
A production-ready Go daemon for system monitoring that outputs JSON formatted stats compatible with Waybar's custom modules.
Features
- Modular Architecture: Easy to extend with new metrics
- Concurrent Updates: Non-blocking goroutines for each module
- Low Resource Usage: Efficient memory management with rolling buffers
- Interactive: Click to toggle between different views
- Visual Graphs: Unicode block characters for real-time graphs
- Thread-Safe: Proper synchronization with mutexes
Modules
CPU Module
- Real-time CPU usage percentage
- 5-minute history buffer with averaging
- Unicode graph visualization (10 blocks)
- Click to toggle graph display
Memory Module
- Shows used/total or available memory
- Mini graph visualization (5 blocks)
- Color-coded CSS classes based on usage
- Click to toggle between views
Network Module
- Displays IP address or upload/download speeds
- Automatic interface detection (WiFi/Ethernet)
- Optional ping latency monitoring
- Click to toggle between IP and speed view
Building
# Clone the project structure
git clone --depth=1 https://git.k4li.de/pika/waybar-stats.git
# Build the daemon
cd waybar-stats
make
# Build and install the daemon
sudo make install
Waybar Configuration
Add to your Waybar config (~/.config/waybar/config
):
{
"modules-right": ["custom/cpu", "custom/memory", "custom/network"],
"custom/cpu": {
"exec": "waybar-stats --cpu 2>/dev/null",
"return-type": "json",
"format": "{}",
"interval": "continuous",
"on-click": "pkill -SIGUSR1 waybar-stats"
},
"custom/memory": {
"exec": "waybar-stats --memory 2>/dev/null",
"return-type": "json",
"format": "{}",
"interval": "continuous",
"on-click": "pkill -SIGUSR2 waybar-stats"
},
"custom/network": {
"exec": "waybar-stats --network 2>/dev/null",
"return-type": "json",
"format": "{}",
"interval": "continuous"
}
}
Alternative: Single Module Approach
If you prefer a single custom module for all stats:
{
"custom/stats": {
"exec": "waybar-stats 2>/dev/null",
"return-type": "json",
"format": "{} {} {}",
"interval": "continuous"
}
}
Waybar Styles
Add to your Waybar style.css (~/.config/waybar/style.css
):
/* CPU Module */
#custom-cpu {
color: #8fbcbb;
padding: 0 10px;
}
#custom-cpu.cpu-high {
color: #bf616a;
animation: blink 1s linear infinite;
}
#custom-cpu.cpu-medium {
color: #d08770;
}
/* Memory Module */
#custom-memory {
color: #88c0d0;
padding: 0 10px;
}
#custom-memory.memory-high {
color: #d08770;
}
#custom-memory.memory-critical {
color: #bf616a;
font-weight: bold;
}
/* Network Module */
#custom-network {
color: #a3be8c;
padding: 0 10px;
}
#custom-network.network-disconnected {
color: #bf616a;
}
@keyframes blink {
50% { opacity: 0.5; }
}
CLI Flags and Configuration
You can select modules via CLI and still use the config for extra options.
Flags:
--cpu
,--memory
,--network
: enable a subset of modules. If none are set, all enabled modules run.--cpu-graph
: force CPU graph view. Without it (and with--cpu
), percentage-only.--memory-graph
: force Memory to include its mini graph. Without it (and with--memory
), shows value only.--network-graph
: show network speeds instead of IP.-config <path>
: optional config file path.- Graph-only behavior for
--*-graph
: only graph content is emitted for that module.
- Graph-only behavior for
Configuration Files
The daemon supports both TOML and JSON configuration files. If no config path is specified, it will look for:
~/.config/waybar-stats/config.toml
~/.config/waybar-stats/config.json
~/.config/waybar-stats/config.yml
Template System
You can customize the display format using template strings with placeholders:
CPU Module Placeholders:
{icon}
- Custom icon{usage}
- CPU usage percentage (e.g., "45%"){usage_1}
- CPU usage with 1 decimal (e.g., "45.2%"){graph}
- CPU graph visualization (fixed-width, scrolling){current}
- Current CPU usage{avg}
- 5-minute average{avg_5min}
- 5-minute average
Memory Module Placeholders:
{icon}
- Custom icon{used}
- Used memory in GB{total}
- Total memory in GB{available}
- Available memory in GB{percent}
- Usage percentage{percent_0}
- Usage percentage (no decimals){graph}
- Memory graph visualization (fixed-width, scrolling){buffers}
- Buffer memory in GB{cached}
- Cached memory in GB
Network Module Placeholders:
{icon}
- Custom icon{ip}
- IP address{cidr}
- CIDR prefix (e.g., 24){interface}
- Network interface name{rx_speed}
- Download speed{tx_speed}
- Upload speed{rx_graph}
- Download speed graph (fixed-width, scrolling){tx_graph}
- Upload speed graph (fixed-width, scrolling){rx_total}
- Total downloaded{tx_total}
- Total uploaded{ping}
- Ping latency with units{ping_ms}
- Ping latency in milliseconds
Example TOML Configuration
output_interval = "1s"
[modules.cpu]
enabled = true
interval = "1s"
icon = "🖥️"
text = "{icon} {usage}"
tooltip = "CPU: {current}\n5-min avg: {avg_5min}"
[modules.cpu.options]
graph_width = 10
show_graph = true
[modules.memory]
enabled = true
interval = "2s"
icon = "💾"
text = "{icon} {used}/{total} GB"
tooltip = "Memory: {used}/{total} GB ({percent})\nAvailable: {available} GB"
[modules.memory.options]
show_used = true
show_graph = true
[modules.network]
enabled = true
interval = "1s"
icon = "🌐"
text = "{icon} {ip}"
tooltip = "Interface: {interface}\nIP: {ip}\nDown: {rx_speed}\nUp: {tx_speed}\nPing: {ping}"
[modules.network.options]
ping_host = "8.8.8.8"
show_ip = true
Configuration Options
Option | Description | Default |
---|---|---|
output_interval |
How often to output JSON | 1s |
modules.<name>.enabled |
Enable/disable module | true |
modules.<name>.interval |
Update interval for module | 1s |
modules.<name>.icon |
Custom icon for module | "" |
modules.<name>.text |
Custom text template | "" (uses default) |
modules.<name>.tooltip |
Custom tooltip template | "" (uses default) |
modules.cpu.options.graph_width |
Width of CPU graph | 10 |
modules.cpu.options.show_graph |
Show CPU graph | true or set by --cpu[-graph] |
modules.memory.options.show_used |
Show used instead of free | true |
modules.memory.options.show_graph |
Show memory graph | true or set by --memory[-graph] |
modules.network.options.ping_host |
Host to ping for latency | 8.8.8.8 |
modules.network.options.show_ip |
Show IP (true) or speeds (false) | true or set by --network[-graph] |
Adding New Modules
To add a new module:
- Create a new package in
modules/yourmodule/
- Implement the
Module
interface:
type Module interface {
Init(cfg config.ModuleConfig) error
Update(ctx context.Context) error
GetStats() Stats
OnClick(button int)
Close() error
}
- Register in
main.go
:
daemon.RegisterModule("yourmodule", yourmodule.New())
Systemd Service
Create /etc/systemd/system/waybar-stats.service
:
[Unit]
Description=Waybar Stats Daemon
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/waybar-stats
Restart=always
User=yourusername
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=default.target
Enable and start:
sudo systemctl enable waybar-stats
sudo systemctl start waybar-stats
Performance
- CPU Usage: < 0.5% on modern systems
- Memory Usage: ~5-10MB RSS
- Update Frequency: Configurable per module
- History Buffers: Limited to prevent memory growth
Troubleshooting
- No output: Check stderr for errors:
./waybar-stats 2>error.log
- High CPU: Increase update intervals in config
- Permission errors: Ensure
/proc
and/sys
are readable - Network module issues: Check interface names with
ip addr
License
MIT License - Feel free to use and modify as needed.
Contributing
The modular architecture makes it easy to contribute new modules. Follow the existing patterns and ensure thread-safety.