thurbox: Skill for Claude Code

.agents/skills/thurbox-testing/SKILL.md

thurbox-testing is a skill for Claude Code, Codex from Thurbeen/thurbox. It costs 0 tokens per session (6,107 once invoked), scanned A, original, MIT.

A testing reference for thurbox, a project with a Lua interface and a Rust kernel, describing its test commands, test areas, and end-to-end test setups.

In plain words
What is it for?
Use it when writing, running, debugging, or extending thurbox tests, including Rust tests, shell-script tests, terminal tests, and session-backend end-to-end tests.
Why use it?
It explains which tests protect the kernel, user interface, installation scripts, extensions, and real terminal behaviour, reducing the chance of using the wrong test method.

Skill for Claude CodeCodex

Written for no agent in particular: nothing here depends on one. Also seen: mentions Claude Code; installed under .agents/ (shared by several agents); mentions AGENTS.md.

This is Thurbeen/thurbox's own configuration. It tells Claude Code and Codex how to work on thurbox itself, so it is not a mod to install elsewhere. Copy it as a starting point and replace the rules that are about this project. Everything thurbox configures →

Reuse

Borrowing it

Nothing to install: this file belongs to Thurbeen/thurbox. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.

Copy the file
curl -O https://raw.githubusercontent.com/Thurbeen/thurbox/main/.agents/skills/thurbox-testing/SKILL.md
Clone the repo
git clone --depth 1 https://github.com/Thurbeen/thurbox

Made for: Claude Code, Codex.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for thurbox-testing

