Whether to enable trollshell — hytte-based Wayland desktop shell.
Type: boolean
Default:
false
Example:
true
Declared by:
Enable the system daemons trollshell’s optional chips lean on (UPower, power-profiles-daemon, geoclue, plus the polkit agent and the agent-name D-Bus policy). Each is still individually overridable; this is a master switch for the lot. Turning it off leaves a working bar — the chips that back onto a missing daemon simply hide themselves.
Type: boolean
Default:
true
Declared by:
Install the optional GNOME desktop apps that pair with the GOA →
evolution-data-server stack trollshell reads: GNOME Calendar (a
read/write UI for the same calendars trollshell’s Calendar page shows
read-only), GNOME Tasks (Endeavour, for the EDS task lists), and GNOME
Contacts. Kept separate from enableRecommendedServices because these
are heavier GUI apps rather than daemons — turn this off to keep the
services + the gnome-control-center account-add UI while dropping the
apps. (gnome-control-center itself stays under the services switch,
since it’s the essential way to add an account.)
Type: boolean
Default:
true
Declared by:
Whether to enable all of the session-integration extras below (fuzzel, the wallpaper daemon, cliphist, portals) as a group. Each is set with mkDefault, so you can still flip an individual one off. The wallpaper daemon is the one selected by programs.trollshell.wallpaper.backend (default swaybg), not hardcoded — set backend = “none” to opt out of daemon management entirely.
Type: boolean
Default:
false
Example:
true
Declared by:
The trollshell package to install.
Type: package
Default:
trollshell.packages.${system}.trollshell
Declared by:
Whether to enable clipboard history (text + images) via home-manager’s services.cliphist, which feeds the Clipboard drawer page.
Type: boolean
Default:
false
Example:
true
Declared by:
Install the trollshell-control-center companion app alongside the shell. It’s the external settings/management window (launchable by its app-id, mov.vibec0re.trollshell.ControlCenter) that speaks to the running shell’s Control session-bus endpoint. Enabled by default; set false to drop it (the shell itself doesn’t depend on it).
Type: boolean
Default:
true
Declared by:
The trollshell-control-center package to install.
Type: package
Default:
trollshell.packages.${system}.trollshell-control-center
Declared by:
Whether to enable the bundled fuzzel launcher config via home-manager’s programs.fuzzel.
Bind Mod+D to fuzzel in niri yourself (etc/niri/binds.kdl).
Type: boolean
Default:
false
Example:
true
Declared by:
Daytime color temperature in kelvin (wlsunset -T <dayTemp>). 6500K is
neutral daylight (wlsunset’s own default).
Type: signed integer
Default:
6500
Example:
6500
Declared by:
Latitude in decimal degrees for wlsunset’s geo (sunrise/sunset) mode
(wlsunset -l <latitude>). Optional. When set (together with
longitude) it takes precedence over the live location fix, so use it
to pin night light to a fixed place, or if you do not run GeoClue2.
Leave both null to follow the live fix instead. With neither a fix nor
these set, the toggle refuses to start the daemon and logs why. May be
given as a float (52.52) or a string (“52.52”).
Type: null or floating point number or string
Default:
null
Example:
52.52
Declared by:
Longitude in decimal degrees for wlsunset’s geo mode
(wlsunset -L <longitude>). Optional, and only used together with
latitude — a half-configured pair is ignored (see latitude). May
be a float or a string.
Type: null or floating point number or string
Default:
null
Example:
13.405
Declared by:
Nighttime color temperature in kelvin (wlsunset -t <nightTemp>).
Lower is warmer; 4000K is a gentle warm-white.
Type: signed integer
Default:
4000
Example:
3500
Declared by:
Declarative plugins (#350, launch model #419), keyed by plugin id:
each attr drops in without hand-writing a systemd unit. The option
renders to a JSON launch-state file
(trollshell/plugins.json under XDG config — per-user via
home-manager, /etc/xdg via the NixOS module) that the running shell
reads at startup, launching each enabled entry as a transient
trollshell-plugin-<id> user unit via systemd-run --user
(trollshell/src/plugin_launcher.rs; Restart=on-failure,
PartOf=graphical-session.target — supervision and session lifetime
stay systemd’s job, and the launch env is where #392’s key
injection hooks in). Being an attrset of submodules (the standard
named-instance pattern), entries merge per-field across modules —
a second module can override one field of one plugin
(plugins.pet.env.PET_NAME = lib.mkForce "nisse";) or disable it
(plugins.pet.enable = false;). The launched plugin dials
plugin.sock and registers itself; the control-center’s Plugins tab
(#348) starts/stops the transient units live, while enablement
stays declared here.
Each bundled plugin ships as its own package in this flake (#558), so
package points straight at a hytte-plugin-<id> output — no
out-of-tree derivation needed:
plugins.pet.package = trollshell.packages.${system}.hytte-plugin-pet;
The bundled ids are: audio-widget, bar-clock-demo, caw, clock-demo,
departures, infobroker, pet, preem-demo, terminal, timer, usage,
weather (each output named hytte-plugin-<id>). Their per-plugin
runtime knobs go through env / secrets above.
Type: attribute set of (submodule)
Default:
{ }
Example:
{
# A bundled plugin, wired from this flake's per-plugin package
# (see the list of ids in the description below):
pet = {
package = trollshell.packages.${system}.hytte-plugin-pet;
env.PET_NAME = "nisse";
};
}
Declared by:
Whether the shell launches this plugin at startup (#419).
A disabled entry is still declared — written to the launch
state as “enabled”: false, so it lists in the control-center’s
Plugins tab and can be started manually — it just doesn’t
auto-launch. Lets a downstream module switch a single entry
off (plugins.pet.enable = false;) without removing its
definition.
Type: boolean
Default:
true
Example:
false
Declared by:
The plugin’s package (its out-of-process binary, built on
hytte-plugin — never linked into the shell). The shell
launches it as a transient trollshell-plugin-<id> user unit
via systemd-run --user (#419,
trollshell/src/plugin_launcher.rs); once running it dials
plugin.sock and speaks the Register handshake itself
(trollshell/src/plugins.rs).
Type: package
Declared by:
Environment variables passed to the plugin binary at launch
(rendered into the launch-state file’s per-plugin env map and
applied as --setenv=K=V by the launcher,
trollshell/src/plugin_launcher.rs). This is the non-secret
sibling of secrets below and the idiom each bundled plugin
reads its config through — so it is how the non-secret runtime
knobs are exposed as nix options (#533): set the plugin’s env
var here rather than in a shell profile. Values must be strings.
Do NOT put API keys here — the launch-state file is
world-readable; use secrets (below) instead, which injects the
key from the login keyring at spawn.
A few representative examples (each also readable from the environment directly; the nix option is just the declarative way to set it):
pet (hytte-plugin-pet): PET_NAME (display name),
PET_LLM_URL (opt into a local llama-server brain — the API
key is a secrets slot, not env).usage (hytte-plugin-usage): TROLLSHELL_USAGE_DASHBOARD_URL
(the Grafana public-dashboard URL — the value that flips the
card from empty-state to live).weather (hytte-plugin-weather): TROLLSHELL_WEATHER_CITY
(geocoded fallback when GeoClue is unavailable — usually set
session-wide via programs.trollshell.weather.fallbackCity
instead of per-plugin here).The full inventory — swept from source, all 12 bundled
plugins including the ones with zero knobs — is published at
https://vibec0re.github.io/trollshell/plugin-env.html
(source: docs/plugin-env.md). An absolute URL rather than a
relative one because this description is also rendered by
nixos-option and man home-configuration.nix, where a
relative plugin-env.html link would resolve to nothing.
Precedence for a plugin that also reads a config file (e.g.
usage’s ~/.config/trollshell/usage.toml): environment (this
option) wins over the file, which wins over the built-in default.
Type: attribute set of string
Default:
{ }
Example:
{
PET_LLM_MODEL = "google/gemini-3.5-flash";
PET_NAME = "nisse";
}
Declared by:
AI-provider key slots to inject into this plugin at launch
(#392). For each slot the shell reads the key stored in your
login keyring — managed by the control-center’s AI Keys tab,
never written to disk or this config — and passes it to the
plugin as the <SLOT>_API_KEY environment variable (e.g.
“openrouter” → OPENROUTER_API_KEY), which is exactly the
override hytte-ai-providers’ load_key reads first. So an
LLM-backed plugin picks the key up with no per-plugin config:
plugins.pet.secrets = [ "openrouter" ];. A slot with no
stored key is simply skipped (the plugin runs keyless and uses
its own fallback); a plugin that doesn’t list a slot never gets
that key in its environment. Rotating a key in the
control-center relaunches the running plugins that declare it.
Type: list of string
Default:
[ ]
Example:
[
"openrouter"
]
Declared by:
Whether to enable the niri xdg-desktop-portal routing + backends via home-manager’s xdg.portal. You still set XDG_CURRENT_DESKTOP=niri:GNOME yourself.
Type: boolean
Default:
false
Example:
true
Declared by:
Whether the screen-recording chip (#403,
crates/hytte-services/src/recorder.rs) starts with audio capture armed.
This is only the initial value of the in-shell audio toggle, read once
at service start; the toggle in Settings still flips it live during a
session. Off by default (recordings are silent unless you opt in). When
true, sets TROLLSHELL_RECORD_AUDIO=1 for the session; that env var is
the override, so leaving this at the default lets a hand-set
TROLLSHELL_RECORD_AUDIO still win.
Type: boolean
Default:
false
Example:
true
Declared by:
How the System Stats drawer page arranges its five resource cards (CPU / Memory / Disks / GPU / Services). Sets TROLLSHELL_STATS_LAYOUT for the session, read once at shell startup.
This is the shell’s first purely-cosmetic layout knob (issue #508). The
design principle is otherwise “composable, not configurable” — the shell
is wired in Rust, not config — so most appearance choices are made in
main.rs, not here. The Stats layout is the deliberate exception,
blessed on the #508 thread, because the combined and split shapes both
have real users.
multicolumn (default): the same five cards in a two-column grid —
CPU beside Memory, Disks beside GPU, Services spanning both columns
underneath. Uses a wider drawer clamp (~1080px vs. the usual 680px)
so the two side-by-side history graphs each keep a usable width.
Chips still open this one page, scrolled to their card.combined: all five cards stacked in one scrolling page. The
original pre-#307 shape, restored by #518 after #307 had split it.
Clicking any resource bar chip opens this page scrolled to that card
(the #516/#547 deep-links).split: five separate single-card pages, one per bar chip — #307’s
shape (filed by kaesaecracker), resurrected here alongside the
combined page so it is a declarative option rather than a fork patch.
Each chip opens only its own resource’s page.An unrecognized value falls back to multicolumn (the enum type
rejects one at evaluation time; the runtime fallback covers a hand-set
env var).
Type: one of “combined”, “multicolumn”, “split”
Default:
"multicolumn"
Example:
"combined"
Declared by:
Whether to enable the bundled swaybg wallpaper user unit standalone, which reads its argument list from ~/.config/trollshell/swaybg.args (the Appearance drawer page writes it — per-output images and rotation supported). Gently deprecated in favor of programs.trollshell.wallpaper.backend = “swaybg” + enableSessionExtras: the extras bundle now starts the swaybg unit when backend is “swaybg” (the default). This option is still honored — set it true to run the swaybg unit without the rest of the bundle. Two wallpaper daemons can never run at once because backend selects exactly one, but if you set this true AND backend = “awww”, swaybg and awww would both start; don’t. Leave it false unless you specifically want swaybg without the bundle.
Type: boolean
Default:
false
Example:
true
Declared by:
Run trollshell as a systemd user service.
Type: boolean
Default:
true
Declared by:
Systemd user target the shell service binds to.
Type: string
Default:
"graphical-session.target"
Example:
"niri-session.target"
Declared by:
Which wallpaper daemon trollshell manages for the session, and what the
Appearance picker tells to reload. One enum value drives the daemon
wiring and the reloadCommand default together, so two daemons can never
run at once — backend selection is structural, not an assertion.
swaybg (default — today’s behavior): the bundled swaybg user unit;
the Appearance picker restarts it (the shell’s built-in default), so
reloadCommand stays null.awww: the swww successor (upstream renamed swww → awww at 0.12; swww
itself is deprecated). Defaults reloadCommand to awww img {}. The
daemon is run by home-manager’s services.awww; the NixOS module only
exports the reload command (a NixOS-only user without home-manager
runs the awww daemon themselves).none: manage no daemon at all — the Appearance picker only writes
~/.config/trollshell/wallpaper.path (and runs reloadCommand if you
set one yourself). Use this to wire your own daemon.The legacy programs.trollshell.swaybg.enable (home-manager) and a
hand-set wallpaper.reloadCommand both still work and take precedence;
they are gently deprecated in favor of this enum.
Type: one of “swaybg”, “awww”, “none”
Default:
"swaybg"
Example:
"awww"
Declared by:
Shell command the Appearance picker runs (via sh -c) after writing
~/.config/trollshell/wallpaper.path, to tell your wallpaper daemon to
reload. A {} in the command is replaced with the chosen path,
shell-quoted. Sets TROLLSHELL_WALLPAPER_RELOAD_CMD for the session.
Use the {} placeholder, not a $VAR reference: this value is delivered
through sessionVariables, which expands $-references at login (before
the path exists), so awww img "$TROLLSHELL_WALLPAPER_PATH" would expand
to awww img "". The path is still also exported as
TROLLSHELL_WALLPAPER_PATH for daemons that read it directly.
Defaults follow wallpaper.backend: null for swaybg (restart the
bundled swaybg unit — the shell’s built-in default) and none, and
awww img {} for awww. Set it explicitly to override; an explicit
value wins over the per-backend default.
Type: null or string
Default:
# per backend: null (swaybg/none) or "awww img {}" (awww)
Example:
"awww img {}"
Declared by:
City the weather widget falls back to when geolocation is unavailable. Sets TROLLSHELL_WEATHER_CITY for the session. Leave null to rely on geoclue (enabled system-side by the NixOS module).
Type: null or string
Default:
null
Example:
"Berlin"
Declared by:
Enable geoclue2 auto-location for the weather widget (and future location-aware features).
Type: boolean
Default:
true
Declared by:
WiFi-positioning backend for geoclue. Mozilla Location Service (geoclue’s historical default) shut down in 2024; beaconDB is the community successor.
Type: string
Default:
"https://api.beacondb.net/v1/geolocate"
Declared by: