RAGS - v1.10.0
    Preparing search index...

    RAGS - v1.10.0

    RAGS (raf's AGS) is a fork of Aylur's GTK Shell (AGS) v1, maintained to keep the v1 API stable while focusing on performance, security, and packaging.

    RAGS is a library built for GJS that lets you define GTK 3 widgets declaratively with reactive property binding. It also provides services and utilities for interacting with the system so your widgets can respond to real-time state changes. GJS is the JavaScript runtime built on SpiderMonkey and GNOME platform libraries --- the same runtime GNOME Shell uses.

    This site is split into two specific sections, with differing purposes:

    Hand-written documentation covering concepts, configuration, and usage. Start here if you are new to RAGS.

    • Getting Started - Installation, writing your first widget, JavaScript basics, and setting up type checking.
    • Configuration - The config object, App singleton, Variables, reactivity model, widgets, services, utilities, theming, CLI usage, and Home Manager integration.
    • Advanced - Writing custom services, subclassing GTK widgets, common issues, and example configurations.
    • Services - Reference pages for each built-in service: Applications, Audio, Backlight, Battery, Bluetooth, Greetd, Hyprland, MPRIS, Network, Notifications, Power Profiles, and System Tray.

    Auto-generated from JSDoc annotations in the source code, listed under Modules in the sidebar. The main areas are:

    • Widgets - GTK widget wrappers with reactive property binding (Box, Button, Label, Window, Slider, Stack, and 27 more).
    • Services - Singleton GObject classes exposing system state (Audio, Battery, Network, Hyprland, Mpris, etc.).
    • Utils - Helper functions for shell commands, file I/O, timers, HTTP requests, and desktop notifications.
    • Core - The reactive primitives: Variable, Binding, Service base class, and the App singleton.
    Tip

    Use the sidebar to navigate between sections, or the search bar to find specific classes, functions, or types.

    const time = Variable("", {
    poll: [1000, function () {
    return Date().toString();
    }],
    });

    const Bar = (monitor) =>
    Widget.Window({
    monitor,
    name: `bar${monitor}`,
    anchor: ["top", "left", "right"],
    exclusivity: "exclusive",
    child: Widget.CenterBox({
    start_widget: Widget.Label({
    hpack: "center",
    label: "Welcome to RAGS!",
    }),
    end_widget: Widget.Label({
    hpack: "center",
    label: time.bind(),
    }),
    }),
    });

    App.config({
    windows: [Bar(0)],
    });

    Widgets are GTK 3 widget classes extended with reactive capabilities. Every widget supports property binding, CSS styling, event hooks, and keyboard shortcuts through the common Widget mixin.

    All widgets accept a setup callback invoked after construction, and support .hook(), .bind(), .on(), .poll(), and .keybind() methods for reactive composition.

    // Create widgets using factory functions
    const myBox = Widget.Box({
    vertical: true,
    css: "padding: 12px;",
    children: [
    Widget.Label({ label: "Hello" }),
    Widget.Button({
    child: Widget.Label({ label: "Click me" }),
    on_clicked: (self) => print("clicked!"),
    }),
    ],
    });

    // Bind reactive data to widget properties
    const myLabel = Widget.Label({
    label: someVariable.bind(),
    });

    // Use CSS class toggling
    const myButton = Widget.Button({
    setup: (self) => {
    self.toggleClassName("active", true);
    },
    });

    Variable is the core reactive primitive. It holds a value and notifies listeners when it changes.

    // Simple variable
    const count = Variable(0);
    count.value++;

    // Poll a command every 5 seconds
    const cpu = Variable("", {
    poll: [5000, "top -bn1 | grep Cpu"],
    });

    // Listen to a subprocess output stream
    const workspaces = Variable([], {
    listen: ["hyprctl workspaces -j", (out) => JSON.parse(out)],
    });

    // Bind to a widget property
    Widget.Label({ label: count.bind().as((v) => `Count: ${v}`) });

    Bindings connect reactive sources (services, variables) to widget properties. They transform values through a functional pipeline.

    // Bind a service property
    Widget.Label({
    label: Audio.speaker.bind("volume").as(
    (v) => `Volume: ${Math.round(v * 100)}%`,
    ),
    });

    // Merge multiple bindings
    const label = Utils.merge(
    [Battery.bind("percent"), Battery.bind("charging")],
    (percent, charging) => `${percent}%${charging ? " (charging)" : ""}`,
    );

    Services are singleton GObject subclasses that expose system state via D-Bus or other backends. They emit signals and notify on property changes.

    // Audio service
    const volume = Audio.speaker?.volume ?? 0;
    Audio.speaker?.connect("changed", () => {
    print(`Volume: ${Audio.speaker.volume}`);
    });

    // Battery service
    Widget.Label({
    label: Battery.bind("percent").as((p) => `${p}%`),
    });

    // Network service
    const ssid = Network.wifi?.ssid;
    const strength = Network.wifi?.strength;

    // Hyprland IPC
    Hyprland.active.workspace.bind("id");

    // MPRIS media players
    const player = Mpris.players[0];
    player?.playPause();
    // Run shell commands
    const output = Utils.exec("whoami");
    const asyncOutput = await Utils.execAsync("ls -la");

    // Spawn a long-running subprocess
    Utils.subprocess(
    ["tail", "-f", "/tmp/some.log"],
    (line) => print(line),
    );

    // File I/O
    const content = Utils.readFile("/etc/hostname");
    await Utils.writeFile("hello", "/tmp/test.txt");
    Utils.monitorFile("/tmp/test.txt", (file, event) => {
    print(`File changed: ${event}`);
    });

    // Timers
    Utils.timeout(1000, () => print("1 second later"));
    Utils.interval(5000, () => print("every 5 seconds"));

    // Desktop notifications
    Utils.notify({
    summary: "Hello",
    body: "This is a notification",
    iconName: "dialog-information",
    });

    Windows are positioned using the Wayland Layer Shell protocol.

    Widget.Window({
    name: "my-bar",
    anchor: ["top", "left", "right"],
    exclusivity: "exclusive",
    layer: "top",
    monitor: 0,
    margins: [0, 0, 0, 0],
    keymode: "on-demand",
    child: Widget.Box({/* ... */}),
    });

    The App singleton manages windows, CSS, and the application lifecycle.

    App.config({
    style: "./style.css",
    windows: [Bar(0), Notifications()],
    });

    // Dynamically manage windows
    App.toggleWindow("my-popup");
    App.openWindow("my-popup");
    App.closeWindow("my-popup");

    // Hot-reload CSS
    App.resetCss();
    App.applyCss("./style.css");