elkowar/eww
ElKowars wacky widgets
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 2mo ago
- ✓41+ active contributors
- ✓Distributed ownership (top contributor 38% of recent commits)
Show all 6 evidence items →Show less
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/elkowar/eww)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/elkowar/eww on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: elkowar/eww
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/elkowar/eww shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 2mo ago
- 41+ active contributors
- Distributed ownership (top contributor 38% of recent commits)
- MIT licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live elkowar/eww
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/elkowar/eww.
What it runs against: a local clone of elkowar/eww — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in elkowar/eww | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 93 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of elkowar/eww. If you don't
# have one yet, run these first:
#
# git clone https://github.com/elkowar/eww.git
# cd eww
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of elkowar/eww and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "elkowar/eww(\\.git)?\\b" \\
&& ok "origin remote is elkowar/eww" \\
|| miss "origin remote is not elkowar/eww (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "crates/eww/src/main.rs" \\
&& ok "crates/eww/src/main.rs" \\
|| miss "missing critical file: crates/eww/src/main.rs"
test -f "crates/eww/src/app.rs" \\
&& ok "crates/eww/src/app.rs" \\
|| miss "missing critical file: crates/eww/src/app.rs"
test -f "crates/eww/src/config/eww_config.rs" \\
&& ok "crates/eww/src/config/eww_config.rs" \\
|| miss "missing critical file: crates/eww/src/config/eww_config.rs"
test -f "crates/eww/src/widgets/build_widget.rs" \\
&& ok "crates/eww/src/widgets/build_widget.rs" \\
|| miss "missing critical file: crates/eww/src/widgets/build_widget.rs"
test -f "crates/simplexpr/src/lib.rs" \\
&& ok "crates/simplexpr/src/lib.rs" \\
|| miss "missing critical file: crates/simplexpr/src/lib.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 93 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~63d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/elkowar/eww"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Eww is a standalone widget system written in Rust that lets you create custom, composable widgets for any Linux window manager using a YUCK-based declarative syntax compiled to GTK. It solves the problem of rigid polybar/i3blocks workflows by providing a scriptable, real-time widget engine with built-in state management, script variables, and system stat monitoring. Monorepo with crates/eww as the main application. Core modules: config/ (YUCK parsing, window definitions, SCSS compilation), state/ (scope graph and reactive state management), widgets/ (built-in widget definitions), ipc_server.rs (daemon communication), display_backend.rs (GTK abstraction). Examples/ folder contains reference configurations. CLI entry via main.rs with opts.rs for argument handling.
👥Who it's for
Linux desktop rice enthusiasts and window manager users (i3, sway, bspwm) who want pixel-perfect custom bars, system monitors, and floating widgets without learning GTK directly. Developers who prefer declaring UIs in a functional configuration language over imperative widget code.
🌱Maturity & risk
Actively developed and production-ready: the project has significant community adoption (examples from 10+ public setups), comprehensive GitHub Actions CI (build.yml, gh-pages.yml), and a documented migration path (YUCK_MIGRATION.md). Regular updates and issue engagement visible; suitable for users willing to follow along with occasional breaking changes.
Single-maintainer project (elkowar) with moderate Rust complexity and GTK bindings (gtk 0.18.1), creating potential maintenance risk. Dependency surface is substantial (40+ workspace deps including tokio, zbus, jaq for jq-like filtering, grass for SCSS). Risk is mitigated by stable Rust ecosystem and active community contributions.
Active areas of work
Active maintenance with recent dependency updates (tokio 1.39.2, gtk 0.18.1, chrono 0.4.38). Project is transitioning users from old to new YUCK syntax (YUCK_MIGRATION.md exists). GitHub workflows include automated docs publishing (gh-pages.yml) and multi-platform builds. No visible stalled PRs; issue templates show structured bug/feature intake.
🚀Get running
Clone and build with Cargo: git clone https://github.com/elkowar/eww && cd eww && cargo build --release. Binary will be in target/release/eww. Install dependencies: GTK 3.0+ dev libraries (libgtk-3-dev on Debian). Run ./target/release/eww daemon to start the daemon, then eww open window-name from config.
Daily commands:
cargo build --release produces the binary. Start daemon: ./target/release/eww daemon. Open a window: eww open mywindow. Watch config: eww watch. Logs: check systemd journal or run with RUST_LOG=debug eww daemon.
🗺️Map of the codebase
crates/eww/src/main.rs— Application entry point and CLI argument parsing; all contributors must understand the command structure and daemon/client lifecyclecrates/eww/src/app.rs— Core application state and window lifecycle management; essential for understanding how widgets are initialized and renderedcrates/eww/src/config/eww_config.rs— Configuration parsing and validation; defines the canonical data structures for widget definitions and window layoutscrates/eww/src/widgets/build_widget.rs— Widget compilation and rendering logic; the bridge between configuration and GTK widget tree constructioncrates/simplexpr/src/lib.rs— Expression evaluation engine used throughout the codebase for dynamic values and script variablescrates/eww/src/state/scope.rs— Variable scoping and state management system; critical for understanding reactive data flow in widgetscrates/eww/src/ipc_server.rs— IPC protocol and daemon communication; essential for understanding client-server architecture and window control commands
🛠️How to make changes
Add a new built-in widget type
- Define the widget struct and properties in crates/eww/src/widgets/widget_definitions.rs (
crates/eww/src/widgets/widget_definitions.rs) - Implement widget-specific build logic in crates/eww/src/widgets/build_widget.rs in the build_widget() function (
crates/eww/src/widgets/build_widget.rs) - Add CSS property handling in crates/eww/src/widgets/transform.rs if custom styling is needed (
crates/eww/src/widgets/transform.rs) - Update configuration parsing in crates/eww/src/config/eww_config.rs to recognize the new widget in defwidgets (
crates/eww/src/config/eww_config.rs)
Add a new script variable type
- Define the variable configuration in crates/eww/src/config/script_var.rs (
crates/eww/src/config/script_var.rs) - Implement the execution logic in crates/eww/src/script_var_handler.rs (
crates/eww/src/script_var_handler.rs) - Register the variable type in the main config parser crates/eww/src/config/eww_config.rs (
crates/eww/src/config/eww_config.rs) - Ensure state propagation through crates/eww/src/state/scope.rs for reactive updates (
crates/eww/src/state/scope.rs)
Add a new IPC command
- Add the command variant to the command enum in crates/eww/src/ipc_server.rs (
crates/eww/src/ipc_server.rs) - Implement the handler logic in the process_command() function in crates/eww/src/ipc_server.rs (
crates/eww/src/ipc_server.rs) - Add CLI option parsing in crates/eww/src/opts.rs to expose the command (
crates/eww/src/opts.rs) - Implement client-side invocation in crates/eww/src/client.rs if it's a client command (
crates/eww/src/client.rs)
Add a new expression function
- Define the function signature in crates/simplexpr/src/ast.rs as a new function call variant (
crates/simplexpr/src/ast.rs) - Implement the function evaluation logic in crates/simplexpr/src/eval.rs (
crates/simplexpr/src/eval.rs) - Update the parser in crates/simplexpr/src/parser/mod.rs to recognize the function name (
crates/simplexpr/src/parser/mod.rs) - Add test snapshots in crates/simplexpr/src/parser/snapshots/ directory (
crates/simplexpr/src/parser/snapshots)
🔧Why these technologies
- Rust + GTK-rs — Provides memory safety, performance, and cross-platform widget rendering; GTK is well-established for X11/Wayland compatibility
- Custom expression engine (simplexpr) — Enables dynamic widget configuration without external scripting language; lightweight and sandboxed
- **** — undefined
🪤Traps & gotchas
X11/Wayland differences: eww uses GTK window properties that behave differently across display servers (strut exclusion, override-redirect). SCSS compilation is synchronous (grass crate), failures will stall the daemon. Script variables poll with custom intervals; excessive polling drains CPU. State updates are single-threaded within tokio; long-running script vars block the entire daemon. Window names must be unique and match config exactly. IPC assumes systemd user session (zbus over session bus). GTK theming requires proper GTK CSS knowledge; eww doesn't validate CSS syntax early.
🏗️Architecture
💡Concepts to learn
- Reactive Scope Graph — Eww's state system is built on a scope graph where variables propagate changes reactively to dependent widgets; understanding this is critical to debugging state management bugs and adding dynamic features
- LALRPOP Parser Generator — The YUCK language is parsed using lalrpop (crates/yuck); contributors working on the DSL need to understand how grammar rules map to AST nodes
- GTK Widget Hierarchy & Properties — Eww builds on GTK 3 widget tree; understanding GTK's property binding, signals, and CSS theming is essential for adding widgets or fixing rendering issues
- D-Bus / zbus for IPC — Eww daemon communicates with CLI clients via D-Bus (zbus crate); this is how config reloads and window commands flow between processes
- Event-Driven Script Variables — External scripts can feed data to eww via polling or event subscriptions; the script_var_handler.rs manages lifecycle and throttling to avoid daemon hangs
- Declarative UI via YUCK Language — YUCK is a Lisp-like functional language for declaring widget trees and styling; learning its semantics (e.g., keyword args, closures, variable binding) is essential for users and config contributors
- Workspace Resolver & Monorepo Structure — This Cargo workspace uses resolver='2' and path dependencies (simplexpr, yuck, eww_shared_util); understanding dependency graph and shared crates helps with cross-crate changes
🔗Related repos
polybar/polybar— Direct predecessor; eww was built as a more flexible, programmable alternative to polybar's rigid module systemdavatorium/rofi— Complementary X11/Wayland tool for menus and launchers; often integrated with eww bars via scriptingelkowar/yolk— Companion project by the same author; dotfile manager often used to distribute eww configurationsnwg-pz/nwg-panel— Alternative Wayland-native panel system; similar goal but GTK/wlroots instead of pure Rustactix/actix-web— Not directly related but tokio ecosystem reference; eww's async model follows similar patterns
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for state management (crates/eww/src/state/)
The state directory contains critical modules (scope.rs, scope_graph.rs, one_to_n_elements_map.rs) with only a test.rs file. Given this is a widget system handling reactive state, comprehensive unit tests for scope graph traversal, state mutation, and element mapping would catch regressions early and improve maintainability. This directly supports the complex state management required for widget reactivity.
- [ ] Add unit tests in crates/eww/src/state/scope.rs for scope creation, variable binding, and lookup operations
- [ ] Add unit tests in crates/eww/src/state/scope_graph.rs for graph traversal, parent-child relationships, and scope isolation
- [ ] Add unit tests in crates/eww/src/state/one_to_n_elements_map.rs for insertion, removal, and batch operations
- [ ] Ensure tests cover edge cases like circular references and orphaned scopes
- [ ] Run with
cargo test --libto verify integration with existing test.rs
Add GitHub Actions workflow for dependency auditing and MSRV validation
The repo has build.yml and gh-pages.yml workflows but lacks automated dependency security checks and Minimum Supported Rust Version (MSRV) testing. Given the workspace uses many external crates (gtk, tokio, zbus, etc.) and the Cargo.toml specifies specific versions, adding cargo-audit for security vulnerabilities and MSRV testing would prevent supply chain issues and ensure compatibility across Rust versions.
- [ ] Create .github/workflows/security-audit.yml with cargo-audit step to check for known vulnerabilities
- [ ] Add MSRV field to Cargo.toml (recommend 1.70+) and create matrix test in build.yml for multiple Rust versions
- [ ] Configure the workflow to fail on high/critical vulnerabilities and run on PRs
- [ ] Document the MSRV policy in CONTRIBUTING.md or README.md
Add integration tests for widget rendering pipeline (crates/eww/src/widgets/)
The widgets directory contains specialized widgets (circular_progressbar.rs, graph.rs, systray.rs, transform.rs, window.rs) but lacks integration tests verifying the build_widget.rs compilation pipeline. Testing how widget definitions are parsed, built, and rendered would catch issues in the widget macro system (def_widget_macro.rs) early and document expected widget behavior.
- [ ] Create crates/eww/tests/widget_compilation_tests.rs to test build_widget.rs pipeline with sample widget definitions
- [ ] Add test cases for each widget type in crates/eww/src/widgets/widget_definitions.rs (button, box, label, etc.)
- [ ] Test widget property binding and state reactivity through the build pipeline
- [ ] Verify transform.rs correctly applies CSS transforms to rendered output
- [ ] Run with
cargo test --test widget_compilation_teststo ensure tests execute separately from unit tests
🌿Good first issues
- Add unit tests for crates/eww/src/config/scss.rs SCSS compilation (grass integration) to catch parsing errors early and improve error messages
- Document the scope graph state model with diagrams in docs/architecture/state-management.md, explaining how variable binding and reactivity work for new contributors
- Implement a built-in widget example: add a
<battery>widget in src/widgets/ that reads from /sys/class/power_supply using sysinfo, with test cases in src/widgets/test.rs
⭐Top contributors
Click to expand
Top contributors
- @w-lfchen — 38 commits
- @elkowar — 9 commits
- @ovalkonia — 6 commits
- @moetayuko — 4 commits
- @inkreasing — 3 commits
📝Recent commits
Click to expand
Recent commits
865cf63— Fix typo (#1422) (abghim)fddb4a0— addformatbytesto expressions (#1333) (topongo)0e409d4— Improve multi-monitor handling under wayland (#1276) (bkueng)98c2201— Fix crash on invalid formattime (#1317) (inkreasing)15315a0— Add wordchar wrap mode (#1306) (UnnaturalTwilight)e953141— Fix crash on NaN or infinite graph value (#1318) (inkreasing)20d0997— fix documentation of ceil and floor (fixes #1319) (elkowar)2c6523a— Add floor() and ceil() (#1315) (wsbankenstein)eb59d15— Add warning for invalid exclusive and anchor combination (#1316) (inkreasing)c999033— Add wikipedia link to widget essay (elkowar)
🔒Security observations
The Eww widget system shows reasonable security posture overall, being a Rust-based application with memory safety guarantees. However, several moderate concerns exist around script execution, expression evaluation from user input, and IPC security. The main risks stem from the dynamic nature of widget configuration and expression evaluation. Critical areas requiring attention: (1) Command injection prevention in script variable execution, (2) Sandboxing/validation of expression evaluation, and (3) Authentication/authorization for IPC daemon access. The codebase lacks visible evidence of hardcoded secrets or SQL injection risks. Recommended immediate actions: implement strict input validation across user-controllable configuration, add IPC authentication, and document security assumptions for widget developers.
- Medium · Potential Command Injection via Script Variables —
crates/eww/src/config/script_var.rs, crates/eww/src/script_var_handler.rs. The codebase includes script_var_handler.rs and script_var.rs which suggest execution of user-defined scripts. If user input from config files is not properly sanitized before being passed to shell execution, this could lead to command injection attacks. Fix: Implement strict input validation and sanitization for all script variables. Use safe APIs for process execution (e.g., std::process::Command with argument arrays rather than shell strings). Avoid shell interpolation of user-controlled data. - Medium · Expression Evaluation from User Input —
crates/simplexpr/src/eval.rs, crates/eww/src/ipc_server.rs. The simplexpr crate provides expression evaluation capabilities. If expressions are evaluated based on untrusted user input from config files or IPC messages without proper validation, this could lead to code injection or information disclosure. Fix: Ensure all expressions come from trusted sources (local config files with proper permissions). Implement sandboxing or expression whitelisting. Add comprehensive input validation before expression evaluation. - Medium · IPC Server Security —
crates/eww/src/ipc_server.rs. The ipc_server.rs handles inter-process communication. Without proper authentication and authorization checks, unauthorized processes could potentially communicate with the daemon and execute arbitrary widget commands or access sensitive data. Fix: Implement authentication mechanisms for IPC connections (e.g., socket permissions, credential checking). Validate all IPC messages. Use Unix socket file permissions to restrict access to the daemon socket. - Low · Dependency on External System Information —
crates/eww/src/config/system_stats.rs. The system_stats.rs and sysinfo dependency expose system information. While not a direct vulnerability, ensure this data exposure doesn't leak sensitive system details in unsecured widget displays. Fix: Document which system information is exposed. Provide options to restrict sensitive data exposure (e.g., disable certain stats). Consider user privacy implications. - Low · File Database Access Controls —
crates/eww/src/file_database.rs. The file_database.rs module manages file operations. If file paths are derived from user input without proper validation, this could lead to directory traversal attacks. Fix: Implement strict path validation using canonicalization and whitelist checks. Prevent directory traversal via '..' sequences. Ensure file operations are restricted to intended directories. - Low · D-Bus Integration Security —
crates/notifier_host/src/host.rs, crates/notifier_host/src/proxy/. The notifier_host crate integrates with D-Bus for system notifications. Ensure proper validation of D-Bus method calls and signal handling to prevent unauthorized access. Fix: Validate all D-Bus service names and paths. Implement proper method call filtering. Review D-Bus interface definitions for security implications. Use restrictive D-Bus policy files. - Low · Hardcoded Configuration Paths —
crates/eww/src/paths.rs, crates/eww/src/config/eww_config.rs. Configuration files are loaded from paths defined in paths.rs. If these paths are world-writable or predictable, users could potentially inject malicious configurations. Fix: Ensure config directories and files have restrictive permissions (0700 for directories, 0600 for files). Validate file ownership. Document security expectations for config file locations.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.