mirror of
https://github.com/outbackdingo/hyprcosmic.git
synced 2026-08-25 14:53:21 +00:00
Bumps both forks to the commits that install at upstream's paths, and adds the packaging that follows from it. packaging/ holds one definition per distribution -- an RPM spec, a PKGBUILD and a Debian control template -- and each wraps a tree that `just install` has already staged rather than compiling again inside the packaging tool. Building 27 Rust components a second time to produce bytes that already exist costs hours and creates a way for the packaged desktop and the built one to drift apart. One package per distribution, not one per component. Fedora splits COSMIC into 27 packages, which is right for a distribution tracking upstream. This is a fork that replaces the desktop as a unit: there is no supported combination in which you take the HyprCosmic cosmic-comp and the distribution's cosmic-session, and one package says so accurately. All three declare a conflict with the distribution's cosmic-comp and cosmic-session, and stop rather than resolve it. Obsoletes would let a routine install quietly remove the desktop the machine is currently running; removing COSMIC stays a decision a person makes. .github/workflows/packages.yml builds all three, each inside a container of the distribution it targets, because nothing here is statically linked and a package built elsewhere records sonames the installing machine will not have. It runs on tags and on demand rather than on every push -- three full desktop builds is hours of runner time for artifacts nobody downloads -- and a tag opens a draft release, not a published one. The RPM file list is generated from the staged tree, and claims a directory only when no package already owns it. A naive list would have the package own /usr, /usr/bin and /usr/share, which belong to `filesystem`. README follows the same reframe: the install goes to /usr/bin, the package route is documented first, and the conflict is explained where a reader meets it rather than left to be discovered.
288 lines
14 KiB
Markdown
288 lines
14 KiB
Markdown
# HyprCosmic
|
|
|
|
COSMIC's compositor, driven the way Hyprland is configured, wearing a HyDE
|
|
shell.
|
|
|
|
It is a fork of [cosmic-epoch](https://github.com/pop-os/cosmic-epoch), the
|
|
meta-repository that names every COSMIC component and builds the desktop out of
|
|
them. Two of its 29 submodules point at forks; the other 27 are System76's,
|
|
unchanged. So this is not a re-implementation of COSMIC and not a theme pack
|
|
sitting beside it — it is COSMIC, built from source, with a different shell on
|
|
top and a different way of telling it what to do.
|
|
|
|
Three things distinguish a HyprCosmic session from a COSMIC one:
|
|
|
|
- **Hyprland's configuration idiom.** A single `~/.config/hyprcosmic/cosmic.conf`
|
|
with `general { }` blocks, `bind =` lines and `$variables` is compiled into
|
|
COSMIC's config tree. The file wins: what it names, it owns.
|
|
- **HyDE's shell.** waybar instead of cosmic-panel, rofi instead of
|
|
cosmic-launcher, `awww` instead of cosmic-bg. HyDE themes are imported
|
|
directly, palette and wallpapers and all.
|
|
- **It replaces COSMIC rather than sitting next to it.** The binaries install as
|
|
`/usr/bin/cosmic-comp` and `/usr/bin/cosmic-session`, the paths a cosmic-comp
|
|
and a cosmic-session go to, and the packages conflict with the distribution's
|
|
accordingly. Both session entries are installed, so the greeter still offers a
|
|
stock COSMIC shell for the day the HyDE one does not start — now served by
|
|
these binaries rather than by a second copy on disk.
|
|
|
|
## Repository layout
|
|
|
|
Everything in `cosmic-epoch`, plus:
|
|
|
|
| Path | What it is |
|
|
| --- | --- |
|
|
| `cosmic-comp/` | submodule → [outbackdingo/hyprcosmic-comp](https://github.com/outbackdingo/hyprcosmic-comp) |
|
|
| `cosmic-session/` | submodule → [outbackdingo/hyprcosmic-session](https://github.com/outbackdingo/hyprcosmic-session) |
|
|
| `cosmic-conf/` | the config compiler and HyDE theme importer. A crate in this repository, not a submodule |
|
|
| `config/` | the shipped `cosmic.conf`, `autostart`, waybar and rofi assets, and the power menu |
|
|
| `tools/install-assets.sh` | installs the parts of `config/` that live outside `$HOME`, and `--check`s them for drift |
|
|
| `docs/` | the design spec, a debugging guide, and one written-up bug that is still open |
|
|
|
|
The other 27 submodules stay on `pop-os`. Nothing about them needs to change,
|
|
and pinning them to copies nobody maintains would be a promise to keep 27 forks
|
|
current.
|
|
|
|
### What the two forks change
|
|
|
|
**cosmic-comp** — four patches, each independent:
|
|
|
|
- `zwlr_foreign_toplevel_management_v1`, which is the protocol waybar's window
|
|
list and rofi's window mode read. Without it the taskbar is empty.
|
|
- A Hyprland-compatible IPC socket (`.socket.sock` and the `.socket2.sock` event
|
|
stream) under the names Hyprland clients actually open, so HyDE's scripts and
|
|
waybar's `hyprland/*` modules work unmodified. The write surface is
|
|
deliberately small: `dispatch exec` and `dispatch killactive` are rejected,
|
|
because this is the surface any process that can open the socket gets.
|
|
- New windows open *beside* the focused window rather than inside it.
|
|
- The install goes to `/usr/bin/cosmic-comp`, at upstream's paths and alongside
|
|
upstream's two `.ron` defaults files, which are carried unmodified.
|
|
|
|
**cosmic-session** — profiles. `HYPRCOSMIC_PROFILE=hyprcosmic` (set by
|
|
`hyprcosmic.desktop`) skips cosmic-panel, cosmic-launcher, cosmic-app-library,
|
|
cosmic-workspaces, cosmic-bg and cosmic-files-applet, then starts whatever
|
|
`~/.config/hyprcosmic/autostart` names. cosmic-greeter is deliberately *not*
|
|
skippable — a display manager is the easiest thing to lock yourself out of. The
|
|
fork installs three files where upstream installs seven; the four it drops are
|
|
owned by the distribution's own `cosmic-session` package and writing them would
|
|
make the two conflict.
|
|
|
|
## Building
|
|
|
|
```shell
|
|
git clone --recurse-submodules https://github.com/outbackdingo/hyprcosmic
|
|
cd hyprcosmic
|
|
just build
|
|
```
|
|
|
|
Build dependencies are COSMIC's — see [upstream's list](https://github.com/pop-os/cosmic-epoch#setup-on-distributions-without-packaging-of-cosmic-components),
|
|
which is long and distribution-specific. `rustup` is recommended over the
|
|
distribution's rustc: `cosmic-comp` is edition 2024 and pins Rust 1.93 in its
|
|
`rust-toolchain.toml`, which is newer than several stable distributions ship —
|
|
Debian bookworm's rustc is 1.63. `just` is likewise absent before Debian
|
|
trixie; `cargo install just --locked` covers it.
|
|
|
|
## Installing
|
|
|
|
The easiest route is a package. Every tag builds one for Fedora, Arch and Debian
|
|
and attaches it to a draft release; `workflow_dispatch` on **Packages** builds
|
|
them at any other time and leaves them as run artifacts.
|
|
|
|
```shell
|
|
sudo dnf install ./hyprcosmic-*.rpm # Fedora
|
|
sudo pacman -U ./hyprcosmic-*.pkg.tar.zst # Arch
|
|
sudo dpkg -i ./hyprcosmic_*_amd64.deb # Debian
|
|
```
|
|
|
|
Expect this to fail the first time, and read what it says when it does. These
|
|
packages provide `/usr/bin/cosmic-comp` and `/usr/bin/cosmic-session`, so they
|
|
**conflict with the distribution's `cosmic-comp` and `cosmic-session`** and your
|
|
package manager will refuse until those are removed. That refusal is the design:
|
|
installing HyprCosmic replaces the machine's desktop, and it should take a
|
|
deliberate `dnf remove cosmic-comp cosmic-session` to say so rather than a
|
|
resolver deciding on your behalf. Both session entries survive the swap, so the
|
|
greeter still offers a stock COSMIC shell afterwards.
|
|
|
|
Building it yourself instead:
|
|
|
|
```shell
|
|
sudo just install '' /usr
|
|
```
|
|
|
|
The two positional arguments are `rootdir` (a staging root, for packaging) and
|
|
`prefix`. **Use `/usr`, not the `/usr/local` default.** Several files name
|
|
`/usr/share/hyprcosmic` as a literal because they have no way to interpolate a
|
|
prefix — a rofi `.rasi` has no variables, `hyprcosmic.desktop` has no way to
|
|
expand one into `Exec=`, and `autostart` is deliberately not a shell.
|
|
`install-assets.sh` prints the exact list when you use another prefix.
|
|
|
|
To stage instead of install:
|
|
|
|
```shell
|
|
just install /tmp/stage /usr
|
|
```
|
|
|
|
This installs all of COSMIC — the 27 unmodified components as well — plus
|
|
`cosmic-conf` at `$prefix/bin/cosmic-conf`, the shared waybar and rofi assets
|
|
under `$prefix/share/hyprcosmic/`, and `hyprcosmic-powermenu`.
|
|
|
|
`install` depends on `build`, which is upstream's arrangement and means `sudo
|
|
just install` compiles as root. That is inherited, not chosen; if you would
|
|
rather not, build into a staging root as your own user and copy it into place.
|
|
|
|
Then log out. `HyprCosmic` appears on the greeter's session menu next to
|
|
`COSMIC`; both work.
|
|
|
|
### Per-user setup
|
|
|
|
`just install` places nothing in a home directory — under `sudo` the only home
|
|
directory it could see is root's. Four files are yours to place:
|
|
|
|
```shell
|
|
mkdir -p ~/.config/hyprcosmic/waybar
|
|
cp config/cosmic.conf config/autostart ~/.config/hyprcosmic/
|
|
cp config/waybar/style.css ~/.config/hyprcosmic/waybar/
|
|
```
|
|
|
|
`style.css` is per-user rather than shared for one reason: it `@import`s a
|
|
sibling `theme.css` holding the installed HyDE theme's palette, and a relative
|
|
`@import` resolves against the importing file. That sibling is written by
|
|
`import-theme --assets`, so the bar is unstyled until you have imported a theme.
|
|
|
|
The fourth file, `~/.config/rofi/config.rasi`, is written by `import-theme
|
|
--assets` too, because it names per-machine paths.
|
|
|
|
Runtime dependencies of the shell itself are not COSMIC's and are not built
|
|
here: `waybar`, `rofi` (wayland build), `awww` (formerly `swww`), and a Nerd
|
|
Font for the bar's glyphs.
|
|
|
|
## Configuration
|
|
|
|
`~/.config/hyprcosmic/cosmic.conf`, in Hyprland's idiom, compiled into
|
|
`cosmic-config` by:
|
|
|
|
```shell
|
|
cosmic-conf apply # once
|
|
cosmic-conf apply --diff # show what would change, write nothing
|
|
cosmic-conf watch # recompile on every edit, for the whole session
|
|
```
|
|
|
|
`watch` is the first line of the shipped `autostart`, which is what makes "the
|
|
file wins" true at login and not only when you last ran `apply` by hand:
|
|
whatever COSMIC's settings UI stored since then is overwritten before the
|
|
desktop settles. A malformed edit is reported to the session log and the last
|
|
good configuration stays in place, so a typo cannot leave you at a broken
|
|
desktop.
|
|
|
|
The rule is one-way and deliberate. Keys this file names are overwritten from
|
|
it on every login; keys it does not name are left entirely alone, so
|
|
cosmic-settings remains the right place to change anything the file is silent
|
|
about. There is no write-back — the GUI never edits `cosmic.conf`.
|
|
|
|
`bind` lines go to the Shortcuts `custom` key, which cosmic-comp merges over
|
|
`defaults`, so the system defaults file is never touched and reverting is a
|
|
matter of deleting the lines and re-applying. Hyprland spellings and COSMIC
|
|
spellings are both accepted for the same setting (`input:follow_mouse` and
|
|
`general:focus_follows_cursor`), and the last assignment wins. Where a Hyprland
|
|
value has no COSMIC equivalent — `follow_mouse = 2` and `3`, which separate
|
|
pointer focus from keyboard focus — it is rejected with an explanation rather
|
|
than quietly rounded.
|
|
|
|
What the shipped file sets up, since the components those keys used to reach are
|
|
no longer running:
|
|
|
|
| Binding | Does |
|
|
| --- | --- |
|
|
| `Super` (tap), `Super+/`, `Super+A` | `rofi -show drun` |
|
|
| `Super+W` | `rofi -show window`, in place of the workspace overview |
|
|
| `Super+Return` | `cosmic-term` (`Super+T` still works — cosmic-comp handles that one itself) |
|
|
| `Super+Shift+E` | `hyprcosmic-powermenu`: lock, suspend, log out, reboot, shut down |
|
|
|
|
The power menu is there because cosmic-panel hosts COSMIC's power applet, and
|
|
without the panel a session had no way out short of `systemctl reboot` from a
|
|
terminal. The same script backs waybar's power button, so the two cannot drift
|
|
apart, and it confirms before anything that ends the session.
|
|
|
|
See [`config/cosmic.conf`](config/cosmic.conf); it is commented at length and is
|
|
the reference for what is supported.
|
|
|
|
## Theming
|
|
|
|
```shell
|
|
cosmic-conf import-theme ~/.config/hyde/themes/'Tokyo Night'/hypr.theme \
|
|
--out ~/.config/hyprcosmic/theme.conf --report --assets
|
|
```
|
|
|
|
This translates a HyDE theme into conf keys, and with `--assets` also installs
|
|
the wallpapers, GTK and icon themes, and the waybar/rofi/kitty theme files that
|
|
sit beside `hypr.theme`. `--report` prints everything that did not translate
|
|
cleanly, which is the honest half of the output.
|
|
|
|
`theme.conf` is written as a separate file and `source`d from `cosmic.conf`
|
|
rather than pasted into it. That keeps re-importing from touching your
|
|
keybindings, and anything you want to override can simply be repeated later in
|
|
`cosmic.conf`, since the last assignment to a key wins. The `source` line ships
|
|
commented out — a `source` naming a file that does not exist is a hard error,
|
|
and no theme is imported on a fresh install. Uncomment it once you have run the
|
|
command above; `import-theme` says so as well.
|
|
|
|
Change the wallpaper by repointing the `current` symlink that `--assets`
|
|
maintains, not by editing `autostart`:
|
|
|
|
```shell
|
|
ln -sfn ~/".local/share/wallpapers/hyprcosmic/<theme>/<image>" \
|
|
~/.local/share/wallpapers/hyprcosmic/current
|
|
```
|
|
|
|
## Continuous integration
|
|
|
|
Two workflows, on purpose:
|
|
|
|
- `.github/workflows/ci.yml` is upstream's, unmodified. It builds the entire
|
|
desktop on Arch via `just sysext`, which is exactly the check a meta-repo
|
|
wants and is not made less useful by forking.
|
|
- `.github/workflows/hyprcosmic.yml` covers what upstream's does not:
|
|
`cosmic-conf` built, tested and clippy-clean on Fedora, Debian and Arch; a
|
|
check that the shipped `cosmic.conf` still parses and resolves against the
|
|
current schema; that `config/waybar/config.jsonc` is still in step with the
|
|
generator that produces it; that the template and generator stay pure ASCII;
|
|
and an `install-assets.sh` round trip into a staging root, verified with
|
|
`--check`.
|
|
|
|
The two forks carry a `hyprcosmic.yml` of the same shape, each building on
|
|
Fedora, Debian and Arch and asserting that its install landed at upstream's
|
|
paths — and that nothing landed in the private `/usr/libexec/hyprcosmic/` this
|
|
fork used to use, which is the assertion that would otherwise rot quietly.
|
|
|
|
`packages.yml` in this repository builds installable packages for the same three
|
|
distributions: an RPM, a `.pkg.tar.zst` and a `.deb`, each compiled inside a
|
|
container of the distribution it targets so the sonames it records are the ones
|
|
the installing machine will have. It runs on tags and on demand, not on every
|
|
push — three full desktop builds is hours of runner time. Tags additionally open
|
|
a **draft** release with the packages attached; drafts rather than published,
|
|
because installing one of these replaces the machine's desktop.
|
|
|
|
The waybar generator deserves its own note. `config.jsonc` is generated from
|
|
`config.jsonc.in` and a codepoint table in `generate-config.py`, and is never
|
|
hand-edited: Nerd Font glyphs live in the Private Use Area, where they are
|
|
destroyed by being retyped and indistinguishable from each other in a diff. CI
|
|
regenerates the file and fails if it moves.
|
|
|
|
## Known gaps
|
|
|
|
- The `/usr/share/hyprcosmic` literals described under [Installing](#installing).
|
|
- `docs/unreproducible-dead-input-2026-08-10.md` records a session that came up
|
|
without input and has not been reproduced since. It is written down rather
|
|
than closed.
|
|
|
|
## Trademark
|
|
|
|
COSMIC is a System76 trademark. This fork is not affiliated with or endorsed by
|
|
System76. See [TRADEMARK.md](TRADEMARK.md), which is upstream's policy and
|
|
applies here.
|
|
|
|
## Upstream
|
|
|
|
For COSMIC itself — the component list, packaging status, translations, and how
|
|
to install it on your distribution rather than building it — see
|
|
[pop-os/cosmic-epoch](https://github.com/pop-os/cosmic-epoch).
|