{"id":45090583,"url":"https://github.com/torvaldz/monique","last_synced_at":"2026-04-06T20:01:22.888Z","repository":{"id":339347407,"uuid":"1161539429","full_name":"ToRvaLDz/monique","owner":"ToRvaLDz","description":"MONitor Integrated QUick Editor — graphical monitor configurator for Hyprland and Sway","archived":false,"fork":false,"pushed_at":"2026-02-22T18:06:32.000Z","size":878,"stargazers_count":64,"open_issues_count":5,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-25T00:17:03.267Z","etag":null,"topics":["archlinux","gtk4","hyprland","linux","monitor-configuration","python","sway","wayland"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ToRvaLDz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"liberapay":"MarcoMigozzi"}},"created_at":"2026-02-19T08:19:22.000Z","updated_at":"2026-02-24T22:32:26.000Z","dependencies_parsed_at":"2026-02-22T20:01:30.374Z","dependency_job_id":null,"html_url":"https://github.com/ToRvaLDz/monique","commit_stats":null,"previous_names":["torvaldz/monique"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/ToRvaLDz/monique","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ToRvaLDz%2Fmonique","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ToRvaLDz%2Fmonique/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ToRvaLDz%2Fmonique/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ToRvaLDz%2Fmonique/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ToRvaLDz","download_url":"https://codeload.github.com/ToRvaLDz/monique/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ToRvaLDz%2Fmonique/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29844845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-25T22:37:40.667Z","status":"ssl_error","status_checked_at":"2026-02-25T22:37:25.960Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["archlinux","gtk4","hyprland","linux","monitor-configuration","python","sway","wayland"],"created_at":"2026-02-19T17:00:23.614Z","updated_at":"2026-04-06T20:01:22.880Z","avatar_url":"https://github.com/ToRvaLDz.png","language":"Python","funding_links":["https://liberapay.com/MarcoMigozzi"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/ToRvaLDz/monique/main/data/com.github.monique.svg\" width=\"96\" alt=\"Monique icon\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eMonique\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cb\u003eMON\u003c/b\u003eitor \u003cb\u003eI\u003c/b\u003entegrated \u003cb\u003eQU\u003c/b\u003eick \u003cb\u003eE\u003c/b\u003editor\n  \u003cbr\u003e\n  Graphical monitor configurator for \u003cb\u003eHyprland\u003c/b\u003e, \u003cb\u003eSway\u003c/b\u003e and \u003cb\u003eNiri\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/ToRvaLDz/monique/actions/workflows/ci.yml\"\u003e\u003cimg alt=\"CI\" src=\"https://github.com/ToRvaLDz/monique/actions/workflows/ci.yml/badge.svg?v=0.6.2\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/ToRvaLDz/monique/releases/latest\"\u003e\u003cimg alt=\"Release\" src=\"https://img.shields.io/github/v/release/ToRvaLDz/monique?include_prereleases\u0026label=release\u0026color=orange\u0026v=0.6.2\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/monique/\"\u003e\u003cimg alt=\"PyPI\" src=\"https://img.shields.io/pypi/v/monique?color=blue\u0026label=PyPI\u0026v=0.6.2\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://aur.archlinux.org/packages/monique\"\u003e\u003cimg alt=\"AUR\" src=\"https://img.shields.io/aur/version/monique?color=1793d1\u0026label=AUR\u0026v=0.6.2\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg alt=\"License: GPL-3.0\" src=\"https://img.shields.io/badge/license-GPL--3.0-blue\"\u003e\u003c/a\u003e\n  \u003cimg alt=\"Python 3.11+\" src=\"https://img.shields.io/badge/python-3.11+-green\"\u003e\n  \u003cimg alt=\"GTK4 + Adwaita\" src=\"https://img.shields.io/badge/toolkit-GTK4%20%2B%20Adwaita-purple\"\u003e\n  \u003cbr\u003e\n  \u003ca href=\"https://github.com/ToRvaLDz/monique/stargazers\"\u003e\u003cimg alt=\"Stars\" src=\"https://img.shields.io/github/stars/ToRvaLDz/monique?style=flat\u0026color=yellow\u0026v=0.6.2\"\u003e\u003c/a\u003e\n  \u003cimg alt=\"Last commit\" src=\"https://img.shields.io/github/last-commit/ToRvaLDz/monique?color=teal\u0026v=0.6.2\"\u003e\n  \u003cimg alt=\"Repo size\" src=\"https://img.shields.io/github/repo-size/ToRvaLDz/monique?color=gray\u0026v=0.6.2\"\u003e\n  \u003cbr\u003e\n  \u003cimg alt=\"Hyprland\" src=\"https://img.shields.io/badge/Hyprland-%2358e1ff?logo=hyprland\u0026logoColor=white\"\u003e\n  \u003cimg alt=\"Sway\" src=\"https://img.shields.io/badge/Sway-%2368751a?logo=sway\u0026logoColor=white\"\u003e\n  \u003cimg alt=\"Niri\" src=\"https://img.shields.io/badge/Niri-%23c77dff\"\u003e\n  \u003cimg alt=\"Wayland\" src=\"https://img.shields.io/badge/Wayland-%23ffbc00?logo=wayland\u0026logoColor=black\"\u003e\n\u003c/p\u003e\n\n---\n\n## Screenshots\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\n      \u003ca href=\"https://raw.githubusercontent.com/ToRvaLDz/monique/main/data/screenshots/1.png\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/ToRvaLDz/monique/main/data/screenshots/1.png\" width=\"400\" alt=\"Monitor layout editor\"\u003e\u003c/a\u003e\n      \u003cbr\u003e\u003csub\u003eLayout editor\u003c/sub\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\n      \u003ca href=\"https://raw.githubusercontent.com/ToRvaLDz/monique/main/data/screenshots/2.png\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/ToRvaLDz/monique/main/data/screenshots/2.png\" width=\"400\" alt=\"Workspace rules\"\u003e\u003c/a\u003e\n      \u003cbr\u003e\u003csub\u003eWorkspace rules\u003c/sub\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\n      \u003ca href=\"https://raw.githubusercontent.com/ToRvaLDz/monique/main/data/screenshots/3.png\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/ToRvaLDz/monique/main/data/screenshots/3.png\" width=\"400\" alt=\"Quick setup wizard\"\u003e\u003c/a\u003e\n      \u003cbr\u003e\u003csub\u003eQuick setup\u003c/sub\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\n      \u003ca href=\"https://raw.githubusercontent.com/ToRvaLDz/monique/main/data/screenshots/4.png\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/ToRvaLDz/monique/main/data/screenshots/4.png\" width=\"400\" alt=\"SDDM preferences\"\u003e\u003c/a\u003e\n      \u003cbr\u003e\u003csub\u003eSDDM integration\u003c/sub\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Features\n\n- **Drag-and-drop layout** — arrange monitors visually on an interactive canvas\n- **Multi-backend** — auto-detects Hyprland, Sway, or Niri from the environment\n- **Cross-write** — save a profile in any compositor and automatically generate config files for the others (e.g. configure in Hyprland → get Sway and Niri configs for free)\n- **Profile system** — save, load, and switch between monitor configurations\n- **Hotplug daemon** (`moniqued`) — automatically applies the best matching profile when monitors are connected or disconnected\n- **Display manager integration** — syncs your layout to the login screen for SDDM (xrandr) and greetd (sway), with polkit rule for passwordless writes\n- **Workspace rules** — configure workspace-to-monitor assignments (Hyprland/Sway)\n- **Live preview** — OSD overlay to identify monitors (double-click)\n- **Workspace migration** — automatically moves workspaces to the primary monitor when their monitor is disabled or unplugged (reverted if you click \"Revert\")\n- **Clamshell mode** — disable the internal laptop display when external monitors are connected (manual toggle in the toolbar or automatic via daemon preferences); the daemon also monitors the lid state via UPower D-Bus\n- **Confirm-or-revert** — 10-second countdown after applying, auto-reverts if display is unusable\n\n## Installation\n\n### AUR (Arch Linux / CachyOS)\n\n```bash\nyay -S monique\n```\n\nOr manually:\n\n```bash\ngit clone https://aur.archlinux.org/monique.git\ncd monique\nmakepkg -si\n```\n\n### NixOS / Nix\n\n**Con flake** (raccomandato) — aggiungilo come input e usa il modulo NixOS:\n\n```nix\n# flake.nix\ninputs.monique.url = \"github:ToRvaLDz/monique\";\n\n# configuration.nix (tramite module)\n{ inputs, ... }: {\n  imports = [ inputs.monique.nixosModules.default ];\n  programs.monique.enable = true;\n}\n```\n\n**Run senza installare:**\n\n```bash\nnix run github:ToRvaLDz/monique\n```\n\n**Installazione nello user profile:**\n\n```bash\nnix profile install github:ToRvaLDz/monique\n```\n\n**Con overlay:**\n\n```nix\nnixpkgs.overlays = [ inputs.monique.overlays.default ];\nenvironment.systemPackages = [ pkgs.monique ];\n```\n\n\u003e **Nota polkit:** il modulo NixOS installa automaticamente la regola polkit per le scritture su SDDM/greetd senza password. Disabilitabile con `programs.monique.enablePolkit = false`.\n\n### PyPI\n\n```bash\npip install monique\n```\n\n### From source\n\n```bash\ngit clone https://github.com/ToRvaLDz/monique.git\ncd monique\npip install .\n```\n\n**Runtime dependencies:**\n\n| Distro | Packages |\n|--------|----------|\n| Arch / CachyOS | `python python-gobject gtk4 libadwaita` |\n| Fedora | `python3 python3-gobject gtk4 libadwaita` |\n| openSUSE | `python3 python3-gobject gtk4 libadwaita typelib-1_0-Adw-1 typelib-1_0-Gtk-4_0` |\n| Ubuntu / Debian | `python3 python3-gi gir1.2-gtk-4.0 gir1.2-adw-1 libadwaita-1-0` |\n| NixOS | gestito automaticamente dal flake |\n\n**Optional:** `python-pyudev` (hardware hotplug detection for Niri)\n\n## Usage\n\n### GUI\n\n```bash\nmonique\n```\n\nOpen the graphical editor to arrange monitors, set resolutions, scale, rotation, and manage profiles.\n\n### Daemon\n\n```bash\nmoniqued\n```\n\nOr enable the systemd user service:\n\n```bash\nsystemctl --user enable --now moniqued\n```\n\nThe daemon auto-detects the active compositor and listens for monitor hotplug events. When a monitor is connected or disconnected, it waits 500ms (debounce) then applies the best matching profile. On Niri, the daemon uses udev DRM events (via `pyudev`) for reliable hardware hotplug detection. Orphaned workspaces are automatically migrated to the primary monitor on Hyprland/Sway (configurable via **Preferences \u003e Migrate workspaces**).\n\n#### Clamshell mode\n\nOn laptops, the daemon can automatically disable the internal display when external monitors are connected. Enable it from the GUI: **Menu \u003e Preferences \u003e Clamshell Mode**.\n\nThe daemon also monitors the laptop lid state via UPower D-Bus: closing the lid disables the internal display, opening it re-enables it. On desktop PCs (no lid detected), clamshell mode simply disables any internal-type output (`eDP`, `LVDS`) whenever external monitors are present.\n\n\u003e **Note:** if your system suspends on lid close, set `HandleLidSwitch=ignore` in `/etc/systemd/logind.conf` so the daemon can handle it instead.\n\n### Behavior per environment\n\n| Environment | Detection | Events |\n|---|---|---|\n| Hyprland | `$HYPRLAND_INSTANCE_SIGNATURE` | `monitoradded` / `monitorremoved` via socket2 |\n| Sway | `$SWAYSOCK` | `output` events via i3-ipc subscribe |\n| Niri | `$NIRI_SOCKET` | udev DRM subsystem (with `pyudev`), IPC fallback |\n| Neither | Warning, retry every 5s | — |\n\n## Display manager integration\n\nMonique can sync your monitor layout to the login screen for supported display managers.\n\n| Display Manager | Method | Config path |\n|---|---|---|\n| SDDM | xrandr via `Xsetup` script | `/usr/share/sddm/scripts/Xsetup` |\n| greetd (sway) | sway `output` commands | `/etc/greetd/monique-monitors.conf` |\n\nA polkit rule is included to allow passwordless writes:\n\n```bash\n# Installed automatically by the PKGBUILD to:\n# /usr/share/polkit-1/rules.d/60-com.github.monique.rules\n```\n\nToggle from the GUI: **Menu \u003e Preferences \u003e Update SDDM Xsetup** or **Update greetd config**.\n\n## Configuration\n\nAll configuration is stored in `~/.config/monique/`:\n\n```\n~/.config/monique/\n├── profiles/\n│   ├── Home.json\n│   └── Office.json\n└── settings.json\n```\n\nMonitor config files are written to the compositor's config directory:\n- **Hyprland:** `~/.config/hypr/monitors.conf`\n- **Sway:** `~/.config/sway/monitors.conf`\n- **Niri:** `~/.config/niri/monitors.kdl`\n\n## Project structure\n\n```\nsrc/monique/\n├── app.py               # Application entry point\n├── window.py            # Main GTK4/Adwaita window\n├── canvas.py            # Monitor layout canvas\n├── properties_panel.py  # Monitor properties sidebar\n├── workspace_panel.py   # Workspace rules dialog\n├── models.py            # MonitorConfig, Profile, WorkspaceRule\n├── hyprland.py          # Hyprland IPC client\n├── sway.py              # Sway IPC client (binary i3-ipc)\n├── niri.py              # Niri IPC client (JSON socket)\n├── daemon.py            # Hotplug daemon (moniqued)\n├── profile_manager.py   # Profile save/load/match\n└── utils.py             # Paths, file I/O, helpers\n```\n\n## License\n\n[GPL-3.0-or-later](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftorvaldz%2Fmonique","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftorvaldz%2Fmonique","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftorvaldz%2Fmonique/lists"}