{"id":50756328,"url":"https://github.com/b0o/niri-tools","last_synced_at":"2026-06-11T05:04:11.361Z","repository":{"id":345013083,"uuid":"1183874580","full_name":"b0o/niri-tools","owner":"b0o","description":"A collection of tools for the Niri Wayland compositor","archived":false,"fork":false,"pushed_at":"2026-05-21T12:34:54.000Z","size":309,"stargazers_count":1,"open_issues_count":9,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-21T20:23:55.638Z","etag":null,"topics":["niri","niri-config"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/b0o.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"AGENTS.md","dco":null,"cla":null},"funding":{"github":"b0o"}},"created_at":"2026-03-17T03:04:40.000Z","updated_at":"2026-05-21T12:34:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/b0o/niri-tools","commit_stats":null,"previous_names":["b0o/niri-tools"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/b0o/niri-tools","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b0o%2Fniri-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b0o%2Fniri-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b0o%2Fniri-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b0o%2Fniri-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/b0o","download_url":"https://codeload.github.com/b0o/niri-tools/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b0o%2Fniri-tools/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34183112,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["niri","niri-config"],"created_at":"2026-06-11T05:04:10.592Z","updated_at":"2026-06-11T05:04:11.346Z","avatar_url":"https://github.com/b0o.png","language":"Rust","funding_links":["https://github.com/sponsors/b0o"],"categories":[],"sub_categories":[],"readme":"# niri-tools\n\nA collection of tools for the [niri](https://github.com/YaLTeR/niri) Wayland compositor.\n\nCurrently provides scratchpad window management. A background daemon tracks window state via niri's event stream and a CLI client sends commands over a Unix socket. You define scratchpad windows in a config file, then bind the CLI commands to keyboard shortcuts in your niri config to toggle them on and off screen.\n\n## How it works\n\nThe daemon (`niri-tools-daemon`) subscribes to niri's event stream and maintains a live mirror of all windows, workspaces, and outputs. When you run a command like `niri-tools scratchpad toggle term`, the CLI connects to the daemon over a Unix socket and tells it to show or hide the window matching that scratchpad definition.\n\nHidden scratchpad windows are moved to a dedicated off-screen workspace. Showing a scratchpad moves it to the current monitor as a floating window, sized and positioned according to your config.\n\nThe daemon auto-starts when you run any scratchpad command.\n\n## Installation\n\n### From source\n\nRequires Rust 1.85+.\n\n```sh\ncargo build --release\n```\n\nBinaries are at `target/release/niri-tools` and `target/release/niri-tools-daemon`. Place both somewhere on your `$PATH`.\n\n### With Nix\n\n```sh\nnix build\n```\n\nOr add the flake as an input to your system configuration.\n\n## Configuration\n\nCreate `~/.config/niri/niri-tools.kdl`:\n\n```kdl\nsettings {\n  notify \"all\"\n  watch true\n}\n\nscratchpad \"term\" {\n  app-id \"com.mitchellh.ghostty\"\n  command \"ghostty\"\n  size width=\"60%\" height=\"60%\"\n  position x=\"50%\" y=\"50%\"\n}\n\nscratchpad \"browser\" {\n  app-id \"firefox\"\n  command \"firefox\"\n  size width=\"80%\" height=\"80%\"\n  position x=\"50%\" y=\"50%\"\n}\n\nscratchpad \"btop\" {\n  app-id \"com.mitchellh.ghostty\"\n  command \"ghostty\" \"-e\" \"btop\"\n  title \"/btop/\"\n  size width=\"70%\" height=\"70%\"\n  position x=\"50%\" y=\"50%\"\n}\n```\n\n### Scratchpad options\n\n| Field      | Description                                                                                                                  |\n| ---------- | ---------------------------------------------------------------------------------------------------------------------------- |\n| `app-id`   | Wayland app ID to match. Prefix with `/` for regex (e.g. `/google-chrome.*`).                                                |\n| `title`    | Window title to match. Prefix with `/` or `^` for regex.                                                                     |\n| `command`  | Command to spawn the window. Each argument is a separate quoted string (e.g. `command \"ghostty\" \"-e\" \"btop\"`). |\n| `size`     | Window size. Accepts percentages (`\"60%\"`) or pixels (`\"800\"`).                                                              |\n| `position` | Window position. `\"0%\"` = top/left edge, `\"50%\"` = centered, `\"100%\"` = bottom/right edge. The window stays fully on screen. |\n\n### Per-output overrides\n\nScratchpads can have different sizes or positions on different monitors:\n\n```kdl\nscratchpad \"term\" {\n  app-id \"com.mitchellh.ghostty\"\n  command \"ghostty\"\n  size width=\"60%\" height=\"60%\"\n  position x=\"50%\" y=\"50%\"\n\n  output \"DP-2\" {\n    position x=\"50%\" y=\"35%\"\n  }\n  output \"eDP-1\" {\n    size width=\"80%\" height=\"80%\"\n  }\n}\n```\n\n### Settings\n\n| Setting  | Values                                    | Default | Description                                        |\n| -------- | ----------------------------------------- | ------- | -------------------------------------------------- |\n| `notify` | `\"none\"`, `\"error\"`, `\"warning\"`, `\"all\"` | `\"all\"` | Desktop notification verbosity.                    |\n| `watch`  | `true`, `false`                           | `true`  | Reload config automatically when the file changes. |\n\n### Includes\n\nSplit config across files:\n\n```kdl\ninclude \"browsers.kdl\"\n```\n\nPaths are relative to the including file. The main file's values take precedence over included ones.\n\n## Commands\n\n### Scratchpad\n\n```\nniri-tools scratchpad toggle [name]\n```\n\nToggle a named scratchpad. If no name is given, performs a smart toggle: hides the focused scratchpad, or shows the most recently hidden one.\n\n```\nniri-tools scratchpad hide\n```\n\nHide the currently focused floating window (moves it to the scratchpad workspace).\n\n```\nniri-tools scratchpad toggle-float [name]\nniri-tools scratchpad float [name]\nniri-tools scratchpad tile [name]\n```\n\nSwitch a scratchpad between floating and tiled layout. If no name is given, acts on the focused scratchpad.\n\n### Smart focus\n\n```\nniri-tools smart-focus --id \u003cwindow-id\u003e\n```\n\nFocus a window by ID with scratchpad-aware behavior:\n\n- If the window is already focused, does nothing.\n- If the window does not exist, shows a warning notification.\n- If the window is a scratchpad, shows it on the current monitor.\n- If the window is a regular window, focuses it (hiding any focused scratchpad first).\n\n### Daemon\n\n```\nniri-tools daemon start\nniri-tools daemon stop\nniri-tools daemon restart\nniri-tools daemon status\n```\n\nThe daemon starts automatically when needed. These commands are for manual control.\n\n## Niri keybinding example\n\n```kdl\nbinds {\n  Mod+Grave { spawn \"niri-tools\" \"scratchpad\" \"toggle\"; }\n  Mod+T { spawn \"niri-tools\" \"scratchpad\" \"toggle\" \"term\"; }\n  Mod+B { spawn \"niri-tools\" \"scratchpad\" \"toggle\" \"browser\"; }\n}\n```\n\n## File paths\n\n| Path                                     | Description                                                   |\n| ---------------------------------------- | ------------------------------------------------------------- |\n| `$XDG_CONFIG_HOME/niri/niri-tools.kdl`  | Configuration file (default `~/.config/niri/niri-tools.kdl`) |\n| `$XDG_RUNTIME_DIR/niri-tools.sock`       | Daemon socket                                                 |\n| `$XDG_RUNTIME_DIR/niri-tools-state.json` | Persisted state (survives daemon restarts)                    |\n\nThe socket path can be overridden with the `$NIRI_TOOLS_SOCKET` environment variable.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb0o%2Fniri-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fb0o%2Fniri-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb0o%2Fniri-tools/lists"}