基于 SOC 职业分类
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill create-panel命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| Use when this capability is needed.
> Use when this capability is needed.
Review architecture and API design for the vfs-s3 project. Use when the user mentions @architect, asks to review an issue's design, discuss module boundaries, API shape, or architectural decisions for vfs-s3. Also trigger when the user wants to create an ADR (Architecture Decision Record) or evaluate a technical approach for the project. Intended for dispatch from Codex automation or Claude routines; GitHub trigger phrase: @vfs-s3-bot please prepare design doc Use when this capability is needed.
| name | create-panel |
| description | | Use when this capability is needed. |
This skill guides the creation of new display panels for the LCDPossible LCD controller.
| Content Type | Base Class | Location |
|---|---|---|
| System info widgets | WidgetPanel | Core plugin |
| Variable item count (0-N) | WidgetPanel with GetItemsAsync | Core plugin |
| External service data | WidgetPanel | Separate plugin |
| Custom canvas drawing | CanvasPanel | Screensavers plugin |
| Animated effects | CanvasPanel | Screensavers plugin |
Prefer WidgetPanel for new info panels - it uses HTML/CSS rendering with responsive web components.
using LCDPossible.Sdk;
namespace LCDPossible.Plugins.Core.Panels;
public sealed class MyNewPanel : WidgetPanel
{
public override string PanelId => "my-panel"; // URL-safe slug
public override string DisplayName => "My Panel"; // Human-readable
// Panel-level data (timestamp, totals, etc.)
protected override Task<object> GetPanelDataAsync(CancellationToken ct)
{
return Task.FromResult<object>(new
{
timestamp = DateTime.Now.ToString("HH:mm:ss"),
total_count = 42
});
}
// Static widgets from panel data
protected override IEnumerable<WidgetDefinition> DefineWidgets(object panelData)
{
// Cast or use dynamic
dynamic data = panelData;
yield return new WidgetDefinition("lcd-stat-card", 6, 2, new
{
title = "Total",
value = data.total_count.ToString(),
status = "success"
});
}
}
For panels displaying 0-N items (network interfaces, VMs, sensors):
public sealed class MyItemsPanel : WidgetPanel
{
public override string PanelId => "my-items";
public override string DisplayName => "My Items";
protected override Task<object> GetPanelDataAsync(CancellationToken ct)
=> Task.FromResult<object>(new { timestamp = DateTime.Now.ToString("HH:mm:ss") });
// Return items to display
protected override Task<IReadOnlyList<object>> GetItemsAsync(CancellationToken ct)
{
var items = GetMyItems(); // Your data source
return Task.FromResult<IReadOnlyList<object>>(items.Cast<object>().ToList());
}
// Customize empty state message
protected override string GetEmptyStateMessage() => "No items found";
// Render each item as a widget
protected override WidgetDefinition? DefineItemWidget(object item, int index, int totalItems)
{
var myItem = (MyItemType)item;
// Auto-layout based on item count (1-4 items)
var (colSpan, rowSpan) = WidgetLayouts.GetAutoLayout(index, totalItems);
WidgetDefinition(, colSpan, rowSpan,
{
title = myItem.Name,
items = []
{
{ label = , = myItem.Status },
{ label = , = myItem.Value }
}
});
}
}
| Component | Props | Use For |
|---|---|---|
lcd-stat-card | title, value, unit, subtitle, status, size | Single value display |
lcd-usage-bar | value, max, label, color, orientation | Progress bars |
lcd-info-list | title, subtitle, items, status | Key-value pairs |
lcd-temp-gauge | value, max, label | Temperature gauges |
lcd-sparkline | values, color, label | Time-series charts |
lcd-status-dot | status, label | Status indicators |
lcd-donut | value, max, label, color | Circular percentage |
success (green), warning (yellow), critical (red), info (blue), neutral (gray)
The grid is 12 columns wide. Common patterns:
| ColSpan | Meaning |
|---|---|
| 12 | Full width |
| 6 | Half width (2 per row) |
| 4 | Third width (3 per row) |
| 3 | Quarter width (4 per row) |
Use WidgetLayouts.GetAutoLayout(index, totalItems) for responsive layouts:
| Items | Layout |
|---|---|
| 1 | Full width (12, 4) |
| 2 | Half each (6, 4) |
| 3 | First half (6, 4), second + third quarter (6, 2) |
| 4 | 2x2 grid (6, 2) |
In the plugin class (e.g., CorePlugin.cs):
public IReadOnlyDictionary<string, PanelTypeInfo> PanelTypes { get; } = new Dictionary<string, PanelTypeInfo>
{
// ... existing panels ...
["my-panel"] = new PanelTypeInfo
{
TypeId = "my-panel",
DisplayName = "My Panel",
Description = "Description for panel list",
Category = "System", // System, Network, Thermal, etc.
IsLive = true
}
};
In the plugin's CreatePanel method:
IDisplayPanel? panel = panelTypeId.ToLowerInvariant() switch
{
// ... existing cases ...
"my-panel" => new MyNewPanel(),
_ => null
};
Add detailed metadata for CLI help:
{
"typeId": "my-panel",
"displayName": "My Panel",
"description": "Brief description",
"category": "System",
"isLive": true,
"dependencies": ["PuppeteerSharp"],
"helpText": "Detailed description for help command",
"examples": [
{
"command": "lcdpossible show my-panel",
"description": "Display my panel"
}
]
}
# Render to file
./start-app.ps1 test my-panel --debug
# Check output
# [DEBUG] Written: C:\Users\...\my-panel.jpg (XXXX bytes)
WidgetPanel uses Scriban templates internally. If you need custom templates, see the scriban-templates skill for escaping rules.
Key rule: Web components are generated automatically - you don't write Scriban templates for standard WidgetPanels.
| File | Action |
|---|---|
Panels/MyNewPanel.cs | Create - panel implementation |
CorePlugin.cs or plugin class | Modify - PanelTypes + CreatePanel |
plugin.json | Modify - add panel metadata |
IMPORTANT: All panels must comply with the visual appeal rules in .claude/rules/panel-visual-appeal.md.
Key requirements:
| Widget Content | Recommended ColSpan | Value Size |
|---|---|---|
| Single large value | 3-4 | text-4xl to text-5xl |
| Value with label | 4-6 | text-2xl to text-3xl |
| Info list (2-4 items) | 4-5 | text-xl values |
| Donut/gauge | 3-4 | text-3xl to text-4xl |
| Sparkline | 6-8 | N/A |
After creating a panel, validate with: /ensure-panelvisualappeal <panel-id>
my-panel not MyPaneldynamic data = panelData; or explicit castsize = "large" for stat cards in 4+ column spanstext-primary, text-success, not #00d4ffConverted and distributed by TomeVault — claim your Tome and manage your conversions.