Skip to content

installation configuration and usage

Cody-will edited this page Sep 20, 2026 · 1 revision

Installation, Configuration, and Usage

Related Files:

  • README.md
  • examples/config.toml
  • src/config.rs
  • src/cli.rs
  • src/main.rs

Related Pages:

  • Overview and Key Features
  • Architecture and Data Flow
  • Session Management and Hyprland Integration
Relevant source files

The following files were used as context for generating this wiki page:

Installation, Configuration, and Usage

rice is a small Rust CLI designed to orchestrate wallpapers, theme generation, and session helpers for a Hyprland desktop. It centralizes common desktop actions (wallpaper cycling, wallust theming, waybar restart, and session startup) behind a single binary and a simple CLI interface. README.md:1-7, README.md:23-31

This page describes, in detail, how rice is installed, how it loads and validates configuration, where it stores state, and how the main CLI commands behave at runtime. It ties together the top-level binary (main.rs), command routing (cli.rs), configuration (config.rs, examples/config.toml), filesystem paths (paths.rs), and feature modules for wallpaper, bar, session, theme, and notifications. src/main.rs:1-18, src/cli.rs:1-34, src/config.rs:1-36


1. Installation

Sources: README.md:33-89, README.md:115-143

1.1 Prerequisites

rice assumes a Linux desktop environment using Hyprland and one or more supported wallpaper backends. The following prerequisites are required or conditionally used:

Component Required Purpose / Notes
Rust toolchain with Cargo Yes Used to build and install the rice binary.
Hyprland Yes Target compositor for which rice is designed.
hyprpaper or swww At least one Wallpaper backends that rice controls.
wallust Optional Theme generator run after wallpaper changes when enabled.
waybar Optional Status bar that can be restarted by rice bar restart or session startup.

README.md:51-61

rice itself is a single binary installed into ~/.cargo/bin by Cargo. That directory must be on the user’s PATH for global invocation. README.md:63-71

1.2 Install via Cargo

There are two supported installation workflows: installing directly from Git or from a local clone. README.md:63-85

From Git (no clone)

cargo install --git https://github.com/Cody-will/rice.git

This compiles and installs the rice binary into ~/.cargo/bin. README.md:63-69

From a local clone

git clone https://github.com/Cody-will/rice.git
cd rice
cargo install --path .

This uses the checked-out source as the install target. README.md:71-77

After installation:

which rice
rice --help

If which rice is empty, the user must add ~/.cargo/bin to PATH, for example in ~/.bashrc or ~/.zshrc. README.md:79-89

Reinstallation after pulling changes is done via:

cd rice
git pull
cargo install --path .

README.md:89-97


2. Configuration

Sources: README.md:99-151, examples/config.toml, src/config.rs:1-40, src/paths.rs:1-63, src/notifications.rs:1-37, src/bar.rs:1-23, src/session.rs:1-19, src/theme.rs:1-27

Configuration is central to how rice behaves: it controls wallpaper selection, backend choice, bar behavior, theming commands, notification toggles, and which applications are started in a session.

2.1 Config file location and lifecycle

rice uses XDG project directories via directories::ProjectDirs with the application name rice. On Linux this resolves to:

  • Config directory: ~/.config/rice
  • Cache directory: ~/.cache/rice

src/paths.rs:13-35

Key path helpers:

Function Description Example path
config_dir() Returns the config directory for rice. ~/.config/rice
cache_dir() Returns the cache directory for rice. ~/.cache/rice
config_file() Returns the path to the TOML config file. ~/.config/rice/config.toml
state_file() Returns the path to the JSON state file. ~/.cache/rice/state.json
icon_file() Returns the path to the notification icon. ~/.config/rice/icon.png
ensure_dir(path) Recursively creates a directory (mkdir -p semantics). Any parent directory for the above

src/paths.rs:17-45

On the first Config::load() call, if config.toml does not exist, rice will:

  1. Compute the config file path via paths::config_file().
  2. Create the parent directory with paths::ensure_dir.
  3. Write the embedded default config (examples/config.toml included at compile time) into config.toml.

