full-stack-skills/t2ui-skills

tui-front-ui

Define strict, example-rich rules for generating pixel-precise ASCII Text UI (TUI) with layout attributes (top/left/width/height/colors/typography) and Pencil MCP–ready specs + batch_design operation plans.

First seen Jun 23, 2026

Installation

$ npx skills add full-stack-skills/t2ui-skills --skill tui-front-ui

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from full-stack-skills/t2ui-skills · top by installs.

npx skills add full-stack-skills/t2ui-skills

Browse all from full-stack-skills/t2ui-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License LICENSE
Default branch main
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 15,590 B
  • docs SUMMARY.md 228 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 16 installs

SKILL.md

Purpose

Produce TUI designs that are accurate enough to be treated like product design artifacts:

  • Render a copy-pastable ASCII TUI.
  • Output a complete layout/spec block with geometry and style tokens.
  • Output a Pencil MCP–ready plan: JSON spec + batch_design operations (chunked to ≤25 ops).

Output Contract (Mandatory)

For any request, output these blocks in this order:

OUTPUT: TUI_RENDER

...monospace-only text...

OUTPUT: COMPONENT_SPEC

{
  "id": "cmp_x",
  "name": "ComponentName",
  "type": "tui-component",
  "bbox": { "topPx": 0, "leftPx": 0, "widthPx": 0, "heightPx": 0 },
  "zIndex": 0,
  "layout": { "paddingPx": 0, "gapPx": 0, "align": "left", "valign": "top" },
  "style": {
    "fillColor": "#ffffff",
    "textColor": "#111111",
    "strokeColor": "#dddddd",
    "strokeThickness": 1,
    "cornerRadius": 8,
    "opacity": 1
  },
  "typography": { "fontFamily": "Inter", "fontSize": 14, "fontWeight": 400, "lineHeight": 20 },
  "overflow": { "mode": "truncate", "ellipsis": "…", "maxLines": 1 },
  "state": { "focused": false, "disabled": false, "loading": false, "error": null },
  "hotkeys": []
}

OUTPUT: PENCIL_SPEC

{
  "canvas": { "widthPx": 390, "heightPx": 844, "backgroundColor": "#ffffff" },
  "grid": { "cellWidthPx": 8, "cellHeightPx": 16 },
  "nodes": [],
  "components": []
}

OUTPUT: PENCILBATCHDESIGN

CALL 1:
root=G()
screen=I(root,{type:"frame",name:"Screen"})
U(screen,{width:390,height:844,x:0,y:0})

CALL 2:
...up to 25 ops...

Rendering Rules (Strict)

1) Character grid and pixel mapping

  • Use a grid (rows/cols) for the ASCII layout.
  • Default mapping:

- grid.cellWidthPx = 8 - grid.cellHeightPx = 16

  • Convert:

- leftPx = col cellWidthPx - topPx = row cellHeightPx - widthPx = cols cellWidthPx - heightPx = rows cellHeightPx

2) Width / truncation / wrapping

  • Never output TAB characters.
  • Hard max line length: pageWidthCols.
  • Overflow policies:

- truncate: cut and append … - wrap: break lines and keep indentation - clip: cut without … (avoid unless required)

3) Frames, borders, and box-drawing

  • Preferred frame set:

- Corners: ┌ ┐ └ ┘ - Lines: ─ │ - Intersections: ├ ┤ ┬ ┴ ┼

  • Default component chrome:

- Header row: [Title] + state tags (e.g., Disabled, Loading) - Body region: content - Footer row (optional): Keys: ...

4) Color output policy

  • Default: do not emit ANSI colors unless explicitly requested by the user.
  • If coloring is requested:

- Emit ANSI TrueColor sequences. - Provide a noColor switch and honor NO_COLOR=1 as a hard disable.

  • In COMPONENTSPEC and PENCILSPEC, always represent colors as hex.

5) Interaction hints

  • Hotkeys must be minimal and consistent.
  • Use this canonical set when applicable:

- Navigation: <up>/<down>/<left>/<right> - Confirm: <enter> - Back: <esc> - Focus: <tab>

