crates/core- shared WM model, resize, focus, and query logiccrates/css- CSS parser, compiler, metadata, and analysiscrates/scene- style matching and layout/scene computationcrates/runtimes/js/core- shared JS graph, compile, payload, and loader logiccrates/runtimes/js/native- native QuickJS config and layout runtimecrates/layout-runtime- end-to-end workspace evaluation and placement logiccrates/ffi- Rust bridge exposed to the Hyprland pluginapps/tilescript-playground- browser playground modeledplugin/hyprland/src/plugin.cpp- Hyprland-side plugin adapterpackages/sdk/js- config/layout SDK surfacepackages/lsp/vscode- VS Code client fortilescript-css-lspdev/test-config- local config fixtureexamples/js- JavaScript/TypeScript starter configexamples/lua- Lua starter configexamples/fennel- Fennel starter config
Recommended entrypoints:
make hypr-plugin
make playground
make test
make liveRust:
cargo test -p tilescript-scene
cargo test -p tilescript-layout-runtime
cargo test -p tilescript-runtime-js-core
cargo test -p tilescript-runtime-js-native
cargo build --release -p tilescript-ffiPlugin:
cmake -S . -B build
cmake --build buildcmake --build build builds the Rust release FFI staticlib before linking build/tilescript-hypr.so.
JS tooling:
pnpm install
pnpm fmt
pnpm lint
pnpm --filter tilescript-css-lsp-vscode run checkPlayground:
make playgroundapps/tilescript-playground
- preview route
- editor route with workspace file tree and live buffers
- system route with state/diagnostics
There are two Hyprland plugin workflows:
- daily-driver plugin build in
build/tilescript-hypr.so - nested debug plugin build in
build-hypr-dev/tilescript-hypr-dev.so
Hyprland is tracked as a git submodule at third_party/Hyprland/.
One-time prerequisites:
make hypr-bootstrap
make hypr-buildBuild the nested-debug plugin against that exact Hyprland tree:
make hypr-plugin-devThat copies the dev plugin to ${XDG_DATA_HOME:-$HOME/.local/share}/tilescript/tilescript-hypr-dev.so.
Launch a nested debug Hyprland session with the repo config:
make hypr-run-devThat target:
- configures
tilescriptdirectly againstthird_party/Hyprland/srcandthird_party/Hyprland/build - launches
third_party/Hyprland/build/Hyprland --config dev/hypr/hyprland.conf
If the Hyprland binary is missing, hypr-run-dev tells you to run make hypr-build first.
If the plugin was built against a different Hyprland revision than the running compositor, plugin init fails with a clear hash-mismatch error instead of relying on undefined ABI behavior.
dev/hypr/hyprland.conf uses:
plugin = $XDG_DATA_HOME/tilescript/tilescript-hypr-dev.soconfig_path = ../../dev/test
For a daily-driver Hyprland session, build the normal plugin and print the corresponding config snippet:
make hypr-plugin
make hypr-plugin-snippetmake hypr-plugin-snippet prints the exact plugin block to paste into your normal Hyprland config. It does not write a config file or load the plugin automatically.
Daily-driver loading uses ${XDG_DATA_HOME:-$HOME/.local/share}/tilescript/tilescript-hypr.so, while the nested debug session uses ${XDG_DATA_HOME:-$HOME/.local/share}/tilescript/tilescript-hypr-dev.so.
Reload loop from inside the nested session:
make hypr-reloadThat rebuilds the nested plugin, copies it to ${XDG_DATA_HOME:-$HOME/.local/share}/tilescript/tilescript-hypr-dev.so, and prints the unload/load command.
Reload loop for your daily-driver Hyprland session:
make hypr-user-reloadThat rebuilds the normal plugin, copies it to ${XDG_DATA_HOME:-$HOME/.local/share}/tilescript/tilescript-hypr.so, and prints the unload/load command for the daily-driver instance.
Useful runtime inspection commands:
hyprctl tilescript-hypr
hyprctl tilescript-hypr reload-layouts
hyprctl tilescript-hypr debug-layout-workspace 1hyprctl tilescript-hypr returns plugin/runtime status, layout load state, errors, and structured CSS diagnostics.
dev/test-config/ is the main local config fixture.
Use it for:
- runtime-js tests
- layout-runtime tests
- local Hyprland plugin validation
examples/js/ is the default starter project skeleton used by plugin bootstrap.
examples/lua/ mirrors the same starter layout in Lua form.
For external config roots, the Hyprland plugin manages a local SDK mirror under:
.sdk/.sdk/tsconfig.json.sdk/package.json.sdk/src/*.d.ts.sdk/src/*.js
The plugin bootstraps missing config roots from examples/js/ and refreshes that managed SDK support when it resolves and loads the config root.
- Rust formatting:
rustfmt.toml - JS/TS formatting:
.oxfmtrc.json - linting:
.oxlintrc.json
README.mddocs/config.mddocs/hyprland.mddocs/jsx.mddocs/css.mddocs/css-lsp.mddocs/development.mddocs/playground.md