Sno Station
Sno Station is your agents' workstation: open-source software that turns the AI agents you already run into one squad on your own machine. Two heads are better than one, and they get better with every
Vyechi | Cultivating Balance, Grounding Thoughts, and Meaningful Connection for a Fulfilling Life.
PluginsPython · HTMLGitHub @VyecheOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Krita plugin: shade a sphere from three colours to study how key light, ambient and base colour interact, then sample the result into your brush.
Taken from the repository README
Loading the full README.
Read the full README ↗An interactive lighting study tool for Krita. A sphere is shaded from three colours you control — shadow, base and light — so you can read how a key light, an ambient bounce and an object's local colour interact, then sample the resulting values straight into your brush.
The useful question it answers is never "what is the local colour" but "what does this surface look like under this light" — which is why it earns its keep on flat and cel-shaded illustration and on 3D shading and rendering. Pick the cel-shaded bands, pick the smooth falloff; the three targets and the shading controls work either way, and the sphere shows you which one you are actually looking at.
Painted in Krita with its own brushes, every colour read off the Lumina sphere zone by zone. Lumina stays docked beside the canvas the whole time. Watch it with sound on YouTube, or read how Lumina was built on the author's blog.
That shot is the two worlds side by side. The beach is flat graphic work — banded sky, hard-edged sun, silhouette palm and dog, birds, a fish shoal. The panel beside it is a smoothly shaded 3D sphere lit from the same key. Three colours sampled off the artwork — a sunset orange, a sea teal and a sand cream — sit in Recent picks, and Lumina derived a coherent shadow / base / light set from the orange; the sphere is what those values look like rendered rather than banded. (The strip along the bottom of the canvas was painted from an earlier version of these derivations.)
New here? Start with Getting started.
From a release: download the Lumina-*.zip file, then in Krita go to
Tools → Scripts → Import Python Plugin from File and select the zip —
import it directly, no need to extract anything. Then restart Krita.
From source (the plugin runs inside the Krita flatpak). From the repository root:
DEPLOY="$HOME/.var/app/org.kde.krita/data/krita/pykrita"
rsync -a --delete --exclude='__pycache__' --exclude='.pytest_cache' --exclude='lumina_log.txt' src/Lumina/ "$DEPLOY/Lumina/"
cp src/Lumina.desktop "$DEPLOY/"
Then restart Krita — it caches its plugin list at startup, so closing the window is not enough. The dock appears under Settings → Dockers → Lumina.
See documentation/KritaFlatpak.md for the full deploy, cache-clear and verification steps, including a headless check that runs the plugin under Krita's own Python.
The sphere is a unit hemisphere. Each pixel maps to a surface normal, and the shading is evaluated per pixel:
surface = base, its hue moving toward the shadow's by signed N·L # into the core
+ base -> light toward the lit peak
body = surface × diffuse (soft floor, no hard terminator)
+ environment light × surface colour # sky, ground, ambient
+ reflected light on the edge away from the light
+ specular lobe centred toward the light
+ Fresnel rim at the silhouette
then contrast, saturation, mixer, glow and a soft display roll-off
The shading engine (color_engine.py) is deliberately free of Qt and Krita
imports, so the whole render can be unit-tested on any machine. See
documentation/ARCHITECTURE.md for the design
decisions and the reasoning behind each tuning constant.
src/Lumina/
__init__.py Registers the dock widget factory with Krita
sphere_docker.py The docker: layout, controls, presets, persistence
sphere_widget.py The sphere: painting, picking, hover sampler
color_engine.py Pure-Python shading engine (no Qt, no Krita)
color_processor.py Adapter between the engine and Krita/Qt
color_controls.py Sliders, buttons, lemon sampler, recent picks, settings panel
derivation.py Light / shadow derivation and the OKLCH slider maths
test_shading.py Smoke tests (needs PyQt5, no Krita)
test_shading_standalone.py Engine tests, run from the repository root
Lumina was written with AI coding assistance, directed and reviewed by a human who decided the design, the tuning constants, and every call about scope. Disclosing that seems better than shipping code whose provenance people might assume is different.
The plugin itself contains no AI and makes no network calls. It is a Phong shading model implemented directly. Nothing is generated at runtime, nothing is downloaded, nothing is sent anywhere.
Development ran through a local harness with Guard in the loop. It gates actions before the assistant takes them — destructive shell commands, secret access, software installs, data movement — by allowing, asking, or blocking, and keeps a record of what happened. It guards the machine, not the source: nothing it protects lives in this repository, and the plugin ships with none of it.
One constraint shaped the whole codebase: keep the import surface as small as possible.
color_engine.py, which does all the actual shading, imports only the standard
library: math, time, logging and typing. The rest
of the plugin adds only PyQt5, which Krita already ships, and Krita's own
scripting module (modules of the plugin itself in italics):
| Module | Imports |
|---|---|
color_engine.py | math, time, logging, typing |
derivation.py | math |
color_processor.py | PyQt5, collections, copy, importlib, os, time, typing, color_engine |
color_controls.py | PyQt5, math, random, time, typing, derivation, tooltip, typed_entry |
sphere_widget.py | PyQt5, math, typing, lumina_logging |
sphere_docker.py | PyQt5, krita, concurrent.futures, json, math, os, sys, threading, time, typing, weakref, the modules above |
Every one of those is either the Python standard library or shipped with Krita. There is no numpy, no colour-science library, no third-party package of any kind, and nothing to install.
That was not asceticism. It means:
If you want to check that for yourself, the whole import surface is one command:
grep -rhE '^\s*(import|from)\s' src/Lumina/*.py | sort -u
If you contribute, please keep it that way. It is the plugin's main practical advantage over anything built on a shading or colour library.
Contributions are genuinely welcome — bug reports, fixes, presets, translations, and especially real artists telling us what is awkward to use, which is the feedback that has changed this plugin the most.
Everyone taking part is expected to follow the Code of Conduct.
A few things that will make a patch easy to merge:
Open an issue first for anything larger than a fix, so we can agree on the approach before you spend an evening on it.
Keep the engine pure. Changes to color_engine.py must not import Qt,
Krita, or anything outside the standard library. It is the one file the test
suite can run anywhere, and that is worth protecting.
Run the tests before opening a pull request:
python3 src/Lumina/test_shading_standalone.py # from the repo root
Match the surrounding style — 4-space indent, docstrings on anything non-obvious, and comments that explain why rather than restate the code. There is a fair amount of that in here, and it is deliberate.
If you are new to the codebase, documentation/ARCHITECTURE.md explains the module layout and where each decision came from. documentation/Bugs.md records what has already gone wrong and how it was fixed, which is probably the fastest way to learn the traps.
Lumina is free and MIT licensed, and it will stay that way. If it earns its keep for you and you'd like to say so:
Sponsorship goes toward keeping it working against new Krita releases, and toward the time that goes into bug reports and feature work from people who aren't writing code. It is genuinely optional, and the plugin does not gate anything behind it.
If you would rather not sponsor, a star, an issue with a real bug report, or telling a colleague about it helps just as much. Those are the things that actually change the software.
python3 src/Lumina/test_shading_standalone.py # from the repo root
python3 src/Lumina/test_shading.py # needs PyQt5
test_shading_standalone.py hardcodes repo-relative paths, so it must be run
from the repository root — from inside src/Lumina/ it fails with a
FileNotFoundError on a doubled path.
| File | Description |
|---|---|
| documentation/GettingStarted.md | Install, enable, and a walkthrough with screenshots |
| documentation/ARCHITECTURE.md | Module layout, data flow, design decisions |
| documentation/KritaFlatpak.md | Deployment — the single source of truth |
| documentation/TestingGuide.md | The test suites and how to run them |
| documentation/Bugs.md | Bugs hit, with the real crash logs and the fixes |
| documentation/CommonIssues.md | Wider troubleshooting |
| src/Lumina/MANUAL.md | The user-facing manual Krita shows under Help → Plugin Help |