Pencil MCP Execution Playbook (Always include)

  1. Call geteditorstate(include_schema=false) to find the active .pen file and selection.
  2. If there is no active document: open_document("new").
  3. Use batchdesign(filePath, operations) to apply PENCILBATCH_DESIGN.

- Keep each call ≤ 25 operations. - Never reuse binding names across different calls.

  1. Validate layout: snapshot_layout(filePath, maxDepth=2, problemsOnly=true).
  2. Visual check: get_screenshot(filePath, nodeId) for the page frame.

Important: the exact positioning property names may differ by schema (e.g. x/y vs left/top). If unknown, retrieve guidelines first (e.g., get_guidelines(topic="design-system")) and adapt the update keys in U(...) accordingly.

Example 1 — Single card with title and body

OUTPUT: TUI_RENDER

┌──────────────────────────────────────────────────────────────┐
│ [Card]                                                      │
├──────────────────────────────────────────────────────────────┤
│ Title: Account Overview                                     │
│ Balance: $2,340.18                                          │
│ Status: Active                                              │
└──────────────────────────────────────────────────────────────┘

OUTPUT: COMPONENT_SPEC

{
  "id": "cmp_card_1",
  "name": "Card",
  "type": "tui-card",
  "bbox": { "topPx": 48, "leftPx": 24, "widthPx": 342, "heightPx": 160 },
  "zIndex": 1,
  "layout": { "paddingPx": 16, "gapPx": 8, "align": "left", "valign": "top" },
  "style": {
    "fillColor": "#ffffff",
    "textColor": "#111111",
    "strokeColor": "#e5e7eb",
    "strokeThickness": 1,
    "cornerRadius": 12,
    "opacity": 1
  },
  "typography": { "fontFamily": "Inter", "fontSize": 14, "fontWeight": 400, "lineHeight": 20 },
  "overflow": { "mode": "wrap", "ellipsis": "…", "maxLines": 4 },
  "state": { "focused": false, "disabled": false, "loading": false, "error": null },
  "hotkeys": []
}

OUTPUT: PENCIL_SPEC

{
  "canvas": { "widthPx": 390, "heightPx": 844, "backgroundColor": "#ffffff" },
  "grid": { "cellWidthPx": 8, "cellHeightPx": 16 },
  "nodes": [
    {
      "id": "node_screen",
      "type": "frame",
      "name": "Screen",
      "topPx": 0,
      "leftPx": 0,
      "widthPx": 390,
      "heightPx": 844,
      "style": { "fillColor": "#ffffff" },
      "children": ["node_card_bg", "node_card_title", "node_card_body"]
    },
    {
      "id": "node_card_bg",
      "type": "rect",
      "name": "Card/Background",
      "topPx": 48,
      "leftPx": 24,
      "widthPx": 342,
      "heightPx": 160,
      "style": { "fillColor": "#ffffff", "strokeColor": "#e5e7eb", "strokeThickness": 1, "cornerRadius": 12 }
    },
    {
      "id": "node_card_title",
      "type": "text",
      "name": "Card/Title",
      "topPx": 64,
      "leftPx": 40,
      "widthPx": 310,
      "heightPx": 24,
      "text": "Account Overview",
      "style": { "textColor": "#111111" },
      "typography": { "fontFamily": "Inter", "fontSize": 16, "fontWeight": 600, "lineHeight": 24 }
    },
    {
      "id": "node_card_body",
      "type": "text",
      "name": "Card/Body",
      "topPx": 96,
      "leftPx": 40,
      "widthPx": 310,
      "heightPx": 96,
      "text": "Balance: $2,340.18\nStatus: Active",
      "style": { "textColor": "#111111" },
      "typography": { "fontFamily": "Inter", "fontSize": 14, "fontWeight": 400, "lineHeight": 20 }
    }
  ],
  "components": [
    {
      "id": "cmp_card_1",
      "name": "Card",
      "bbox": { "topPx": 48, "leftPx": 24, "widthPx": 342, "heightPx": 160 },
      "zIndex": 1
    }
  ]
}

OUTPUT: PENCILBATCHDESIGN

CALL 1:
root=G()
screen=I(root,{type:"frame",name:"Screen"})
U(screen,{width:390,height:844,x:0,y:0})

