## What are the changes about?
Adds zlua for running Lua code as the configuration file.
Missing as of this time:
- ~~Parsing custom binds and labels~~
- ~~Fix memory leaks~~
- ~~Investigate issue with animation colours~~
- ~~Add examples and default config~~
## What existing issue does this resolve?
[#976](https://codeberg.org/fairyglade/ly/issues/976)
## Pre-requisites
- [ ] I have tested & confirmed the changes work locally
- [ ] I have run `zig fmt` throughout my changes
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/1010
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
An update to #1042
## What are the changes about?
This no longer creates a new file and instead appends the new save data to the existing file in a backwards compatible way.
It can differentiate by using a prefix to the string (which would usually be the username) of "ly/tty".
Usernames on supported systems aren't able to include a forward slash, and if they could, the chances of those colliding..
The rest follows the last PR:
Fix using saved user list where it shouldn't
Now saves users that weren't previously in the save file (fixes TODO)
Since we save only valid state, the save file is self-cleaning of bad/outdated data
## What existing issue(s) does this resolve?
#1040
## Pre-requisites
- [ x ] I have tested & confirmed the changes work locally (freebsd, void linux)
- [ x ] I have read and fully adhere to the rules set in the contributing guidelines found in `CONTRIBUTING.md`
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/1044
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
## What are the changes about?
Allows the game of life animation to be ran with configurable rules, specifically: the neighbors required for birth and survival.
### Example: [B3/S12345 (Maze)](https://conwaylife.com/wiki/OCA:Maze)
(where numbers after B are neighbors required for birth, and S for survival)
<video src="/attachments/49120c5e-ce21-4025-852e-924befbc2621" title="Screencast_20260814_233338" controls></video>
Introduces two keys to the config:
```ini
# Sets the multiple amounts of neighbors needed for a cell to survive.
# Each numerical digit from 0 to 8 inclusive in this string becomes
# one of the targets required for this cell to survive.
# Example: a string of "23" makes the cell survive on 2 or 3 neighbors
gameoflife_param_survival = "23"
# Sets the multiple amounts of neighbors needed for a cell to be born.
# Each numerical digit from 0 to 8 inclusive in this string becomes
# one of the targets required for this cell to be born.
# Example: a string of "3" makes the cell be born on 3 neighbors
gameoflife_param_birth = "3"
```
## What existing issue(s) does this resolve?
Solves !1023
## Pre-requisites
- [x] I have tested & confirmed the changes work locally
- [x] I have read and fully adhere to the rules set in the contributing guidelines found in `CONTRIBUTING.md`
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/1041
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
## What are the changes about?
Add optional `bigclock_outline_fg`. When set, each big-clock digit gets a 1-cell outline drawn under the glyph so it stays readable over busy animations. Default is `null` (previous behavior).
When the outline is enabled, the gap under the clock is slightly larger so the stroke is not glued to the login box.
## What existing issue(s) does this resolve?
Fixes#1030
## Pre-requisites
- [x] I have tested & confirmed the changes work locally
- [x] I have read and fully adhere to the rules set in the contributing guidelines found in `CONTRIBUTING.md`
### Testing
- `zig build -Doptimize=ReleaseSafe` (zig 0.16.0)
- Greeter with `bigclock = en` and `bigclock_outline_fg = 0x20000000` over a `dur_file` animation
- Default `null` leaves stock look unchanged
### AI usage (per contributing.md)
Assisted by an LLM (xAI Grok) for exploration and drafting. I directed the design (optional outline only, no panel/box, stock layout otherwise), reviewed the Zig, fixed an `i2` overflow in the outline loop, verified the build/local greeter, and wrote this PR text.
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/1031
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
## What are the changes about?
Add corner customization (what is in which corner of the screen)
## What existing issue does this resolve?
Issue #961
## Pre-requisites
- [x] I have tested & confirmed the changes work locally
- [x] I have run `zig fmt` throughout my changes
Co-authored-by: AnErrupTion <anerruption@disroot.org>
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/963
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
## What are the changes about?
Add an option to allow user manually input username, instead of selecting from a list of discovered users.
I have not tested the changes yet since I wasnt able to get it build locally. Will try to resolve this asap.
## What existing issue does this resolve?
#891
## Pre-requisites
- [ ] I have tested & confirmed the changes work locally
- [x] I have run `zig fmt` throughout my changes
Co-authored-by: HigherOrderLogic <73709188+HigherOrderLogic@users.noreply.github.com>
Co-authored-by: AnErrupTion <anerruption@disroot.org>
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/1012
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
## What are the changes about?
So far ly only supported showing battery capacity on Linux. This adds support for FreeBSD as well using `sysctlbyname()` instead of reading from `/sys/...`
## What existing issue does this resolve?
No battery shown on FreeBSD.
_Replace this with a reference to an existing issue, or N/A if there is none_
## Pre-requisites
- [x] I have tested & confirmed the changes work locally
- [x] I have run `zig fmt` throughout my changes
Co-authored-by: AnErrupTion <anerruption+codeberg@disroot.org>
Co-authored-by: AnErrupTion <anerruption@disroot.org>
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/988
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
## What are the changes about?
TL;DR:

Slaps the entire LuaJIT runtime onto Ly, allowing for the creation of custom dynamic animations like GameOfLife, ColorWave, Doom, etc.
This PR adds the [ziglua](https://github.com/natecraddock/ziglua?ref=zig-0.16) dependency for its zig bindings and considerable buildtime config (mainly lua version selection).
### Example
<video src="/attachments/3f91cf72-ae24-459c-8ef6-099f71e866fd" title="Screencast_20260519_172320" controls></video>
```lua
ly.frame_delay = 5
local timer = 0
local clock = os.clock()
local clock_diff = 0
function draw()
timer = timer + 1
byte = string.byte(' ')
clock_diff = os.clock() - clock
clock = os.clock()
timer = timer + clock_diff
for x = 0, ly.width-1 do
for y = 0, ly.height-1 do
local xc = 0xFF
if x < 255 then xc = ((x + math.floor(timer / 2)) * 3) % 255 else xc = 0 end
local yc = 0xFF
if y < 255 then yc = ((y) * 3) % 255 else yc = 0 end
ly.putCell(byte, xc, bit.bor(xc, yc), x, y)
end
end
end
```
### The API
The API that Ly gives to the user is minimal. A table is globally available, named `ly`, which provides the following:
| Member | Purpose |
|---------|---------|
| `ly.width` & `ly.height` | Respective Width/Height from the `TerminalBuffer` |
| `ly.putCell(byte, fg, bg, x, y)` | Literally `Cell.init(byte, fg, bg).put(x, y)`.|
| `ly.clock()` | The current real-time, in microseconds. |
### Error Handling
On a Lua Error, Ly won't quit but will instead paint the entire background red. The lua error in question can be found in the Ly log file and on-screen.
```log
2026-05-19 16:13:40 [err/Lua] Error (Cannot call draw()): attempt to call a nil value
2026-05-19 11:05:51 [err/Lua] Lua Error: ...dsammyt/programming/probe/ly/scratch/testConfig/test.lua:30: bad argument #1 to 'ipairs' (table expected, got number)
```
## Pre-requisites
- [X] I have tested & confirmed the changes work locally
- [X] I have run `zig fmt` throughout my changes
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/1001
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
Animations bigger than the rendering area would have an alignment to the
top left instead of center.
## What are the changes about?
Fixes incorrect offset calculations for dur movies bigger than the screen.
## What existing issue does this resolve?
N/A
## Pre-requisites
- [x] I have tested & confirmed the changes work locally
- [x] I have run `zig fmt` throughout my changes
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/966
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
## What are the changes about?
Added a new option in the configuration file for moving the box relative to the screen size.
```
box_h_position = 0.5
box_v_position = 0.5
```
The big clock is centered relative to the box. In the cases where it would be outside of the screen, it moves the box to fit in the screen.
## What existing issue does this resolve?
Add more options for personalization
## Examples
Normal usage:
```
box_h_position = 0.15
box_v_position = 0.35
```

Clock would be outside of the screen vertically:
```
box_h_position = 0.15
box_v_position = -1.0
```

Clock would be outside of the screen horizontally and vertically:
```
box_h_position = -1.0
box_v_position = -1.0
input_len = 3
```

Clock would be outside of the screen horizontally and vertically on the bottom left of the screen:
```
box_h_position = 2.0
box_v_position = 2.0
input_len = 3
```

## What existing issue does this resolve?
_Replace this with a reference to an existing issue, or N/A if there is none_
## Pre-requisites
- [x] I have tested & confirmed the changes work locally
- [x] I have run `zig fmt` throughout my changes
Co-authored-by: AnErrupTion <anerruption+codeberg@disroot.org>
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/964
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
## What are the changes about?
Fixes battery label positioning in regards to custom binds.
Since the label was on the top-left, it only accounted for the first line of built-in keybinds, and it didn't account for the other lines of custom ones.
This also fixes the custom keybinds not disappearing on `hide_key_hints = false`, which is my bad. whoops.
Also, with https://codeberg.org/fairyglade/ly/pulls/963 being a thing, we should probably think about deprecating this hardcoded battery label in favor of a custom label command, top-left by default.
## What existing issue does this resolve?
N/A
## Pre-requisites
- [x] I have tested & confirmed the changes work locally
- [x] I have run `zig fmt` throughout my changes
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/970
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
Signed-off-by: AnErrupTion <anerruption@disroot.org>
## What are the changes about?
Ports the code base to Zig 0.16.0.
## What existing issue does this resolve?
N/A
## Pre-requisites
- [x] I have tested & confirmed the changes work locally
- [x] I have run `zig fmt` throughout my changes
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/962
The shell session is unconditionally added to the session list with no way to hide it. This is inconsistent with `xinitrc`, which is omitted from the list when set to `null`.
This change adds a `shell` boolean config option (default `true`). Setting it to `false` hides the shell session from the list, following the same pattern as `xinitrc`.
Co-authored-by: Jackson Delahunt <jackson@stemn.com>
Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/955
Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org>
Co-authored-by: Jackson Delahunt <sabrehagen@noreply.codeberg.org>
Co-committed-by: Jackson Delahunt <sabrehagen@noreply.codeberg.org>