src/config.rs:1-27

Subsequent loads read the file and parse it as TOML into a Config struct. src/config.rs:27-36

2.2 Config schema and default values

The Config struct defines the runtime configuration schema and is deserialized from TOML: src/config.rs:9-23

#[derive(Deserialize, Debug)]
pub struct Config {
    pub wallpaper_dir: PathBuf,
    pub backend: String,
    pub sort: String,
    pub extensions: Vec<String>,
    pub theme: Theme,
    pub bar: Bar,
    pub session: Session,
    pub notifications: Notifications,
}

Theme, Bar, Session, and Notifications all have Default implementations leveraged when fields are missing from the TOML. src/theme.rs:9-24, src/bar.rs:9-21, src/session.rs:7-18, src/notifications.rs:11-24

The example (and default) configuration is stored at examples/config.toml and embedded via include_str!. A representative snippet from the README (which mirrors the example) is: src/config.rs:3-7, README.md:99-135

wallpaper_dir = "~/Pictures/walls"
backend = "hyprpaper"    # hyprpaper | swww | none
sort = "name"
extensions = ["jpg", "jpeg", "png", "webp"]

[theme]
enable = true
command = "wallust"
args = []                 # apply() should call: wallust run <image>

[bar]
restart_on_theme = true
command = "waybar"

[session]
exec = ["waybar", "swaync"]

README.md:99-135

In addition, notifications configuration is provided via the Notifications struct with default values: src/notifications.rs:11-24

#[derive(Serialize, Deserialize, Debug)]
#[serde(default)]
pub struct Notifications {
    pub on_success: bool,
    pub on_error: bool,
}

impl Default for Notifications {
    fn default() -> Self {
        Self {
            on_success: false,
            on_error: true,
        }
    }
}

2.3 Tilde expansion in config paths

After parsing, Config::load() post-processes the wallpaper_dir field by expanding a leading ~ using the user’s home directory: src/config.rs:29-36, src/paths.rs:47-63

cfg.wallpaper_dir = paths::expand_tilde(&cfg.wallpaper_dir);

The expand_tilde helper:

  • ~ → $HOME
  • ~/something → $HOME/something
  • Any other path is returned unchanged.

src/paths.rs:47-63

This ensures that wallpaper directories configured with ~ are resolved to absolute paths before use.

2.4 Configuration options reference

Below is a consolidated table of configuration fields, types, and default behavior:

Section Field Type Default value / behavior Notes
root wallpaper_dir PathBuf "~/Pictures/walls" (from example) Tilde expanded.
root backend String "hyprpaper" (from example) Must be "hyprpaper", "swww", or "none" for built-in backends. src/wall/backend.rs:7-19
root sort String "name" (from example) Only "name" is treated specially (lexicographic sort). src/wall/mod.rs:15-26
root extensions Vec<String> ["jpg","jpeg","png","webp"] (from example) Used to filter images. src/config.rs:38-40, src/wall/mod.rs:17-23
theme enable bool true (Default impl) Disables theme/apply if false. src/theme.rs:9-24, src/theme.rs:28-34
theme command String "wallust" (Default impl) Executable used for theming.
theme args Option<Vec<String>> None (Default impl) Extra args appended after run <image>. src/theme.rs:9-24, src/theme.rs:36-47
bar restart_on_theme bool true (Default impl) If true, bar::restart is called after theme apply. src/bar.rs:9-21, src/theme.rs:49-55
bar command String "waybar" (Default impl) Process name used by pkill and for relaunch. src/bar.rs:9-21
session exec Vec<String> ["waybar","swaync","discord"] (Default impl) Commands spawned on rice session start. src/session.rs:7-18, src/session.rs:20-31
notifications on_success bool false (Default impl) Controls success notification emission. src/notifications.rs:11-24, src/notifications.rs:46-53
notifications on_error bool true (Default impl) Controls error notification emission. src/notifications.rs:11-24, src/notifications.rs:55-62