CALL 2:
cardBg=I(screen,{type:"rect",name:"Card/Background"})
U(cardBg,{x:24,y:48,width:342,height:160,fillColor:"#ffffff",strokeColor:"#e5e7eb",strokeThickness:1,cornerRadius:12})
cardTitle=I(screen,{type:"text",name:"Card/Title",content:"Account Overview"})
U(cardTitle,{x:40,y:64,width:310,height:24,textColor:"#111111",fontFamily:"Inter",fontSize:16,fontWeight:600})
cardBody=I(screen,{type:"text",name:"Card/Body",content:"Balance: $2,340.18\\nStatus: Active"})
U(cardBody,{x:40,y:96,width:310,height:96,textColor:"#111111",fontFamily:"Inter",fontSize:14,fontWeight:400})

Example 2 — Input field with validation error

OUTPUT: TUI_RENDER

┌──────────────────────────────────────────────────────────────┐
│ [Input]                                                     │
├──────────────────────────────────────────────────────────────┤
│ Email                                                      ! │
│ [ [email protected]______________________________ ]           │
│ Error: Please enter a valid email                            │
└──────────────────────────────────────────────────────────────┘

OUTPUT: COMPONENT_SPEC

{
  "id": "cmp_input_email",
  "name": "Input",
  "type": "tui-input",
  "bbox": { "topPx": 240, "leftPx": 24, "widthPx": 342, "heightPx": 132 },
  "zIndex": 2,
  "layout": { "paddingPx": 16, "gapPx": 8, "align": "left", "valign": "top" },
  "style": {
    "fillColor": "#ffffff",
    "textColor": "#111111",
    "strokeColor": "#ef4444",
    "strokeThickness": 1,
    "cornerRadius": 12,
    "opacity": 1
  },
  "typography": { "fontFamily": "Inter", "fontSize": 14, "fontWeight": 400, "lineHeight": 20 },
  "overflow": { "mode": "truncate", "ellipsis": "…", "maxLines": 1 },
  "state": { "focused": true, "disabled": false, "loading": false, "error": "Please enter a valid email" },
  "hotkeys": ["<tab>", "<enter>", "<esc>"]
}

OUTPUT: PENCIL_SPEC

{
  "canvas": { "widthPx": 390, "heightPx": 844, "backgroundColor": "#ffffff" },
  "grid": { "cellWidthPx": 8, "cellHeightPx": 16 },
  "nodes": [],
  "components": [
    {
      "id": "cmp_input_email",
      "name": "Input",
      "bbox": { "topPx": 240, "leftPx": 24, "widthPx": 342, "heightPx": 132 },
      "zIndex": 2
    }
  ]
}

OUTPUT: PENCILBATCHDESIGN

CALL 1:
root=G()
screen=I(root,{type:"frame",name:"Screen"})
U(screen,{width:390,height:844,x:0,y:0})

CALL 2:
field=I(screen,{type:"rect",name:"Input/Field"})
U(field,{x:24,y:240,width:342,height:132,fillColor:"#ffffff",strokeColor:"#ef4444",strokeThickness:1,cornerRadius:12})
label=I(screen,{type:"text",name:"Input/Label",content:"Email"})
U(label,{x:40,y:256,width:310,height:20,textColor:"#111111",fontFamily:"Inter",fontSize:14,fontWeight:600})
value=I(screen,{type:"text",name:"Input/Value",content:"[email protected]"})
U(value,{x:40,y:284,width:310,height:20,textColor:"#111111",fontFamily:"Inter",fontSize:14,fontWeight:400})
err=I(screen,{type:"text",name:"Input/Error",content:"Error: Please enter a valid email"})
U(err,{x:40,y:312,width:310,height:20,textColor:"#ef4444",fontFamily:"Inter",fontSize:12,fontWeight:400})

Example 3 — Multi-component page and required summary

OUTPUT: TUI_RENDER

┌──────────────────────────────────────────────────────────────┐
│ [Profile]                                                   │
├──────────────────────────────────────────────────────────────┤
│ Name: Ada Lovelace                                          │
│ Role: Engineer                                              │
├──────────────────────────────────────────────────────────────┤
│ [Rate]  * * * * .  (4/5)                                    │
├──────────────────────────────────────────────────────────────┤
│ Keys: <tab> next  <enter> edit  <esc> back                   │
└──────────────────────────────────────────────────────────────┘

