thurbox-ui
Edit the thurbox TUI — add, change or remove a pane of the running interface, which is Lua files in the thurbox interface directory (not this repository)
Install / Use
npx skills add Thurbeen/thurbox --skill ui-skillInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
MarketingSupported Platforms
Our assessment of thurbox-ui
thurbox-ui scores 80/100 on our quality scale, 528th of 582 Marketing skills we index.
Its SKILL.md is 13 KB long, well organised into 12 sections with 5 code examples: a thorough specification that gives an agent plenty to work with.
It has no GitHub stars yet, so there is no community track record; judge it on its content.
Maintenance, license and trust
- The repository was last updated today, so thurbox-ui is actively maintained.
- Our last check on 2026-09-12 found the source still online.
- No license is declared. By default that means all rights are reserved: you can read it, but reusing or redistributing it is not clearly permitted. Ask the author before building on it commercially.
- Its trust signals score 80/100, with 2 cautions from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
thurbox-ui compared with similar skills
All 4 of these similar skills score higher than thurbox-ui; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| thurbox-ui (this skill)by Thurbeen | 80 | 0 | today | SKILL.md |
| algorithmic-artby anthropics | 100 | 177.9k | 33d ago | SKILL.md |
| pptxby anthropics | 100 | 177.9k | 33d ago | SKILL.md |
| designby nextlevelbuilder | 100 | 137.2k | 11d ago | SKILL.md |
| ui-ux-pro-maxby nextlevelbuilder | 100 | 137.2k | 11d ago | SKILL.md |
Frequently asked questions
- How do I install thurbox-ui?
- Run
npx skills add Thurbeen/thurbox --skill thurbox-ui. The install tabs above show the steps for each supported agent. - Which AI agents does thurbox-ui work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is thurbox-ui safe to use?
- It declares no license and scores 80/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is thurbox-ui still maintained?
- The repository was last updated today, so thurbox-ui is actively maintained.
Skill content
View source on GitHubname: thurbox-ui
description: Edit the thurbox TUI — add, change or remove a pane of the running interface, which is Lua files in the thurbox interface directory (not this repository). Use whenever the user asks to change how thurbox itself looks or behaves on screen — a new pane or panel, a different layout or arrangement, a keybinding, a status line, colours or theme roles, or "add X to the sidebar". Also use for thurbox-cli plugin work — install, sync, check or debug an interface plugin, or a pane that loads but draws nothing.
Editing the thurbox interface
Managed by thurbox
extension install— see Updating this skill at the bottom before editing it.
thurbox's interface has no built-in screen underneath. Every pane is a Lua file in one directory, the kernel reads that directory at startup, and saving a file reloads it. Changing the TUI means editing Lua there — never Rust, and never the repository this session happens to be sitting in.
First: find the directory
The interface is not in the current repo. It is a config directory of the user's, so it is almost always outside this session's worktree:
thurbox-cli plugin dir # the directory in force, and which rule chose it
Two rules pick it: THURBOX_UI_DIR if set, otherwise the user's own copy —
~/.config/thurbox/ui, or ~/.config/thurbox-dev/ui for a dev build. Run the
command; do not assume which. If you cannot write outside this session's
worktree, say so and ask for that path to be allowed — do not edit something
else instead and report it as done.
A thurbox checkout's ui/ is not the live interface. Editing ui/ inside a
clone of the thurbox repository changes nothing on screen unless
THURBOX_UI_DIR points at it (just tui-ui in that repo does exactly that). If
the user wants their running thurbox changed, the destination is plugin dir's
answer. If they want the shipped interface changed, it is the checkout, and
that is a code change with a pull request behind it — ask which they mean when
both are plausible.
Then: read the directory's own docs
The directory ships the reference, and it is versioned with the binary the user is running, so it is more current than anything you remember:
UI="$(thurbox-cli plugin dir --text | head -1)" # or: plugin dir --json | jq -r .dir
cat "$UI/AGENTS.md" # the operational half — what is easy to get wrong
cat "$UI/README.md" # the reference — node kinds, the API, the traps
cat "$UI/layout.lua" # the arrangement — which slots exist and where
ls "$UI/plugins" "$UI/lib"
The --text is load-bearing: thurbox-cli switches to TOON — its compact
machine encoding — the moment its stdout is a pipe, so a bare plugin dir | head -1 hands you that, not a path.
Read AGENTS.md before your first edit of a session. The rest of this skill is
the short version — enough to judge a request and to not make the two mistakes
that fail silently.
The loop: edit, then check
thurbox-cli plugin check # loads the interface exactly as thurbox does
Run it after every edit and do not report an edit as done without it. It exits non-zero on failure and it catches the failure that looks like success:
- a file that will not load, named with its reason;
- a pane that loads and draws nothing, because no arrangement places its
slot. It compiles, declares its keys, appears in
plugin list, and is absent from the screen.checkprints thelayout.lualine to add.
Then thurbox-cli plugin list shows every file, where it came from, and whether
it is drawing. In a running thurbox, F10 reloads from disk and Ctrl+, → ]
is the same inventory.
Adding a pane is two edits
The plugin file and its slot in layout.lua. A pane names a slot; the
arrangement decides where that slot goes. Miss the second and you get the
silent failure above. thurbox-cli plugin new <name> writes a starter that
already loads, and thurbox-cli plugin install prints the layout.lua line for
what it installed. Nothing writes the arrangement for you — that edit is yours.
A pane sharing a switch slot is the quieter version: the slot's first
occupant is shown and yours waits until it is focused. Declare a pill and the
action band offers it:
pills = { { action = "mine.open", label = "Mine", priority = 10 } },
The five rules the kernel actually enforces
- Four node kinds, forever —
text,box,input,surface. Lists, panels, tables and gauges are not node kinds; they compose inlib/widgets.lua. Wanting a fifth kind means wanting a widget. - Layout resolves before render. Size is declared statically in the
plugin's table, never returned from
render. That is what lets the kernel hand yourrenderthe rect it is drawing into (ctx.width,ctx.height,ctx.focused). - Snapshot-read, command-write. Reads come from an in-memory snapshot and
return instantly; writes are
command(name, args)calls the kernel applies later. Nothing you write can stall the render loop on SQLite, git or an unreachable host. - Capabilities by absence. An ungranted capability is not in the
environment —
runis nil, not a function that errors. - Anything touching the world runs on a worker. You ask; the answer appears on a later frame.
What exists inside a pane, and what does not
Standard library: string, table, math, coroutine, utf8, plus the base
functions. Injected globals: thurbox (the snapshot — .sessions, .settings,
.theme, .repos, .runs, .diffs, .metrics, .chrome, .platform,
.granted, …), command(name, args), store, state, require (for lib/
only), files, and run(key, cmd, opts) when the user has trusted the file.
A plugin may also react: declare events = { "session.status", … } with an
on_event(name, payload) handler and the kernel calls it once per change
(thurbox-cli plugin events lists them with their payloads; an unknown name
refuses to load). commands = { { action, desc } } puts an action in the
Ctrl+P palette with no chord, run through the same on_action as a key.
command("emit", { text = "x", … }) reaches other plugins as user.x.
Deliberately absent: os, io, debug, package, print, dofile,
load, loadstring, and require of anything outside lib/. They are not
blocked, they are missing — os.time() is attempt to index a nil value, not
a permission error. If you reach for one, the design is wrong, not the sandbox.
There is no npm, cargo, pip or go get here, and nothing to run one
on. A pane's only dependencies are the modules already in lib/. Never build
under the interface directory: it is watched recursively, and a burst of events
keeps the debounce rolling forward, so the symptom is not "reloads too often",
it is stops reloading at all. Generated files belong in
$XDG_CACHE_HOME/<plugin>/.
Traps that cost real time
- Asking every frame is correct.
run(...)and thestore.want_*reads are designed to be called on every render — a fresh answer is a table lookup, not a process. Trying to call them "only once" gets you a pane that never updates. - The answer is not there yet.
runreturns nothing useful on the frame you ask. Readthurbox.runs[key]and handlenilandstate ~= "done". runis nil until the user trusts the file. Declaringcapabilities = { "run" }does not grant it — the user does, in settings (Ctrl+,→]→t). Checkif not run thenand draw something honest. You cannot do that step for them, and you must not editui.jsonto fake it.- A program pane needs
focusable = true, andthurbox.granted.programchecked, sincecommandis present whether or not you may. - A plugin-scoped chord does not outrank a global one. After adding a key,
check
F1: if it is not listed, it did not bind. theme.*returns roles, not colours. Ask fortheme.accentortheme.mutedso the pane reads correctly under all thirty-six palettes. Never hardcode a hex value.- Give a pane one key that both enters and leaves it, with
command("focus", { text = "review", toggle = true }), declaredscope = "global"and preferably an F-key — a focused terminal keeps the barectrl+<letter>chords for the program in it. A pane that only focuses itself is a one-way door.
Performance: make the pane cost what changed, not what exists
render runs on the UI thread up to thirty times a second, so the kernel gives
every pane three levers — and a custom pane that skips them is the one thing
that can make the whole interface feel slow.
- Declare
pure = trueunless the render writes. A pure render readsthurbox.*,ctx,storeandstateand returns a tree; the kernel then reuses that tree until something it read actually changes, and skips your Lua entirely on every other frame. This is the single biggest lever. It is only wrong ifrenderwritesstore/stateor callscommand— move those writes intoon_key/on_action/on_clickand purity comes back. Floats especially: a float renders every frame even while closed, so an impure closed modal costs a Lua call per frame forever. - Memoize on table identity, not by re-deriving. The published groups
(
thurbox.sessions,thurbox.theme,thurbox.registry,thurbox.diffs,thurbox.bookmarks, …) keep the same table until their data moves, sorawequal(thurbox.sessions, cache.src)is a sound, one-comparison way to know your derived model is still valid. Build the model once, keep it in an upvalue, rebuild only when the identity changes. Never compare by serialising, and never cache across frames on anything time-based. - Window first, build second. Compute which rows are visible
(
widgets.window) before building spans for them. Building every row of a long list and letting the list widget crop it does all the work for rows nobody sees. - Hoist per-row work out of the loop. A
store.*read crosses into Rust; atheme.role(...)lookup walks tables;fuzzy.compile(query)splits the query once so per-row matching doesn't re-split it. Read once per render, pass values down. - Strings: concatenate through a table.
s = s .. piecein a loop over a wide row is O(width²); accumulate into a table andtable.concat, or emitstring.repruns. - Animation is not free-running, and reading the clock is what buys it.
ctx.elapsedplus the shared spinner helper inlib/follows the kernel's animation clock, which only ticks while something is actually animating — a pane that derives its own timer from elapsed on every frame re-renders forever and defeats its ownpure. Readingctx.elapsedis also what keys your cached tree on that tick, so read it where you animate and not at the top of a render that usually draws nothing moving.
F12 opens the perf HUD: renders climbing while you touch nothing means a
pane is not settling — usually an impure render or a per-frame store write of
an unchanged value (writing the same value is free; writing a fresh table each
frame is not).
"Install a plugin" means thurbox-cli plugin install
A plugin here is a thurbox interface pane, not a package from a language registry:
thurbox-cli plugin available # what installs by bare name
thurbox-cli plugin install <name> # or a URL, or a path
thurbox-cli plugin install git+<url> # a repository: cloned, payload and all
thurbox-cli plugin sync # after editing plugins.toml by hand
thurbox-cli plugin remove <name> # file, spec entry and record
git+<url> puts that repository's files on the user's disk, executables
included. Say so plainly before running it, and never install a repository the
user did not name. Nothing is executed by installing, and a program still n
Truncated for display — read the full file on GitHub.
Related Skills
algorithmic-art
177.9kCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems.
pptx
177.9kUse this skill any time a .pptx or .potx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx or .potx file (even if the extracted content will be used elsewhere, like in an em…
design
137.2kComprehensive design skill: brand identity, design tokens, UI styling, logo generation (55 styles, Gemini, Atlas Cloud, or MuAPI AI), corporate identity program (50 deliverables, CIP mockups), HTML presentations (Chart.js), banner design (22 styles, social/ads/web/print), icon design (15 styles, SVG…
ui-ux-pro-max
137.2kUI/UX design intelligence for web, mobile, and desktop. This skill should be used when designing, building, reviewing, or fixing interfaces, including pages, components, design systems, accessibility, interaction, responsive layout, typography, color, charts, and stack-specific UI implementation.
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