3. Runtime architecture and command flow

Sources: src/main.rs:1-58, src/cli.rs:1-34, README.md:23-31

3.1 CLI commands overview

The Cli struct and its nested subcommands define the CLI surface: src/cli.rs:1-34

#[derive(Parser)]
#[command(name = "rice", about = "Hyprland helpers")]
pub struct Cli {
    #[command(subcommand)]
    pub command: Command,
}

#[derive(Subcommand)]
pub enum Command {
    Wall {
        #[command(subcommand)]
        action: WallAction,
    },
    Bar {
        #[command(subcommand)]
        action: BarAction,
    },
    Session {
        #[command(subcommand)]
        action: SessionAction,
    },
}

Available actions:

  • rice wall next
  • rice wall prev
  • rice wall start
  • rice bar restart
  • rice session start

README.md:23-31, src/cli.rs:18-34

wall actions are dispatched to functions in wall::mod, bar actions to bar::restart, and session actions to session::start via the top-level main function: src/main.rs:7-18, src/main.rs:20-30

3.2 Main runtime flow

The main function parses CLI arguments, runs the selected command, and then handles notifications and exit status: src/main.rs:7-18, src/main.rs:20-58

High-level logic:

  1. Parse CLI: Cli::parse().
  2. Match command and dispatch to the appropriate module function.
  3. After the function returns, if Ok(()):
    • Try to load Config.
    • If successful, send a success notification "Wallpaper updated".
    • Return Ok(()).
  4. If the function returns Err(e):
    • Try to load Config.
    • If successful, send an error notification "Update failed: {e:#}".
    • Print the error to stderr.
    • Exit with code 1.

src/main.rs:7-18, src/main.rs:20-58

The simplified conceptual flow is:

let result = match Cli::parse().command { /* dispatch */ };

match result {
    Ok(()) => {
        if let Ok(cfg) = Config::load() {
            notifications::success(&cfg, "Wallpaper updated");
        }
        Ok(())
    },
    Err(e) => {
        if let Ok(cfg) = Config::load() {
            notifications::error(&cfg, &format!("Update failed: {e:#}"));
        }
        eprintln!("{e:#}");
        std::process::exit(1);
    }
}

src/main.rs:7-18, src/main.rs:20-58

3.3 Command flow diagram

The following Mermaid diagram visualizes the main command flow from CLI invocation to module dispatch and notification handling:

graph TD
  CLI["User runs rice"] --> Parse["Cli::parse()"]
  Parse --> MatchCmd["Match Command"]
  MatchCmd --> WallCmd["wall::*"]
  MatchCmd --> BarCmd["bar::restart"]
  MatchCmd --> SessionCmd["session::start"]
  WallCmd --> Result["Result<()>"]
  BarCmd --> Result
  SessionCmd --> Result
  Result --> OkBranch["Ok(())"]
  Result --> ErrBranch["Err(e)"]
  OkBranch --> LoadCfgOk["Config::load()"]
  ErrBranch --> LoadCfgErr["Config::load()"]
  LoadCfgOk --> SuccNotif["notifications::success()"]
  LoadCfgErr --> ErrNotif["notifications::error()"]
  ErrNotif --> Stderr["Print error"]
  Stderr --> Exit["Exit(1)"]
Loading

Sources: src/main.rs:7-18, src/cli.rs:1-34, src/notifications.rs:39-62


4. Wallpaper management and state

Sources: src/wall/mod.rs:1-104, src/wall/backend.rs:1-24, src/state.rs:1-55, src/config.rs:36-40, src/theme.rs:26-55, examples/config.toml

The wall module encapsulates image discovery, selection, and backend-specific wallpaper application. It also coordinates theme application and state persistence.

4.1 Image discovery and filtering

list_images(cfg: &Config) reads the configured wallpaper_dir and filters files by extension: src/wall/mod.rs:7-26