README.md
[![agentmods](https://agentmods.dev/badge/skills/thurbeen/thurbox/thurbox-testing/github.svg)](https://agentmods.dev/skills/thurbeen/thurbox/thurbox-testing)
Your own site
<a href="https://agentmods.dev/skills/thurbeen/thurbox/thurbox-testing"><img src="https://agentmods.dev/badge/skills/thurbeen/thurbox/thurbox-testing/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for thurbox-testing

Your own site · 80×15
<a href="https://agentmods.dev/skills/thurbeen/thurbox/thurbox-testing"><img src="https://agentmods.dev/badge/skills/thurbeen/thurbox/thurbox-testing.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 0 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 6,107 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe. Third-party audits
  • NVIDIA SkillSpector pass 7 Sept 2026
How audits are shown
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00000 $0.06107
Opus 5.5 $0.00000 $0.02443
Sonnet 5.5 $0.00000 $0.01221
Haiku 4.5 $0.00000 $0.00611

Measured 5d ago against content hash baaa8e4a2c1a, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

Grade A, and why

thurbox-testing scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 5d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

.agents/skills/thurbox-testing/SKILL.md · 360 lines

How it starts

The opening of the file, as written. The whole thing — 360 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Testing thurbox

Working reference indexed by AGENTS.md. The rationale behind these decisions is owned by the docs under docs/; a change that invalidates what this says updates it in the same PR.

Testing

cargo nextest run --all              # Run all tests (preferred runner)
cargo nextest run -E 'test(name)'    # Run a single test by name
cargo nextest run --all --profile ci # Run with CI profile
bats scripts/install.bats             # Test install script (requires bats-core)
bats extensions/*/scripts/*.bats      # Test the extensions' shell scripts
just test-scripts                     # Both of the above, the way CI runs them

The Nix development shell includes bashInteractive, not merely stdenv's non-interactive Bash. Real-tmux fixtures exercise Readline's bracketed-paste mode, including its bind setting, so substituting the stdenv shell changes the terminal contract those tests are meant to drive.

tests/doc_references.rs keeps the tracked documents honest about each other: every relative Markdown link, every docs/<NAME>.md and .agents/skills/<name> path and every github.com/Thurbeen/thurbox/blob/main/… link names a file that exists, and the names in its RETIRED table appear nowhere. Rename a document or delete a symbol that docs cite, and that test lists every stale citation. Add a name to RETIRED once nothing in the tree mentions it any more.

Kernel and interface tests

The interface is Lua on a Rust kernel, so most coverage drives the real kernel over the real ui/ rather than a harness that imitates either:

  • tests/kernel_mvp.rs — the kernel's contract: the four node kinds and their count, the plugin environment enumerated global-by-global (no blanket exemption for a leading underscore — that is how a capability once hid under __run_impl), the instruction/memory bounds, snapshot reads, and painting a plugin to a TestBackend.
  • The per-surface files — one file per surface or contract: session_list, search, new_session, terminal_pane, session_lifetime, keymap, focus, modals, chrome, mouse, hover, decoration, plugin_{authoring,commands,lifecycle,settings,switching}, repo_memory, remote_status, session_status, core_settings, attach_by_name. Several build an interface in a tempdir from the embedded copy, so delivery and loading are exercised together. plugin_switching also runs the registry persistence path in an isolated child process under a Unix file-size limit: the forced mid-write failure must preserve every byte of the prior ui.json and leave no staged file behind. The native interruption probe is Unix-only; Windows replacement is compile-checked and uses MoveFileExW, but is not exercised by that probe. The same file pins config-file symlink preservation on Unix and paths beyond MAX_PATH on Windows.
  • tests/edited_interface.rs — an edited interface keeps working across an upgrade. It holds files frozen from old releases with a user's edit (tests/fixtures/edited_interface/<release>/: v2.22.4's layout, session list and agent pane, v2.32.0's layout and agent pane), and checks that they are preserved, arrange, render and pass plugin check against the current lib/ and kernel. It also pins every name lib/ exports (lib_surface.txt). This is the check behind lib/'s compatibility promise in ui/AGENTS.md. Never refresh the frozen files to follow ui/. A new lib/ export is appended to the pin; a removed one means adding a shim back.
  • tests/kernel_limits.rs — instruction and memory ceilings, in their own file because they mutate process-wide limits.
  • Lua statics — selene ui (undefined names + the sandbox, via thurbox.yml), lua-language-server --check (types + withheld libraries, via ui/lib/thurbox.d.lua), stylua (format). The three cover different halves; see Linting & Formatting.
  • scripts/ci/check-lua-types.sh — the definitions' own test. Three panes in tests/fixtures/lua_types/ each misspell one thing the plugin API otherwise drops in silence (a node prop, a command option, a theme role) and each must still be reported. --check ui proves the panes are clean; this proves the types have teeth. Runs in the Lua Lint job and in just lint.
  • scripts/ci/check-lua-std.sh — the same trick for thurbox.yml. tests/fixtures/lua_std/reads.lua, generated from src/kernel/lua_api.rs with the thurbox.* entries it lints against, reads every declared path and must lint clean, and typos/ holds one pane per table misspelling one field, each of which must not. It asserts on selene's incorrect_standard_library_use code from its Json2 output and attributes a finding by the file it came from, so no assertion depends on message wording. A checked path stops at the first […], so a list has nothing below it to probe, and runs is the one map whose keys are the plugin's own literals rather than a session id. Those tables were declared without their fields for as long as nothing read them (issue #1133). Same two runners.
  • tests/lua_api.rs — the plugin API against kernel::lua_api (issue #1476): the generated declaration files equal what it renders (THURBOX_REGENERATE=1, i.e. just lua-api, rewrites them), a pane walking every key of a fully populated publish finds none undeclared, and thurbox.api/requires_api hold; its meta module drives ui.* session meta from the real thurbox-cli to the bundled session list.
  • tests/frames.rs — the bundled panes' frames pinned cell for cell, as literals in the file (no snapshot tool): the session list grouped, nested, windowed, narrow and under double-width names; the selection as a style; the agent pane empty, detached, failed, and with a real vt100 screen behind its surface. A failing test prints the new frame as a literal to paste. Every input is pinned (the default preset by name, a fixed elapsed, a fixed snapshot) — keep it that way; a frame that moves on its own is worse than none.
  • tests/render_props.rs — proptest crash invariants: every bundled pane renders and paints at any size down to one cell, the arrangement places its slots inside the screen and apart, no key sequence makes a pane throw (the creation flow included), and selection extraction survives arbitrary buffers and arbitrary vt100 byte streams.
  • tests/tui_e2e.rs (unix) — the real binary on a real pty, via libc's openpty (no PTY crate), fully isolated (private HOME/config/data, a short private TMUX_TMPDIR, inherited INPUTRC scrubbed, network and heartbeat features off). It asserts what no TestBackend test can: the boot frame, the kernel overlays opening and closing, the search strip taking focus, a column toggle reflowing with no screen clear, a resize storm down to 1×1, a broken pane reported through the Interface tab, exit restoring the terminal (alternate screen, mouse, bracketed paste, cursor) — and, where tmux exists, a headlessly created session attached, painted and typed into (sh as the agent), the classic Shell tab raised, lowered and still holding its shell (and replaced by a working one after it exited behind the agent, or its window went while thurbox was closed), and a v2.32.0 layout-preset profile (fixture in tests/fixtures/v2_32_0_split_shell/) upgrading back to classic. Also delayed remote shell creation and re-adoption keeping F1 responsive, and just smoke. It replaced the bash tmux smoke script, which could not see the byte stream and duplicated this harness. Keyboard negotiation covers responsive legacy, kitty and silent terminals; docs/DEVELOPMENT.md records the reply invariant and execution measurements. Two scenarios there cover a remote session whose link has gone bad, which needs a stand-in that a local tmux cannot supply on its own: tmux -C attach-session hands its stdin and stdout file descriptors to the tmux server and then only shepherds, so stopping the client changes nothing, while a real ssh is a byte relay whose stopping wedges the link. The ssh stand-in therefore runs the control connection through a pair of cat pumps over fifos — the pids the test SIGSTOPs — and execs straight through for every other call, whose exit status is load-bearing (has-session answering "no" is how ensure_ready decides to create a session). Both scenarios assert only on a kernel-owned overlay, never on the session list: the list returns on a snapshot tick, seconds even on a healthy link, so it cannot tell a frozen interface from a patient one. See ADR-P24.
  • tests/self_update_scratch.rs (unix) — the real update CLI with private config/data/home and bounded fake downloaders, terminated in its own process group mid-download. The leader stays unreaped until group teardown so the harness cannot signal a reused pid. Pins recovery on the next update while preserving an aged live owner's staging; no network or installed binary is touched. A subprocess probe also pins that the system temp fallback never reserves or sweeps unrelated paths. agent::self_update::tests covers the same staging lifecycle in child processes on Unix and native Windows, including normal exit, recent work, legacy names, malformed ownership, and symlinks / Windows junctions.
  • tests/reap_e2e.rs — window-teardown ownership against a real tmux on a throwaway socket (skipped when tmux is absent), because the bug it pins only exists in how tmux resolves a target. 15 tests. Seven pin the reap itself: a stale row's reap spares a live namesake's window (stamped, and unstamped as every psmux window is), a namesake's pane the stale row still remembers, a live window whose name only collides after sanitize_window_name ('fleet 1' and 'fleet_1' share one tb-fleet_1), and a soft-deleted namesake still inside its undo window — while a row whose own pane resolves, and one whose pane id resolves to nothing but whose stamp nobody else answers to, still lose their window. Sparing must not be bought by making the reap a no-op. Force delete, stop and restart share the reap's ownership gate (ADR-25, backend::identity::WindowIndex) rather than each resolving tb-<name> on their own, so one test walks all three against their own live namesake, plus one asserting force delete still kills the row's own window. Two more cover the stamp itself: a row with no pane id at all (the psmux shape) still resolves its own window, and a restore whose name a live session now answers to is refused outright (issue #1192) rather than joining it on the backend — respawn's own ownership gate is walked by restart in the three-path test above. The last three cover the companion shell and the no-server guarantee (ADR-24/25's remote teardown): force delete and reap both collect the companion shell alongside the agent's window, a teardown spares a live namesake's companion shell, and a teardown never brings a tmux server into being (the ensure_ready side effect this path must not trigger). The owed-teardown sweep (retry_owed_remote_teardowns) is unit-tested against host_cli::fake in session_ops::delete — that a failed remote teardown is written onto the row, that a soft-deleted row is never on its worklist (the undo window), and that a silent host is asked once per pass — and proven end to end on a real process by linux-container.sh's remote_teardown_probe. The same file covers a delegated delete whose host never answers at all: it falls back to the local teardown and owes a retry, while any other host error still aborts. restart --if-missing refusing to relaunch against an unreachable host (rather than reading it as "no window" and starting a second agent) is proven end to end by linux-container.sh's restart_if_missing_probe.
  • tests/concurrent_respawn.rs — six sessions relaunching onto a tmux server that does not exist yet, against a real tmux on a throwaway socket (skipped when tmux is absent): every worker's ensure_session_configured sees "no session" and races new-session, and the regression this pins is that a loser must not abort its whole respawn over tmux's duplicate session — it has to notice the winner's session and continue.
  • tests/spawn_command_resolution.rs (unix) — a local spawn against a real tmux on a throwaway socket (skipped when tmux is absent): starts a server whose own PATH lacks the agent, then spawns it through TmuxBackend's control-mode path with the agent only on thurbox's PATH. Pins the fix in resolve_local_program (docs/CONFIG.md → How command is resolved): a local window command used to be left for the multiplexer to resolve, which sees the server's PATH (an attached client's is not copied in), not the one thurbox itself was launched with.
  • tests/spawn_with_failing_tmux_hook.rs (unix) — its own binary and its own socket because it installs a server-global hook, which any suite sharing the socket would then spawn into. Against a real tmux (skipped when tmux is absent): a dead after-new-window hook, the shape an uninstalled tmux plugin leaves behind. Pins that the one-shot new-window path believes the pane id on stdout rather than the exit status — tmux hands the client the status of the last run-shell its command list triggered, hooks included, so a window that was created came back as exit status: 127 and was torn down (#1154). The second test pins the quieter half: the id kept must still resolve to that window and carry its session stamp.
  • tests/path_resolution_absolute.rs (unix) — its own test binary because it moves the process working directory, which a sibling test in the same binary would see. Pins that resolve_on_path (docs/CONFIG.md → How command is resolved) skips an empty PATH component rather than joining it as "the current directory": that join used to answer with a bare relative name, reintroducing the multiplexer-resolves-it dependence the function exists to remove.
  • tests/session_state_agreement.rs — one row, four independent readers (session get, session list, watch --initial via the real binary, and SnapshotStore in-process): all four must answer the same SessionState. Pins the concrete regression the session::hook_status consolidation fixed — seen_at is a stored fact only the snapshot used to read, so a turn the interface already showed as idle kept answering done on every headless surface for the rest of the session's life.

Read the full file on GitHub · 360 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 5d ago Changed · +22 lines baaa8e4a2c1a
  2. 7d ago Changed · +1 lines d9094d46468d
  3. 9d ago Changed · +10 lines 881eea5899e6
  4. 11d ago Changed · +2 lines 9efce37be5a0
  5. 15d ago Changed · +1 lines 0af23b807218
  6. 17d ago Changed · +15 lines e96165741f45
  7. 19d ago Changed · +6 lines 959abf1eadad
  8. 20d ago Changed · +9 lines fe72e33c8f60
  9. 1mo ago Changed · +8 lines 0e02559a155c
  10. 1mo ago First seen · 286 lines · 0 tokens per session scan A eff22a0240c6

Subscribe to this mod's changes

thurbox-testing is a skill published in the GitHub repository Thurbeen/thurbox (115 stars, last pushed today), licensed MIT. It costs nothing until one of its globs matches a file; then it loads 6,107 tokens. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.

Related

Other skills, from other repositories

research-engineer

An uncompromising Academic Research Engineer. Operates with absolute scientific rigor, objective criticism, and zero flair. Focuses on theoretical correctness, formal verification, and optimal implementation across any required technology.

davila7/claude-code-templates · 43 tokens

tika-eval-compare

Compare extracts from two Tika builds over a corpus to detect regressions in content, encoding, exceptions, and embedded-document handling. Use for "compare before/after extracts", "eval this change against the corpus".

apache/tika · 50 tokens

cua-driver

Use Cua Driver for desktop or browser tasks that are awkward or unavailable through Bash/APIs, or when the user explicitly wants GUI interaction: app testing, visual bug reproduction, form filling, calendar entry, screenshots, and demo recording. Also covers Cua setup; not OpenAI Codex Computer Use or web research.

davidondrej/skills · 68 tokens

jetson-validate-image

Use after jetson-flash-image to run static BSP checks, on-target smoke/regression tests on a flashed DUT, or both. Not for build or flash steps. Triggers: validate bsp, on-target validation.

NVIDIA/skills · 50 tokens

atmos-validation

Validate Atmos projects, components, arbitrary JSON Schema inputs, EditorConfig, and GitHub Actions; use affected-file selection and native CI annotations.

cloudposse/atmos · 31 tokens

skill-benchmark

Benchmark AI skill effectiveness by measuring implementation quality against legacy constraints.

HoangNguyen0403/agent-skills-standard · 16 tokens