Index of every page on this site: llms.txt
All skills
Run it yourself

Build, debug, test, or package Python Textual terminal interfaces: screens, widgets, TCSS, reactive state, workers, keyboard workflows, and optional browser delivery. Use when Textual is selected or an existing Textual app is involved; do not turn a noninteractive CLI or simple Rich output into a TUI unnecessarily.

Use this Skill: https://skilld.dev/gh/tristanmanchester/agent-skills/textual-tui

Nothing lands on disk. Nothing to clean up.

Fork this Skill

Edit a local copy. It keeps the author and licence.

referencesreactivity-and-workers.md

≈971 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Reactivity, concurrency, and result ownership

State

Use reactive when changes should participate in UI refresh/layout as configured. Use var for reactive behaviour without automatic refresh/layout; it still has watchers and other reactive features. A plain attribute is appropriate when none of that machinery is needed. Keep compute_* pure and cheap. Watchers can schedule work or update UI but should not block. set_reactive supports deliberate initial values without triggering premature watchers; inspect mounted-widget availability.

Choose the execution mechanism

An async worker is concurrent with message handling, not a new CPU thread. Await nonblocking I/O inside it; do not call requests.get, time.sleep, heavy parsing, or blocking subprocess APIs there and expect responsiveness. Use thread=True for a blocking I/O API; choose a process/native computation strategy when CPU/GIL cost requires it. Bound input sizes, subprocess lifetime, and remote request timeouts.

@work wraps a method and returns a Worker when called. Do not await the decorated method as though it were the original coroutine. Waiting for worker.wait inside a message handler can still hold up that handler's message processing; use completion messages/events when appropriate.

Cancellation and latest-result wins

Exclusive workers cancel earlier work in the applicable group; choose groups so unrelated operations do not cancel one another. Coroutine cancellation needs cooperative cleanup and must not be swallowed as a normal success. Thread workers cannot be forcibly cancelled like a coroutine: check get_current_worker().is_cancelled and use the underlying operation's own timeout/cancellation support.

For robust result ownership, increment a revision on each new search/selection, pass it with the request, and check that same revision on the UI thread immediately before applying success or error. A thread's earlier cancellation check alone has a race with a new request. Marshal updates through post_message or call_from_thread; do not mutate widgets/reactive values directly from the worker thread. Ignore results for a removed screen or obsolete selection.

Do not use latest-request-wins for payments, saves, or deletes as though cancellation undoes the operation. Persist an operation identity, gate duplicate submissions, and reconcile unknown outcomes. A cancelled wait does not prove remote cancellation.

Errors and lifecycle

Worker errors exit the app by default; use exit_on_error=False deliberately for recoverable failures and handle Worker.StateChanged/error outcomes visibly. Do not silently swallow exceptions into empty results. Keep PENDING/RUNNING/SUCCESS/ERROR/ CANCELLED distinct, including progress and retry affordances.

Workers are associated with their originating DOM node. Removal/app exit cancels managed workers, but external threads/processes/network writes still need their own lifetime controls. Close streams, subprocesses, temporary files, and clients in cleanup. Stop observers/timers on teardown; do not keep updating removed widgets.

Streaming views and tests

Batch appropriate UI changes; preserve user navigation and scrollback. Anchor only when the user is following the tail. Bound retained logs/transcript rows and use backpressure or sampling rather than indefinitely mounting widgets per token. Render untrusted text without enabling unintended markup, links, or terminal escapes.

Test out-of-order results, cancellation before/after completion, failure after a new selection, screen removal, repeated input, timeout, and teardown. Use controlled fake services and observable state with a deadline; fixed sleeps and snapshot-only checks miss these races.

Reviewed sources:

Source: SKILL.md on GitHub

skilld matched fixed text patterns in SKILL.md and file names. Patterns miss obfuscated code.

skilld run checks every file with the same patterns. It asks for approval before it loads a Skill with a behavior marked Needs approval.

1 warning1mo4 checks · Risk SAFE
  • Gen Agent Trust Hub1mo

    The skill provides developer tools for Textual TUI development, including scaffolding and auditing. It uses dynamic Python code loading to analyze local projects, which presents a localized execution risk for the agent's environment.

  • Socket1mo

    1 alert: gptAnomaly

  • Snyk1mo

    Risk: LOW · No issues

  • ZeroLeaks6mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 3323bc9. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 weeks ago.

Steadyupdated last month
metadata
{
  "version": "3.0.0",
  "reviewed": "2026-09-13"
}
Other metadata
compatibility
Textual currently supports Python >=3.9,<4. Use the project's locked Textual and developer-tool versions. Bundled scaffold checks parse source without importing the generated application; runtime tests need Textual and the app's dependencies.

README badge

README badge for tristanmanchester/agent-skills/textual-tui