Key behaviors:

  • Uses fs::read_dir on cfg.wallpaper_dir.
  • Keeps only paths that are files (path.is_file()).
  • Keeps only files whose lowercase extension appears in cfg.extensions.
  • If no images are found, it errors with bail!("no wallpapers in {}", dir.display()).
  • If cfg.sort == "name", it sorts the images lexicographically.

src/wall/mod.rs:7-26, src/config.rs:38-40

Config::is_valid_img helper:

pub fn is_valid_img(&self, img_ext: &str) -> bool {
    self.extensions.contains(&img_ext.to_string())
}

src/config.rs:36-40

4.2 Wallpaper state persistence

The State struct tracks the last used wallpaper and backend across runs: src/state.rs:7-21

#[derive(Serialize, Deserialize, Debug)]
#[serde(default)]
pub struct State {
    pub wallpaper: Option<PathBuf>,
    pub backend: Option<String>,
}
  • State::load():
    • If state.json does not exist, returns State::default() (both fields None).
    • Otherwise, reads and deserializes JSON from ~/.cache/rice/state.json.

src/state.rs:23-42

  • State::save():
    • Ensures the parent directory exists via paths::ensure_dir.
    • Serializes the struct to pretty JSON and writes it to state.json.

src/state.rs:44-55

4.3 Wallpaper stepping logic

The step(delta: isize) function is used by both next and prev: src/wall/mod.rs:28-50

Processing steps:

  1. Load global config: Config::load().
  2. Load state: State::load().
  3. List available images via list_images.
  4. Compute current index:
    • If state.wallpaper is Some and present in images, use its index.
    • Otherwise, fall back to index 0.
  5. Compute next index using wrapping arithmetic:
    • (idx + delta).rem_euclid(n) where n is the number of images.
  6. Derive backend:
    • Use state.backend if set, else cfg.backend.as_str().
  7. Set wallpaper via backend: backend::set(&images[next], backend).
  8. Apply theme via theme::apply.
  9. Update state with chosen wallpaper and backend, then save.
  10. Print the chosen image path to stdout.

src/wall/mod.rs:28-50

next() and prev() are thin wrappers:

pub fn next() -> Result<()> {
    step(1)
}

pub fn prev() -> Result<()> {
    step(-1)
}

src/wall/mod.rs:52-60

Wrap-around behavior is verified by unit tests: src/wall/mod.rs:76-88

#[test]
fn wrap_next_from_last() {
    let n: isize = 3;
    let idx: isize = 2;
    assert_eq!((idx + 1).rem_euclid(n) as usize, 0);
}

4.4 Wallpaper start logic

start() restores the last used wallpaper or falls back to the first image: src/wall/mod.rs:62-75

Flow:

  1. Load Config and State.
  2. Get image list.
  3. Determine target wallpaper:
    • If state.wallpaper is set and present in the image list, use that.
    • Otherwise, use images[0].
  4. Determine backend:
    • Use state.backend if set, else cfg.backend.
  5. Call backend::set(&path, &backend).
  6. Call theme::apply(&path, &cfg).
  7. Update state.wallpaper and state.backend, save state.
  8. Print chosen path.

src/wall/mod.rs:62-75

4.5 Backend integration

The wall::backend module abstracts backend-specific commands: src/wall/backend.rs:1-24

pub fn set(path: &Path, backend: &str) -> Result<()> {
    let img_path = path.to_str().context("wallpaper path is not valid utf-8")?;
    match backend {
        "hyprpaper" => cmd::run("hyprctl", &["hyprpaper", "wallpaper", &format!("eDP-1, {img_path}")]),
        "swww" => cmd::run("swww", &["img", img_path]),
        "none" => Ok(()),
        _ => bail!("unkown backend {backend}"),
    } 
}
  • For "hyprpaper", it uses hyprctl hyprpaper wallpaper eDP-1, <img_path>.
  • For "swww", it uses swww img <img_path>.
  • For "none", it is a no-op.
  • Any other backend string results in an error.

