Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add skills/openscribbler/syllago/tui-buildernpx skills add OpenScribbler/syllago --skill tui-buildergit clone --depth 1 https://github.com/OpenScribbler/syllagoWrote 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.
[](https://agentmods.dev/skills/openscribbler/syllago/tui-builder)<a href="https://agentmods.dev/skills/openscribbler/syllago/tui-builder"><img src="https://agentmods.dev/badge/skills/openscribbler/syllago/tui-builder.svg" alt="Measured on agentmods" height="20"></a>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.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00045 | $0.01331 |
| Opus 5 | $0.00023 | $0.00665 |
| Sonnet 5 | $0.00009 | $0.00266 |
| Haiku 4.5 | $0.00005 | $0.00133 |
Grade A, and why
tui-builder 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 6d 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.
How it starts
The opening of the file, as written. The whole thing — 59 lines — stays where its author put it; the contents beside it link to each section on GitHub.
TUI Builder — Golden Rules + Quick Reference
Context gate: On first invocation in a session, run:
touch /tmp/syllago-tui-builder-${PPID}This signals the tui-context-gate hook that the skill was loaded.
Golden Rules Checklist
Before any layout or component work, verify:
- Mouse + keyboard parity on EVERY interactive element —
zone.Mark()in View,zone.Get().InBounds()in updateMouse. No exceptions. If it responds to a keypress, it must respond to a click. - Subtract 2 from height for borders, 2 from width for borders
- Never rely on auto-wrap — truncate explicitly (
maxTextWidth = panelWidth - 4) - Use
MaxWidth()notWidth()— Width word-wraps - Use
borderedPanel()for all bordered panels - Parent owns child sizes — call
SetSize(), never let children calculate - All async work via
tea.Cmd— never goroutines - All state changes returned from
Update()— never mutate elsewhere - Always propagate
Update()to active sub-models - Handle
tea.WindowSizeMsg— store and recalculate
Component Message Contracts
| Component | Receives | Sends |
|---|---|---|
| topbar | tea.WindowSizeMsg, tea.KeyMsg, tea.MouseMsg |
tabChangedMsg, actionPressedMsg, helpToggleMsg |
| items | tea.WindowSizeMsg, tea.KeyMsg |
itemSelectedMsg |
| explorer | tea.WindowSizeMsg, tea.KeyMsg, content items |
explorerDrillMsg, explorerCloseMsg |
| gallery | tea.WindowSizeMsg, tea.KeyMsg, tea.MouseMsg |
cardSelectedMsg, cardDrillMsg |
| modal | tea.KeyMsg, tea.MouseMsg |
editSavedMsg, editCancelledMsg |
| install | tea.KeyMsg, tea.MouseMsg, step data |
installResultMsg, installDoneMsg, installCloseMsg |
| toast | tea.KeyMsg, toastTickMsg |
(dismisses via Dismiss() cmd) |
Gotchas
- AdaptiveColor mutates renderer state. Fix: warmup render in
TestMain(). - bubbletea v1 uses
tea.KeyMsg, nottea.KeyPressMsg(v2 API). Check version before using spec code. - Golden files with raw ANSI are fragile. Strip ANSI before storing.
lipgloss.Width()is ANSI-aware,len()is not. Always uselipgloss.Width()for rendered strings.- Children that never receive WindowSizeMsg render at zero size.
- goimports strips "unused" imports between edits. Add import and usage in a single Edit call.
- Cursor initialization with Reset(): When
active = -1,Open()must default cursor to 0, not -1. - lipgloss Width() wraps, MaxWidth() truncates. For bordered panels, always use both Width+MaxWidth and Height+MaxHeight. Without MaxHeight, content overflow pushes the header offscreen.
- Manual string splitting destroys zone markers. Never split rendered strings containing zone.Mark() on newlines or truncate by rune — the invisible zero-width markers get broken. Use lipgloss styling for dimension control instead.
- Sort indicators overflow short columns. "Files ▲" is 7 visual chars but the Files column is 5. Use
headerCell()which truncates the label to make room for the indicator within the column width. - App-level keys intercept search input. When the library search input is active, keys like 'a' (add), 'q' (quit), '1' (group switch) must be passed through to the search handler instead of triggering app shortcuts. Check
table.searchingbefore handling global letter keys. - Help bar separator is middle dot (·) not asterisk (*). Cleaner look.
- Metadata bar steals table height. When adding a fixed-height panel below a variable-height component (like table + metadata bar), always reduce the variable component's height in both
SetSize()ANDView(). If only one is updated, the table renders at the wrong height on resize vs initial draw. - Modal
lipgloss.Place()centering. Uselipgloss.Place(width, height, lipgloss.Center, lipgloss.Center, rendered)for modal centering — not manual padding math. Handles terminal resize automatically. - YAML folded scalars add trailing newlines. Descriptions from
loadout.yamlusing>have\nat the end. Always sanitize catalog text fields before rendering in the TUI. - Unified frame requires manual border construction.
borderedPanel()can't create shared borders between sections. Build frames manually:╭/╰for corners,├──┤for internal separators,├──┬──┤/╰──┴──╯for split pane junctions. - Metadata panel height is constant (metaBarLines=3 + 1 separator). Type-specific line 3 is blank for simple types, not omitted. This prevents the frame from shifting when scrolling between hooks and skills.
- Explorer needs providers for metadata. Pass providers + repoRoot to
newExplorerModel()so it can compute installed status viacomputeMetaPanelData(). - Keyboard-only components are bugs. If a View renders interactive elements without
zone.Mark(), mouse users can't interact with them. Every radio option, checkbox row, list item, button, and text input needs a zone mark in View and a correspondingzone.Get().InBounds()check in updateMouse. ThecheckboxListcomponent automates this viazonePrefix— set it and callHandleClick()in the parent's mouse handler.
What ships with it
2 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
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.
- 6d ago First seen · 59 lines · 45 tokens per session scan A fdaa6b24732e
tui-builder is a skill published in the GitHub repository OpenScribbler/syllago (15 stars, last pushed 3d ago), licensed Apache-2.0. It adds 45 tokens to every session and 1,331 once invoked, about $0.0002 per session on Opus 5. 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.
Other skills, from other repositories
go-safe-move-refactor
Safely move Go source files between packages with zero compilation downtime. Handles package declarations, import updates, symbol exports, type renames, test migration, and forwarding stubs. Validates compilation after every atomic step.
go-source-documentation
Add idiomatic, godoc-compliant documentation to Go source and test files. Use when user asks to document Go files, add doc comments, improve Go documentation, or mentions /document-go. Covers file headers, package comments, types, functions, interfaces, constants, variables, tests (with detailed explanations)…
increase-test-coverage
Increase Go test coverage to 90%+ using a Research → Plan → Implement pipeline. Analyzes coverage gaps, generates table-driven tests with httptest mocks, and validates results with go test -coverprofile. Designed for Go MCP server projects using the official go-sdk and gitlab.com/gitlab-org/api/client-go/v2.
modularize-go-package
Modularize a monolithic Go package into domain-specific sub-packages. Extracts shared utilities, moves domain files, updates imports, renames types, creates registration functions, and validates compilation+tests at every step. Designed for large-scale refactoring of 50-100+ file packages.
create-mcp-tool
Create a new MCP tool end-to-end: sub-package, input/output structs, handler, ActionSpec metadata, markdown formatter, tests, catalog projection, and documentation. Use when adding a new GitLab API endpoint as an MCP tool.
generate-project-documentation
Generate comprehensive project documentation including architecture overview, package/component docs, MCP tools/resources/prompts reference, developer onboarding guide, and configuration/deployment guide. Uses Diátaxis framework and Mermaid diagrams.