OUTPUT: COMPONENT_SPEC

{
  "id": "cmp_page_profile",
  "name": "Page",
  "type": "tui-page",
  "bbox": { "topPx": 0, "leftPx": 0, "widthPx": 390, "heightPx": 844 },
  "zIndex": 0,
  "layout": { "paddingPx": 24, "gapPx": 16, "align": "left", "valign": "top" },
  "style": { "fillColor": "#ffffff", "textColor": "#111111", "strokeColor": "#e5e7eb", "strokeThickness": 0, "cornerRadius": 0, "opacity": 1 },
  "typography": { "fontFamily": "Inter", "fontSize": 14, "fontWeight": 400, "lineHeight": 20 },
  "overflow": { "mode": "wrap", "ellipsis": "…", "maxLines": 0 },
  "state": { "focused": false, "disabled": false, "loading": false, "error": null },
  "hotkeys": ["<tab>", "<enter>", "<esc>"]
}

OUTPUT: PENCIL_SPEC

{
  "canvas": { "widthPx": 390, "heightPx": 844, "backgroundColor": "#ffffff" },
  "grid": { "cellWidthPx": 8, "cellHeightPx": 16 },
  "nodes": [],
  "components": [
    { "id": "cmp_profile_header", "name": "Header", "bbox": { "topPx": 24, "leftPx": 24, "widthPx": 342, "heightPx": 88 }, "zIndex": 1 },
    { "id": "cmp_rate_1", "name": "Rate", "bbox": { "topPx": 128, "leftPx": 24, "widthPx": 342, "heightPx": 64 }, "zIndex": 2 }
  ]
}

OUTPUT: PENCILBATCHDESIGN

CALL 1:
root=G()
screen=I(root,{type:"frame",name:"Profile"})
U(screen,{width:390,height:844,x:0,y:0})

CALL 2:
headerBg=I(screen,{type:"rect",name:"Header/Background"})
U(headerBg,{x:24,y:24,width:342,height:88,fillColor:"#ffffff",strokeColor:"#e5e7eb",strokeThickness:1,cornerRadius:12})
name=I(screen,{type:"text",name:"Header/Name",content:"Name: Ada Lovelace"})
U(name,{x:40,y:40,width:310,height:20,textColor:"#111111",fontFamily:"Inter",fontSize:14,fontWeight:600})
role=I(screen,{type:"text",name:"Header/Role",content:"Role: Engineer"})
U(role,{x:40,y:64,width:310,height:20,textColor:"#111111",fontFamily:"Inter",fontSize:14,fontWeight:400})
rateBg=I(screen,{type:"rect",name:"Rate/Background"})
U(rateBg,{x:24,y:128,width:342,height:64,fillColor:"#ffffff",strokeColor:"#e5e7eb",strokeThickness:1,cornerRadius:12})
rateText=I(screen,{type:"text",name:"Rate/Text",content:"* * * * .  (4/5)"})
U(rateText,{x:40,y:152,width:310,height:20,textColor:"#111111",fontFamily:"Inter",fontSize:14,fontWeight:400})

国内适配

  • 支持中文文档和中文注释
  • 示例代码兼容国内开发环境
  • 提供中文 FAQ 和常见问题解答

能力边界

✅ 适用场景

  • 当你需要使用此技能对应的技术栈时
  • 当项目需要遵循最佳实践时
  • 当需要快速上手或深入理解核心概念时

⚠️ 需要注意

  • 复杂业务逻辑需要结合具体场景调整
  • 性能优化需要根据实际数据量评估

❌ 不适用场景

  • 不相关的技术栈或框架
  • 需要完全自定义的特殊场景

使用流程

Step 1: 环境准备

确保开发环境已安装必要的依赖和工具。

Step 2: 配置初始化

根据项目需求进行基础配置。

Step 3: 核心功能使用

按照示例代码实现核心功能。

Step 4: 测试验证

运行测试确保功能正常。

Step 5: 部署上线

完成开发后进行部署和监控。