src/wall/backend.rs:7-19

4.6 Wallpaper flow diagram

graph TD
  Start["Command: wall next/prev/start"] --> LoadCfgW["Config::load()"]
  LoadCfgW --> LoadStateW["State::load()"]
  LoadCfgW --> ListImgs["list_images(cfg)"]
  ListImgs --> ChooseIdx["Compute index / path"]
  ChooseIdx --> ChooseBackend["Resolve backend"]
  ChooseBackend --> BackendSet["backend::set(path, backend)"]
  BackendSet --> ThemeApply["theme::apply(path, cfg)"]
  ThemeApply --> UpdateState["Update State"]
  UpdateState --> SaveState["State::save()"]
  SaveState --> PrintPath["Print wallpaper path"]
Loading

Sources: src/wall/mod.rs:7-26, src/wall/mod.rs:28-50, src/wall/mod.rs:62-75, src/wall/backend.rs:7-19, src/theme.rs:26-55, src/state.rs:23-55


5. Theme application and bar restart

Sources: src/theme.rs:1-55, src/bar.rs:1-29, src/cmd.rs:1-18, examples/config.toml

5.1 Theme configuration and defaults

The Theme struct controls whether theming is performed and how the theme command is executed: src/theme.rs:9-24

#[derive(Deserialize, Debug)]
#[serde(default)]
pub struct Theme {
    enable: bool,
    command: String,
    args: Option<Vec<String>>
}

impl Default for Theme {
    fn default() -> Self {
        Self {
            enable: true,
            command: "wallust".into(),
            args: None,
        }
    }
}

When theme.enable is false, apply returns immediately without invoking any external commands. src/theme.rs:26-34

5.2 Theme application flow

theme::apply is invoked after wallpaper changes and during wall start: src/theme.rs:26-55, src/wall/mod.rs:44-50, src/wall/mod.rs:68-75

Steps:

  1. Check cfg.theme.enable; if false, return Ok(()).
  2. Expand tilde in path via paths::expand_tilde.
  3. Convert path to string, erroring if invalid UTF-8.
  4. Build arguments: start with ["run", <image>], then append any extra cfg.theme.args if present.
  5. Convert to &str slice and call cmd::run(&cfg.theme.command, &args_ref).
  6. If cfg.bar.restart_on_theme is true, call bar::restart(cfg).

src/theme.rs:26-55

cmd::run executes a child command and checks its exit status: src/cmd.rs:1-18

pub fn run(bin: &str, args: &[&str]) -> Result<()> {
    let status = Command::new(bin)
        .args(args)
        .status()
        .with_context(|| format!("failed to start {bin}"))?;
    
    if !status.success() {
        bail!("{bin} exited with {status}");
    }

    Ok(())
}

5.3 Bar restart logic

The Bar struct and restart function manage restarting the configured bar command: src/bar.rs:9-23

#[derive(Deserialize, Debug)]
#[serde(default)]
pub struct Bar {
    pub restart_on_theme: bool,
    pub command: String,
}

impl Default for Bar {
    fn default() -> Self {
        Self {
            restart_on_theme: true,
            command: "waybar".into(),
        }
    } 
}

pub fn restart(cfg: &Config) -> Result<()> {
    cmd::run("pkill", &[&cfg.bar.command])?;
    std::process::Command::new(&cfg.bar.command)
        .spawn()
        .with_context(|| format!("failed to start {}", cfg.bar.command))?;
    Ok(())
} 
  • First, pkill <bar.command> is called via cmd::run.
  • Then a new process for cfg.bar.command is spawned.

src/bar.rs:9-23

5.4 Theme and bar flow diagram

