Waybar stats daemon written in go with pure std library.
Find a file
2025-09-30 13:01:39 +02:00
config added 'dots' as graph option 2025-09-26 20:41:13 +02:00
modules fixed diagrams 2025-09-30 13:01:39 +02:00
config.toml - 2025-09-23 23:45:31 +02:00
config.toml.priv wip 2025-09-25 17:32:14 +02:00
go.mod - 2025-09-23 23:45:31 +02:00
go.sum - 2025-09-23 23:45:31 +02:00
main.go wip 2025-09-25 12:57:53 +02:00
Makefile wip 2025-09-25 18:31:32 +02:00
README.md wip 2025-09-25 18:51:51 +02:00

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.

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:

  1. Create a new package in modules/yourmodule/
  2. Implement the Module interface:
type Module interface {
    Init(cfg config.ModuleConfig) error
    Update(ctx context.Context) error
    GetStats() Stats
    OnClick(button int)
    Close() error
}
  1. 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

  1. No output: Check stderr for errors: ./waybar-stats 2>error.log
  2. High CPU: Increase update intervals in config
  3. Permission errors: Ensure /proc and /sys are readable
  4. 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.