graph TD
  WallChange["Wallpaper updated"] --> ThemeApplyCall["theme::apply(path, cfg)"]
  ThemeApplyCall --> CheckEnable["theme.enable?"]
  CheckEnable -->|false| ThemeReturn["Return Ok(())"]
  CheckEnable -->|true| BuildArgs["Build args: run <image> + extra"]
  BuildArgs --> RunCmd["cmd::run(theme.command, args)"]
  RunCmd --> CheckBar["bar.restart_on_theme?"]
  CheckBar -->|false| EndTheme["Done"]
  CheckBar -->|true| BarRestart["bar::restart(cfg)"]
  BarRestart --> EndTheme
Loading

Sources: src/theme.rs:26-55, src/bar.rs:9-23, src/cmd.rs:1-18


6. Session startup

Sources: src/session.rs:1-31, examples/config.toml, src/wall/mod.rs:62-75, README.md:137-151

The session module provides a single action: rice session start. It spawns a list of configured processes and then restores the last wallpaper (with associated theming and bar restart behavior).

6.1 Session configuration and defaults

Session struct and Default: src/session.rs:7-18

#[derive(Deserialize, Debug)]
#[serde(default)]
pub struct Session {
    pub exec: Vec<String>,
}

impl Default for Session {
    fn default() -> Self {
        Self {
            exec: vec!["waybar".into(), "swaync".into(), "discord".into()],
        }
    }
}

The example config in README uses a shorter list: README.md:127-135

[session]
exec = ["waybar", "swaync"]

6.2 Session start flow

session::start() is invoked from main when the user runs rice session start. src/main.rs:15-18, src/cli.rs:30-34

Implementation: src/session.rs:20-31

pub fn start() -> Result<()> {
    let cfg = Config::load()?;
    
    for exec in cfg.session.exec {
        std::process::Command::new(&exec)
            .spawn()
            .with_context(|| format!("failed to start {exec}"))?;
    };    

    crate::wall::start()?;
    Ok(()) 
}

Sequence:

  1. Load Config.
  2. Iterate over cfg.session.exec, spawning each command as a child process.
  3. Call wall::start() to restore the last or first wallpaper (including theme and bar restart).
  4. Return Ok(()).

src/session.rs:20-31, src/wall/mod.rs:62-75

6.3 Session flow diagram

graph TD
  SessionCmd["Command: session start"] --> LoadCfgS["Config::load()"]
  LoadCfgS --> LoopExec["For each exec in session.exec"]
  LoopExec --> SpawnProc["spawn(exec)"]
  SpawnProc --> LoopExec
  LoopExec --> WallStart["wall::start()"]
  WallStart --> DoneSession["Return Ok(())"]
Loading

Sources: src/session.rs:20-31, src/wall/mod.rs:62-75


7. Notifications and assets

Sources: src/notifications.rs:1-62, src/paths.rs:37-45, src/main.rs:20-58

Notifications are optional desktop notifications triggered after command execution, depending on the success or failure of the operation and per-user configuration.

7.1 Notification configuration

Notifications struct with defaults: src/notifications.rs:11-24

  • on_success: default false.
  • on_error: default true.

These flags determine if success and error functions emit a notification.

7.2 Notification icon handling

The notification module embeds an icon and ensures it is written to disk: src/notifications.rs:5-9, src/notifications.rs:26-38

const ICON: &[u8] = include_bytes!("../assets/rice-notify.png");

fn ensure_icon() -> Result<PathBuf> {
    let path = crate::paths::icon_file()?;
    if !path.exists() {
        if let Some(dir) = path.parent() {
            crate::paths::ensure_dir(dir)?;
        }
        std::fs::write(&path, ICON)
            .with_context(|| format!("failed to write {}", path.display()))?;
    }
    Ok(path)
}

The file path is ~/.config/rice/icon.png as provided by paths::icon_file(). src/paths.rs:37-45

7.3 Success and error notification emission

show constructs a notification via notify_rust if ensure_icon and path conversion succeed: src/notifications.rs:40-48

fn show(body: &str, urgency: Urgency) {
    let Ok(icon) = ensure_icon() else { return };
    let Some(icon) = icon.to_str() else { return };
    let _ = Notification::new()
        .appname("rice")
        .summary("rice")
        .body(body)
        .icon(icon)
        .urgency(urgency)
        .show();
}

High-level entry points: src/notifications.rs:50-62

pub fn success(cfg: &Config, body: &str) {
    if cfg.notifications.on_success {
        show(body, Urgency::Low);
    }
}

pub fn error(cfg: &Config, body: &str) {
    if cfg.notifications.on_error {
        show(body, Urgency::Normal);
    }
}

These functions are called from main after command execution: src/main.rs:20-58

7.4 Notification flow diagram

graph TD
  CmdResult["Command result"] --> OkRes["Ok(())"]
  CmdResult --> ErrRes["Err(e)"]
  OkRes --> LoadCfgN1["Config::load()"]
  ErrRes --> LoadCfgN2["Config::load()"]
  LoadCfgN1 --> CheckSuccess["cfg.notifications.on_success?"]
  LoadCfgN2 --> CheckError["cfg.notifications.on_error?"]
  CheckSuccess -->|true| ShowSucc["show(body, Low)"]
  CheckSuccess -->|false| EndN1["No notification"]
  CheckError -->|true| ShowErr["show(body, Normal)"]
  CheckError -->|false| EndN2["No notification"]
  ShowSucc --> EndN1
  ShowErr --> EndN2
Loading

Sources: src/main.rs:20-58, src/notifications.rs:11-24, src/notifications.rs:40-62


8. File and directory layout

Sources: README.md:33-49, src/paths.rs:13-45, src/state.rs:23-55, src/notifications.rs:26-38, src/config.rs:15-27

8.1 Project structure on disk

From README: README.md:33-49

rice/
├── Cargo.toml
├── examples/
│   └── config.toml
├── rustfmt.toml
└── src/
    ├── main.rs
    ├── cli.rs
    ├── paths.rs
    ├── config.rs
    ├── state.rs
    ├── cmd.rs
    ├── theme.rs
    ├── bar.rs
    ├── session.rs
    └── wall/
        ├── mod.rs
        └── backend.rs

Runtime files are created in XDG directories:

File Purpose Creator
~/.config/rice/config.toml Main configuration TOML Config::load() on first run.
~/.cache/rice/state.json Wallpaper/backend state State::save().
~/.config/rice/icon.png Notification icon notifications::ensure_icon().

src/paths.rs:17-45, src/config.rs:15-27, src/state.rs:23-55, src/notifications.rs:26-38


9. Example usage patterns

Sources: README.md:23-31, README.md:137-151, src/cli.rs:18-34, src/main.rs:7-18

9.1 Basic wallpaper control

rice wall next
rice wall prev
rice wall start

README.md:23-31

9.2 Bar restart

rice bar restart
  • Terminates the configured bar command via pkill.
  • Spawns a new bar process with the same command name. src/bar.rs:9-23

README.md:23-31

9.3 Session startup

rice session start
  • Spawns each program in session.exec.
  • Restores wallpaper (and theme/bar behavior) via wall::start().

README.md:137-151, src/session.rs:20-31


10. Summary

rice provides a cohesive command-line interface for managing wallpapers, themes, bar restarts, and session startup in a Hyprland environment. Installation is performed via Cargo into ~/.cargo/bin, and configuration is stored in ~/.config/rice/config.toml, with sensible defaults derived from examples/config.toml. README.md:51-85, src/config.rs:3-27

At runtime, the main entrypoint routes CLI subcommands to wall, bar, and session modules, each of which uses structured configuration (Config), state (State), and helper utilities (cmd, paths, notifications) to execute external commands in a predictable way. Wallpaper operations integrate backend-specific logic, theming, and state persistence, while notifications optionally report success or failure. src/main.rs:7-18, src/wall/mod.rs:7-50, src/theme.rs:26-55, src/state.rs:23-55, src/notifications.rs:40-62

Developers extending or integrating rice should rely on the documented configuration schema, path helpers, and command flows described above to maintain consistent behavior across installation, configuration, and usage scenarios.

Clone this wiki locally