Просмотр исходного кода

feat(ascii-tools): 添加多个ASCII工具的实现和示例

- 新增ascii-cli-logo-banner及其Python实现的示例文件
- 添加ascii-table-renderer基础示例和用法说明
- 实现ascii-diagram-boxflow脚本用于绘制流程图
- 添加ascii-ansi-colorizer脚本支持ANSI颜色渐变
- 新增ascii-progress-and-spinner演示脚本
- 添加ascii-cli-logo-banner-figletjs的Node.js实现
- 扩展fullstack-engineer代理配置文件
- 实现Python版本的banner生成器支持多种样式和颜色模式
wandl-6A72h 7 месяцев назад
Родитель
Сommit
9924c0d075
75 измененных файлов с 9989 добавлено и 0 удалено
  1. 47 0
      agents/fullstack-engineer.md
  2. BIN
      dist/cli-ascii-logo.skill
  3. 104 0
      docs/pipeline-stage-to-skills.md
  4. 29 0
      docs/skills-ecosystem.md
  5. 28 0
      docs/speckit-agent-skills.md
  6. 122 0
      docs/stitch-skills.md
  7. 871 0
      docs/tauri-skills.md
  8. 202 0
      skills/ascii-ansi-colorizer/LICENSE.txt
  9. 59 0
      skills/ascii-ansi-colorizer/SKILL.md
  10. 24 0
      skills/ascii-ansi-colorizer/examples/gradient.md
  11. 103 0
      skills/ascii-ansi-colorizer/scripts/colorize.py
  12. 202 0
      skills/ascii-cli-logo-banner-figletjs/LICENSE.txt
  13. 63 0
      skills/ascii-cli-logo-banner-figletjs/SKILL.md
  14. 21 0
      skills/ascii-cli-logo-banner-figletjs/examples/color-ansi256.md
  15. 30 0
      skills/ascii-cli-logo-banner-figletjs/examples/taag-figlet.md
  16. 313 0
      skills/ascii-cli-logo-banner-figletjs/scripts/figlet_banner.mjs
  17. 202 0
      skills/ascii-cli-logo-banner-python/LICENSE.txt
  18. 61 0
      skills/ascii-cli-logo-banner-python/SKILL.md
  19. 26 0
      skills/ascii-cli-logo-banner-python/examples/banner-80.md
  20. 18 0
      skills/ascii-cli-logo-banner-python/examples/banner-compact.md
  21. 17 0
      skills/ascii-cli-logo-banner-python/examples/banner-slogan-centered.md
  22. 22 0
      skills/ascii-cli-logo-banner-python/examples/color-ansi256.md
  23. 505 0
      skills/ascii-cli-logo-banner-python/scripts/generate_banner.py
  24. 202 0
      skills/ascii-cli-logo-banner/LICENSE.txt
  25. 81 0
      skills/ascii-cli-logo-banner/SKILL.md
  26. 26 0
      skills/ascii-cli-logo-banner/examples/banner-80.md
  27. 18 0
      skills/ascii-cli-logo-banner/examples/banner-compact.md
  28. 202 0
      skills/ascii-diagram-boxflow/LICENSE.txt
  29. 52 0
      skills/ascii-diagram-boxflow/SKILL.md
  30. 50 0
      skills/ascii-diagram-boxflow/examples/login-flow.md
  31. 105 0
      skills/ascii-diagram-boxflow/scripts/boxflow.py
  32. 202 0
      skills/ascii-image-to-ascii/LICENSE.txt
  33. 70 0
      skills/ascii-image-to-ascii/SKILL.md
  34. 39 0
      skills/ascii-image-to-ascii/examples/readable-vs-detail.md
  35. 145 0
      skills/ascii-image-to-ascii/scripts/image_to_ascii.py
  36. 202 0
      skills/ascii-mini-charts/LICENSE.txt
  37. 52 0
      skills/ascii-mini-charts/SKILL.md
  38. 31 0
      skills/ascii-mini-charts/examples/sparkline.md
  39. 130 0
      skills/ascii-mini-charts/scripts/mini_charts.py
  40. 202 0
      skills/ascii-motd-profile-banner/LICENSE.txt
  41. 50 0
      skills/ascii-motd-profile-banner/SKILL.md
  42. 22 0
      skills/ascii-motd-profile-banner/examples/ssh-long.md
  43. 14 0
      skills/ascii-motd-profile-banner/examples/ssh-short.md
  44. 202 0
      skills/ascii-progress-and-spinner/LICENSE.txt
  45. 59 0
      skills/ascii-progress-and-spinner/SKILL.md
  46. 40 0
      skills/ascii-progress-and-spinner/examples/styles.md
  47. 97 0
      skills/ascii-progress-and-spinner/scripts/demo.py
  48. 202 0
      skills/ascii-table-renderer/LICENSE.txt
  49. 62 0
      skills/ascii-table-renderer/SKILL.md
  50. 41 0
      skills/ascii-table-renderer/examples/basic.md
  51. 154 0
      skills/ascii-table-renderer/scripts/render_table.py
  52. 202 0
      skills/ascii-terminal-animation-pack/LICENSE.txt
  53. 54 0
      skills/ascii-terminal-animation-pack/SKILL.md
  54. 12 0
      skills/ascii-terminal-animation-pack/examples/poster.md
  55. 17 0
      skills/ascii-terminal-animation-pack/examples/spec.md
  56. 111 0
      skills/ascii-terminal-animation-pack/scripts/matrix_demo.py
  57. 202 0
      skills/ascii-text-art-library/LICENSE.txt
  58. 51 0
      skills/ascii-text-art-library/SKILL.md
  59. 60 0
      skills/ascii-text-art-library/examples/templates-80.md
  60. 79 0
      skills/ascii-text-art-library/scripts/generate_templates.py
  61. 68 0
      skills/cli-ascii-logo/SKILL.md
  62. 22 0
      skills/cli-ascii-logo/references/palettes.md
  63. 577 0
      skills/cli-ascii-logo/scripts/generate_logo.py
  64. 42 0
      skills/skill-installer/SKILL.md
  65. 3 0
      skills/skill-installer/index.d.ts
  66. 1 0
      skills/skill-installer/index.d.ts.map
  67. 161 0
      skills/skill-installer/index.js
  68. 0 0
      skills/skill-installer/index.js.map
  69. 260 0
      skills/skill-installer/index.ts
  70. 1254 0
      skills/skill-installer/package-lock.json
  71. 23 0
      skills/skill-installer/package.json
  72. 16 0
      skills/skill-installer/tsconfig.json
  73. 69 0
      skills/skill-sop-creator/SKILL.md
  74. 831 0
      tools/generate_tui_skills.py
  75. 53 0
      tools/lint_tui_no_uviewpro.py

+ 47 - 0
agents/fullstack-engineer.md

@@ -0,0 +1,47 @@
+---
+name: fullstack-engineer
+description: "Use this agent when you need comprehensive full-stack engineering expertise, particularly for server-side development, system architecture, DevOps, and infrastructure tasks. Examples include: (1) Designing and implementing scalable server architectures using languages like Node.js, Python, Go, Java, or Ruby; (2) Setting up CI/CD pipelines, Docker containers, Kubernetes orchestrations, or cloud infrastructure on AWS/Azure/GCP; (3) Optimizing database performance, implementing caching strategies, or designing API systems; (4) Troubleshooting production issues, analyzing logs, or performing system monitoring and alerting setup; (5) Implementing security best practices, authentication systems, or compliance requirements; (6) Conducting code reviews for backend services, infrastructure as code, or deployment configurations. This agent should be consulted proactively when architectural decisions, scalability concerns, or operational excellence considerations are needed for any server-side or infrastructure component."
+model: sonnet
+---
+
+You are a senior full-stack engineer with deep expertise in server-side development across multiple programming languages and comprehensive DevOps knowledge. Your specialization encompasses backend architecture, system design, infrastructure automation, and operational excellence.
+
+Core Competencies:
+- **Server-Side Development**: You are proficient in Node.js, Python (Django, Flask, FastAPI), Go, Java (Spring Boot), Ruby on Rails, PHP, and C#. You understand when to use each language based on performance requirements, team expertise, and ecosystem considerations.
+- **Database Architecture**: You design optimal database schemas, write efficient queries, implement proper indexing strategies, and work with PostgreSQL, MySQL, MongoDB, Redis, and other data stores. You understand ACID properties, transaction management, and data consistency patterns.
+- **API Design**: You create RESTful APIs and GraphQL services with proper versioning, authentication (OAuth2, JWT), rate limiting, pagination, and comprehensive error handling. You follow OpenAPI/Swagger standards for documentation.
+- **DevOps & Infrastructure**: You excel in containerization (Docker), orchestration (Kubernetes), CI/CD pipelines (GitHub Actions, GitLab CI, Jenkins), Infrastructure as Code (Terraform, CloudFormation), and cloud platforms (AWS, Azure, GCP).
+- **System Architecture**: You design microservices architectures, implement event-driven systems using message queues (RabbitMQ, Kafka), and apply patterns like Circuit Breaker, CQRS, and Event Sourcing when appropriate.
+- **Performance & Scalability**: You optimize application performance through caching strategies (Redis, Memcached), load balancing, horizontal scaling, database sharding, and CDN implementation. You conduct load testing and capacity planning.
+- **Security**: You implement security best practices including input validation, SQL injection prevention, XSS protection, CSRF tokens, secure headers (CSP, HSTS), and secrets management. You conduct security audits and follow OWASP guidelines.
+- **Monitoring & Observability**: You set up comprehensive monitoring using Prometheus, Grafana, ELK stack, or Datadog. You implement structured logging, distributed tracing (Jaeger, Zipkin), and create meaningful dashboards and alerting rules.
+- **Testing**: You advocate for TDD/BDD, write unit tests (Jest, pytest, JUnit), integration tests, and end-to-end tests. You understand testing pyramid principles and mock external dependencies appropriately.
+
+Operational Principles:
+1. **Pragmatic Decision Making**: Choose technologies and approaches based on project requirements, team capabilities, and long-term maintainability rather than following trends.
+2. **Code Quality**: Write clean, readable, well-documented code following SOLID principles and language-specific idioms. Conduct thorough code reviews with constructive feedback.
+3. **Operational Excellence**: Implement automation for repetitive tasks, ensure zero-downtime deployments, and design systems with failure in mind (graceful degradation, retry mechanisms, circuit breakers).
+4. **Documentation**: Maintain clear documentation for architecture decisions (ADRs), API specifications, deployment procedures, and runbooks for incident response.
+5. **Cost Optimization**: Consider cloud costs, right-size resources, implement auto-scaling policies, and choose appropriate pricing models (reserved instances, spot instances).
+
+When Approaching Tasks:
+- **Analysis**: First understand the business requirements, constraints, and success criteria. Ask clarifying questions if specifications are ambiguous.
+- **Solution Design**: Propose multiple approaches with trade-offs clearly explained (complexity vs. performance, cost vs. reliability, time-to-market vs. technical debt).
+- **Implementation**: Write production-ready code with proper error handling, logging, metrics, and testing. Include examples and usage instructions.
+- **Review & Optimization**: Critique your own solutions before presenting them. Identify potential bottlenecks, security vulnerabilities, or scalability issues.
+- **Deployment Considerations**: Provide deployment strategies (blue-green, canary, rolling updates) and rollback procedures.
+
+Communication Style:
+- Be precise and technical when discussing implementation details
+- Explain complex concepts with appropriate analogies when needed
+- Provide context for architectural decisions (why X over Y)
+- Highlight risks and mitigation strategies proactively
+- Include code examples, configuration snippets, and diagram descriptions when helpful
+
+When encountering edge cases or ambiguous requirements:
+- State assumptions clearly before proceeding
+- Provide recommendations with confidence levels
+- Suggest proof-of-concept approaches for high-risk areas
+- Offer to validate decisions with stakeholders when appropriate
+
+You balance technical excellence with practical delivery, understanding that perfect is the enemy of good. You advocate for sustainable development practices that enable long-term project success while meeting immediate business needs.

BIN
dist/cli-ascii-logo.skill


+ 104 - 0
docs/pipeline-stage-to-skills.md

@@ -0,0 +1,104 @@
+# 需求→部署全链路:阶段与技能映射表
+
+本文档固化了「需求 → PRD → 原型与设计 → 领域模型与架构 → 任务拆分 → 开发 → 测试 → 部署」各阶段对应的技能名及所属仓库,供编排 Agent 或 PartMe Claw 按需调用。当前阶段仅做技能准备,不落编排实现。
+
+**技能来源**:speckit-skills(或 speckit-agent-skills)、t2ui-skills、stitch-skills、pencil-skills、full-stack-skills。
+
+---
+
+## 阶段总览(产品 / 设计 / 开发)
+
+| 阶段 | 仓库 | 职责 | 输入 → 输出 |
+|------|------|------|-------------|
+| **产品阶段** | speckit-skills(即 speckit-agent-skills / 本仓库 speckit-*) | 描述需求、澄清需求 | 需求分析 → 原始需求 → PRD 文档 |
+| **设计阶段** | t2ui-skills(需求转译) | 需求转译 | PRD 文档 → ASCII 界面;PRD 文档 → Stitch 设计语言;PRD 文档 → Pencil 设计语言 |
+| **设计阶段** | stitch-skills | 原型设计 | Stitch 设计语言 → Stitch MCP → 原型图 |
+| **设计阶段** | pencil-skills | 界面设计 | Pencil 设计语言 → Pencil MCP → 产品图 |
+| **开发阶段** | speckit-skills(即 speckit-agent-skills / 本仓库 speckit-*) | 领域与架构、技术细分 | 领域模型设计、系统架构设计、技术细分 |
+
+说明:t2ui-skills 在本链路中承担「需求转译」(text/PRD to UI 描述),只产出描述语言,不调用 Stitch/Pencil MCP。
+
+---
+
+## 1. 需求侧(产品阶段)
+
+| 阶段 | 技能名 | 仓库 | 说明 |
+|------|--------|------|------|
+| 需求 / 一句话需求 / 需求分析 → 原始需求 | full-stack-doc | full-stack-skills | 需求分析模板、需求调研模板 |
+| 需求 / PRD(what/why) | speckit-specify | speckit-agent-skills(可选) | Spec Kit:从自然语言生成/更新规格 |
+| 需求澄清 / 歧义消除 | speckit-clarify | speckit-agent-skills(可选) | Spec Kit:澄清规格 |
+| 清楚的原始需求 → PRD 文档 | full-stack-doc | full-stack-skills | PRD 文档模板 |
+| 需求/PRD → 结构化设计输入 | stitch-ui-design-spec-generator, stitch-ui-prompt-architect | stitch-skills | 设计规范与 Stitch 提示词 |
+| PRD 界面 → 多格式描述 | tui-prd-to-descriptions | t2ui-skills | ASCII 补充 PRD;Stitch 可执行描述供 stitch-skills;Pencil 可执行描述供 pencil-skills。不调用 Stitch/Pencil MCP |
+
+**缺口**:独立「一句话需求归纳」技能可后续补充;当前可由 full-stack-doc + 对话或 speckit-clarify 覆盖。
+
+---
+
+## 2. 设计阶段(需求转译 → 原型 → 界面)
+
+| 阶段 | 技能名 | 仓库 | 说明 |
+|------|--------|------|------|
+| **需求转译**(PRD → 多格式描述) | tui-prd-to-descriptions | t2ui-skills | PRD 文档 → ASCII 界面;PRD → Stitch 设计语言;PRD → Pencil 设计语言。不调用 MCP |
+| 设计规范 / 视觉与交互 DNA | full-stack-doc, stitch-ui-design-spec-* | full-stack-skills, stitch-skills | 视觉与交互 DNA 模板;uviewpro/element 等框架设计规范 |
+| **原型设计**(Stitch 设计语言 → 原型图) | stitch-mcp-*;编排:stitch-ui-designer | stitch-skills | Stitch 设计语言 → Stitch MCP → 原型图 |
+| **界面设计**(Pencil 设计语言 → 产品图) | pencil-mcp-*;编排:pencil-ui-designer;pencil-design-from-stitch-html | pencil-skills | Pencil 设计语言 → Pencil MCP → 产品图(.pen);或 Stitch HTML → .pen |
+| UI 设计说明 | full-stack-doc, stitch-design-md | full-stack-skills, stitch-skills | UI 设计说明模板;从 Stitch 项目产出 DESIGN.md |
+| 交互设计(规范与说明) | stitch-ued-guide, stitch-ui-design-spec-* | stitch-skills | UED 指南;框架规范 |
+
+---
+
+## 3. 开发阶段(领域模型 / 系统架构 / 技术细分)
+
+| 阶段 | 技能名 | 仓库 | 说明 |
+|------|--------|------|------|
+| **领域模型设计** | full-stack-doc, ddd4j-project-creator, ddd-cola, plantuml;speckit-* | full-stack-skills;speckit-skills | 领域模型说明模板;DDD/COLA;PlantUML |
+| **系统架构设计** | full-stack-doc, drawio-architecture, plantuml;speckit-plan | full-stack-skills;speckit-skills | 系统架构设计模板;DrawIO;PlantUML |
+| **技术细分** | full-stack-doc, skill-sop-creator;speckit-tasks | full-stack-skills;speckit-skills | 任务拆分、技术细分、可执行工作项 |
+| 技术策略(how) | speckit-plan | speckit-agent-skills(可选) | Spec Kit:技术方案/计划 |
+| 任务列表(可执行工作项) | speckit-tasks | speckit-agent-skills(可选) | Spec Kit:生成有序任务 |
+| 一致性/依赖校验 | speckit-analyze | speckit-agent-skills(可选) | Spec Kit:分析校验 |
+
+---
+
+## 4. 前端开发 / 后端开发
+
+| 阶段 | 技能名 | 仓库 | 说明 |
+|------|--------|------|------|
+| 前端(Vue/React/uni-app,基于设计稿) | stitch-uviewpro-components, stitch-vue-element-components, stitch-react-components 等;frontend-design | stitch-skills, full-stack-skills | Stitch 屏→组件代码;前端设计 |
+| 后端(Java/Node 等) | ddd4j-project-creator, spring-boot, nestjs 等 | full-stack-skills | DDD4j;Spring Boot;NestJS |
+| 实现(代码落地) | speckit-implement | speckit-agent-skills(可选) | Spec Kit:按规格与任务执行实现 |
+
+**说明**:**桌面/跨平台**开发可选用 [tauri-skills](https://github.com/partme-ai/tauri-skills)(Tauri 应用开发)。**Node 版本管理**等基础技能见本仓库 **nvm-install**、**nvm-setup**、**nvm-usage-basics** 等(详见 [docs/skills-ecosystem.md](skills-ecosystem.md))。
+
+---
+
+## 5. 自动化测试 / 自动化部署
+
+| 阶段 | 技能名 | 仓库 | 说明 |
+|------|--------|------|------|
+| 自动化测试 | test-writer, playwright, pytest, jest, webapp-testing | full-stack-skills | 测试编写;E2E/单元 |
+| 自动化部署 | github-actions, gitlab-ci, jenkins, docker, kubernetes | full-stack-skills | CI/CD;容器与编排 |
+
+---
+
+## 6. Spec Kit 与本链路的对应关系
+
+| Spec Kit 阶段 | 本链路阶段 | 本仓库技能 | 外部/可选 |
+|---------------|------------|------------|-----------|
+| Constitution | 项目原则/约束 | full-stack-doc | speckit-constitution |
+| Specify | 需求/PRD(what/why) | full-stack-doc | speckit-specify |
+| Clarify | 需求澄清 | — | speckit-clarify |
+| Plan | 领域模型/架构/技术策略 | full-stack-doc, ddd4j, plantuml, drawio | speckit-plan |
+| Analyze | 一致性校验 | — | speckit-analyze |
+| Tasks | 任务拆分与工作项 | full-stack-doc(技术细分), skill-sop-creator | speckit-tasks |
+| Implement | 开发/测试/部署 | stitch-*, pencil-*, ddd4j, test-writer, github-actions 等 | speckit-implement |
+
+使用 Spec Kit 时,可在运行环境中安装 [dceoy/speckit-agent-skills](https://github.com/dceoy/speckit-agent-skills),将 `skills/` 与 stitch-skills、pencil-skills、full-stack-skills 一并加载。**本仓库**已在 `full-stack-skills/skills/` 内复制 speckit-* 技能,详见 [speckit-agent-skills.md](speckit-agent-skills.md)。
+
+---
+
+## 7. 文档与编排
+
+- **阶段→技能**:本文档为权威映射表;后续全链路编排 Agent(如 product-dev-pipeline)按此表按需调用技能。
+- **各仓库说明**:speckit-skills(speckit-agent-skills)、t2ui-skills、stitch-skills、pencil-skills、tauri-skills、full-stack-skills 的 AGENTS.md 或 README 中已注明参与本链路(或边界),并指向本文档(或 workspace 内等效路径)。

+ 29 - 0
docs/skills-ecosystem.md

@@ -0,0 +1,29 @@
+# 技能生态与主文档入口
+
+本仓库(**full-stack-skills**)为全链路**阶段→技能**映射与**基础技能**的主入口。权威映射表见 [pipeline-stage-to-skills.md](pipeline-stage-to-skills.md)。
+
+**说明**:tui/t2ui 类技能(需求转译、ASCII 界面、Pencil 设计语言等)以 **t2ui-skills** 为准,本仓库不再保留 `skills/tui-skills`。Pencil MCP 使用与 .pen 编辑以 **pencil-skills** 为准,本仓库不再保留 `skills/pencil`。
+
+---
+
+## 关联技能仓库
+
+| 仓库 | 职责 | 阶段/用途 |
+|------|------|-----------|
+| [t2ui-skills](https://github.com/partme-ai/t2ui-skills) | 需求转译:PRD → ASCII 界面、Stitch 设计语言、Pencil 设计语言 | 设计阶段 |
+| [stitch-skills](https://github.com/partme-ai/stitch-skills) | 原型设计:Stitch 设计语言 → Stitch MCP → 原型图 | 设计阶段 |
+| [pencil-skills](https://github.com/partme-ai/pencil-skills) | 界面设计:Pencil 设计语言 → Pencil MCP → 产品图(.pen) | 设计阶段 |
+| [tauri-skills](https://github.com/partme-ai/tauri-skills) | Tauri 跨平台桌面/移动应用开发 | 开发阶段(桌面/跨平台) |
+| **full-stack-skills**(本仓库) | 基础技能(文档/架构/测试/部署、nvm 等)、speckit-*、阶段映射 | 全阶段 |
+
+各仓库的 README/AGENTS 应指向本文档或 [pipeline-stage-to-skills.md](pipeline-stage-to-skills.md)。
+
+---
+
+## nvm 相关技能(本仓库内)
+
+**Node 版本管理**等基础开发环境技能当前在 **full-stack-skills** 内,不作为独立仓库:
+
+- nvm-install、nvm-setup、nvm-usage-basics、nvm-defaults-and-nvmrc、nvm-shell-integration、nvm-docker-ci、nvm-troubleshooting-macos、nvm-global-packages 等。
+
+若未来拆出独立 nvm-skills 仓库,将在本文档与 pipeline 中补充对应条目。Tauri 技能规划清单见 [tauri-skills.md](tauri-skills.md)。

+ 28 - 0
docs/speckit-agent-skills.md

@@ -0,0 +1,28 @@
+# Spec Kit 技能整合说明
+
+本仓库在 `skills/` 下已复制 [dceoy/speckit-agent-skills](https://github.com/dceoy/speckit-agent-skills) 的 **speckit-*** 技能,用于与「需求→部署」全链路映射表配合使用。
+
+## 技能列表
+
+| 技能名 | 说明 |
+|--------|------|
+| speckit-constitution | 定义项目原则与约束 |
+| speckit-specify | 从自然语言生成/更新功能规格(what/why) |
+| speckit-clarify | 澄清规格歧义 |
+| speckit-baseline | 从现有代码生成规格(可选入口) |
+| speckit-plan | 生成技术方案(how) |
+| speckit-analyze | 一致性/依赖校验 |
+| speckit-tasks | 生成有序工作项 |
+| speckit-taskstoissues | 任务转 Issue(如 GitHub) |
+| speckit-checklist | 检查清单 |
+| speckit-implement | 按规格与任务执行实现 |
+
+## 与本链路的关系
+
+- **阶段→技能映射**:见 [pipeline-stage-to-skills.md](pipeline-stage-to-skills.md);其中需求/PRD、领域模型/架构/任务拆分、实现等阶段均列出可选 speckit-* 对应项。
+- **上游**:原始技能与 Spec Kit 工作流见 [speckit-agent-skills README](https://github.com/dceoy/speckit-agent-skills)。若需 `.specify/` 模板或脚本,可从该仓库另行复制或通过 [Spec Kit](https://github.com/github/spec-kit) 安装使用。
+
+## 使用方式
+
+- 与 stitch-skills、pencil-skills、full-stack-skills 其他技能一并加载,由编排 Agent 或人工按阶段按需调用。
+- 各 speckit-* 的 SKILL.md 保持上游格式;仅在本仓库文档中说明其与全链路阶段的对应关系。

+ 122 - 0
docs/stitch-skills.md

@@ -0,0 +1,122 @@
+          
+Stitch MCP 是一套强大的 AI UI 生成工具,基于你提供的 MCP 定义文件,我为你设计了一套完整的 **"AI-Driven UED Workflow" (AI 驱动的用户体验设计工作流)**。
+
+这份规划旨在将 Stitch 的原子能力封装为 Agent 可调用的高阶技能(Skills),并建立严谨的 "设计 -> 执行" 规范,确保生成的 UI 既符合用户创意,又具备工程落地的高质量。
+
+---
+
+### 🎨 Stitch Agent Skills 体系规划
+
+我将 Skills 分为三层:**基础原子技能层**(直接映射 MCP)、**高级设计技能层**(Prompt Engineering & 规范化)、**工作流编排层**(全链路落地)。
+
+#### 1. 基础原子技能层 (Atomic Skills)
+这部分直接封装 MCP 工具,供 Agent 在执行具体动作时调用。
+
+| Skill Name | 对应 MCP | 描述与用途 |
+| :--- | :--- | :--- |
+| `stitch_project_create` | `create_project` | **创建项目容器**。用于初始化一个新的设计空间,设定全局的主题(颜色、字体、圆角)和设备类型(Mobile/Desktop)。 |
+| `stitch_project_list` | `list_projects` | **检索项目列表**。用于查找现有的设计项目,支持按所有者筛选。 |
+| `stitch_project_get` | `get_project` | **获取项目详情**。用于读取项目的元数据、全局主题配置等上下文信息。 |
+| `stitch_screen_generate` | `generate_screen_from_text` | **核心生成能力**。输入 Prompt,输出 UI 界面。支持指定模型(Gemini 3 Pro/Flash)和设备类型。 |
+| `stitch_screen_list` | `list_screens` | **浏览页面列表**。查看当前项目下已经生成的页面概览。 |
+| `stitch_screen_get` | `get_screen` | **获取页面详情**。获取特定页面的 HTML 代码、截图 URL 和 Figma 导出文件。 |
+
+#### 2. 高级设计技能层 (Design Logic Skills)
+这部分是你要求的 **"先设计,后执行"** 的核心。Agent 不直接调用生成工具,而是先调用这些 Skill 来“思考”和“规范”设计。
+
+*   **`design_spec_generator` (视觉交互 DNA 规范生成)**
+    *   **输入**: 用户模糊需求(如 "做一个小清新的宠物店 App")。
+    *   **输出**: 结构化的设计规范 JSON。包含:配色方案(主色、辅色、背景色)、排版系统(字体、字号)、圆角风格、阴影深度、组件风格。
+    *   **作用**: 对应目录下的 `5、视觉与交互 DNA 规范模板.md`,确保项目风格统一。
+
+*   **`ui_prompt_architect` (UI 提示词架构师)**
+    *   **输入**: 页面功能描述 + 设计规范。
+    *   **输出**: **Stitch-Ready Prompt**。这是专门针对 Stitch 优化过的提示词,包含布局结构、组件细节、状态描述。
+    *   **作用**: 将 "登录页" 翻译成 "Mobile screen, minimal style. Top 1/3: Brand logo centered. Middle: Input field for 'Email', Input field for 'Password'. Bottom: Primary button 'Login', Secondary link 'Forgot Password'. White background, #007AFF accent."
+
+#### 3. UX 落地操作指南 (UX Implementation Guide)
+
+这是一套标准作业程序 (SOP),指导 Agent 如何一步步完成任务。
+
+**阶段一:项目初始化 (Setup)**
+1.  **用户意图分析**: 确定是新项目还是在旧项目新增页面。
+2.  **风格定义**: 调用 `design_spec_generator` 确定 Design Theme。
+3.  **创建/选择项目**: 调用 `stitch_project_create` (带上定义好的 Theme) 或 `stitch_project_list`。
+
+**阶段二:页面设计与生成 (Design & Generate)**
+1.  **需求转化**: 用户输入需求 -> 调用 `ui_prompt_architect` -> 获得 Stitch Prompt。
+2.  **执行生成**: 调用 `stitch_screen_generate` (传入 Stitch Prompt + ProjectID)。
+3.  **结果验证**: 获取生成结果,展示给用户(Screenshot)。
+
+**阶段三:交付与迭代 (Deliver)**
+1.  **代码获取**: 调用 `stitch_screen_get` 获取 HTML/Figma。
+2.  **资产归档**: 将生成的资源记录到项目文档中。
+
+---
+
+### 📘 UED 交互指南 (Interaction Guidelines)
+
+为了让 Agent 更好地扮演资深设计师,制定以下交互原则:
+
+**1. 视觉语言标准化 (Visual Vocabulary)**
+Agent 在与 Stitch 交互时,必须使用标准的视觉术语:
+*   **布局**: Header, Footer, Sidebar, Grid, Hero Section, Card Layout.
+*   **组件**: FAB (Floating Action Button), Modal, Toast, Carousel, Accordion, Tab Bar.
+*   **风格**: Flat, Material, Neomorphism, Glassmorphism, Brutalism, Minimalist.
+
+**2. 设备与响应式约束**
+*   **Mobile**: 默认宽度 375px/393px,强调垂直滚动,Touch Target > 44px。
+*   **Desktop**: 强调栅格系统,利用宽屏优势做多栏布局。
+
+**3. 渐进式增强提示 (Progressive Prompting)**
+*   不要试图一次性生成极其复杂的逻辑。
+*   策略:**先骨架,后肉体**。
+    *   *Bad*: "做一个像淘宝一样的电商首页,要有秒杀倒计时和推荐算法流。"
+    *   *Good*: "E-commerce app home screen. Top: Search bar and category icons. Middle: Featured banner carousel. Bottom: 2-column product grid with image, title, and price."
+
+---
+
+### 🚀 实战案例:设计一个登录页面
+
+按照要求 #5,演示 Agent 的执行路径:
+
+**用户指令**: "帮我设计一个登录页面,风格要科技感强一点,暗色调。"
+
+**Agent 执行步骤**:
+
+1.  **[Skill: design_spec_generator] 思考与规划**:
+    *   *分析*: 风格=科技感 (Cyberpunk/Futuristic),色调=Dark Mode。
+    *   *输出设计规范*:
+        *   Theme: Dark
+        *   Primary Color: Neon Blue (#00F0FF) or Neon Purple.
+        *   Font: Inter or Roboto Mono.
+        *   Roundness: Low (Sharp edges).
+
+2.  **[Skill: ui_prompt_architect] 构建提示词**:
+    *   *构建*: 基于上述规范和 "登录页" 功能。
+    *   *输出 Prompt*:
+        > "Dark mode mobile login screen. Cyberpunk aesthetic. Background: Deep dark blue (#0A0A12) with subtle geometric glowing lines.
+        > Center: App logo with neon glow effect.
+        > Form area: Two input fields with dark semi-transparent background and neon blue borders for 'Username' and 'Password'.
+        > Action: Large rectangular 'LOGIN' button, solid neon blue background, white bold text.
+        > Footer: 'Create Account' link in grey text. Tech font style."
+
+3.  **[Skill: stitch_screen_generate] 调用 MCP**:
+    *   `projectId`: [Current Project ID]
+    *   `prompt`: [The Prompt from Step 2]
+    *   `deviceType`: MOBILE
+    *   `modelId`: GEMINI_3_PRO
+
+4.  **[Skill: stitch_screen_get] 获取结果**:
+    *   向用户展示生成的截图,询问是否满意。
+
+---
+
+### 下一步计划
+
+如果您认可这个规划,我将开始编写:
+1.  **Agent Skills 代码/Prompt 模板**:实现上述的 `design_spec_generator` 等逻辑。
+2.  **集成 MCP**:确保 Agent 可以通过 `Task` 或 `Tool` 的形式调用 Stitch MCP。
+3.  **文档输出**:生成完整的 `.md` 指南文档,放入您的 `2.0、模板` 目录中。
+
+请确认是否开始执行创建?

+ 871 - 0
docs/tauri-skills.md

@@ -0,0 +1,871 @@
+# Tauri v2 Agent Skills 生成指令清单
+
+### 1. Foundation (基石层)
+
+- tauri-setup ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-setup 的 skills,必须参考
+- `https://v2.tauri.app/start/prerequisites/`
+- `https://v2.tauri.app/mobile/development/#prerequisites`
+  并严格遵循以下设计规格:
+- **边界**:专注于操作系统层面的依赖安装(Rust, Node.js, VS Build Tools, Xcode, Android SDK)。
+- **v2 特性**:必须包含移动端开发环境(Android Studio/NDK)的检查步骤。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能完成全平台开发环境准备。
+
+- tauri-scaffold ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-scaffold 的 skills,必须参考
+- `https://v2.tauri.app/start/create-project/`
+- `https://v2.tauri.app/start/project-structure/`
+- `https://v2.tauri.app/start/frontend/`
+  并严格遵循以下设计规格:
+- **边界**:`create-tauri-app` 的执行决策与初始配置。
+- **关键点**:重点处理前端框架的 SSG(静态站点生成)配置(如 Next.js 的 `output: 'export'`),确保适配 Tauri v2 的加载机制。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能创建结构正确的 Tauri v2 项目。
+
+- tauri-app-creator ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-creator 的 skills,必须参考
+- `https://v2.tauri.app/`
+- `https://v2.tauri.app/start/`
+- `https://v2.tauri.app/start/prerequisites/`
+- `https://v2.tauri.app/start/create-project/`
+- `https://v2.tauri.app/start/project-structure/`
+  并严格遵循以下设计规格:
+- **边界**:用官方脚手架创建 Tauri v2 项目(create-tauri-app)。
+- **关键点**:根据系统与团队偏好选择安装方式(curl / npm / pnpm / bun / cargo),并能解释每种方式的适用场景。
+- **输出**:给出可执行的创建命令,以及创建后最小可运行的验证路径(安装依赖、启动前端与 Tauri 开发模式)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能完成 Tauri v2 项目创建工作。
+
+Bash:sh <(curl https://create.tauri.app/sh)
+PowerShell:irm https://create.tauri.app/ps | iex
+Fish:sh (curl -sSL https://create.tauri.app/sh | psub)
+npm:npm create tauri-app@latest
+Yarn:yarn create tauri-app
+pnpm:pnpm create tauri-app
+deno:deno run -A npm:create-tauri-app
+bun:bun create tauri-app
+Cargo:
+cargo install create-tauri-app --locked
+cargo create-tauri-app
+
+- tauri-app-frontend-selection ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-frontend-selection 的 skills,必须参考
+- `https://v2.tauri.app/start/frontend/`
+- `https://v2.tauri.app/start/frontend/leptos/`
+- `https://v2.tauri.app/start/frontend/nextjs/`
+- `https://v2.tauri.app/start/frontend/nuxt/`
+- `https://v2.tauri.app/start/frontend/qwik/`
+- `https://v2.tauri.app/start/frontend/sveltekit/`
+- `https://v2.tauri.app/start/frontend/trunk/`
+- `https://v2.tauri.app/start/frontend/vite/`
+  并严格遵循以下设计规格:
+- **边界**:前端框架选型与初始化策略(与 Tauri v2 加载机制兼容)。
+- **推荐**:默认推荐 Vite(除非需求明确要求 SSR/SSG 框架)。
+- **关键点**:对需要静态导出的框架(如 Next.js)明确给出 SSG/export 配置与产物路径要求,确保 Tauri 能加载本地静态资源。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能完成前端框架选型与初始化工作。
+
+### 2. Core Development (核心开发层)
+
+- tauri-ipc ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-ipc 的 skills,必须参考
+- `https://v2.tauri.app/concept/inter-process-communication/`
+- `https://v2.tauri.app/develop/calling-rust/`
+- `https://v2.tauri.app/develop/calling-frontend/`
+  并严格遵循以下设计规格:
+- **边界**:前端 `invoke` 调用与后端 `#[tauri::command]` 定义。
+- **v2 特性**:强调类型安全,优先推荐使用 `tauri-specta` 或官方类型生成工具,避免 `any` 类型。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现类型安全的双向通信。
+
+- tauri-app-develop ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-develop 的 skills,必须参考
+- `https://v2.tauri.app/develop/`
+- `https://v2.tauri.app/develop/configuration-files/`
+- `https://v2.tauri.app/develop/calling-rust/`
+- `https://v2.tauri.app/develop/calling-frontend/`
+- `https://v2.tauri.app/develop/resources/`
+- `https://v2.tauri.app/develop/sidecar/`
+- `https://v2.tauri.app/develop/state-management/`
+- `https://v2.tauri.app/develop/updating-dependencies/`
+- `https://v2.tauri.app/develop/icons/`
+- `https://v2.tauri.app/develop/debug/`
+- `https://v2.tauri.app/develop/debug/crabnebula-devtools/`
+- `https://v2.tauri.app/develop/debug/neovim/`
+- `https://v2.tauri.app/develop/debug/rustrover/`
+- `https://v2.tauri.app/develop/debug/vscode/`
+- `https://v2.tauri.app/develop/plugins/`
+- `https://v2.tauri.app/develop/plugins/develop-mobile/`
+- `https://v2.tauri.app/develop/tests/`
+- `https://v2.tauri.app/develop/tests/mocking/`
+- `https://v2.tauri.app/develop/tests/webdriver/`
+- `https://v2.tauri.app/develop/tests/webdriver/ci/`
+- `https://v2.tauri.app/develop/tests/webdriver/example/selenium/`
+- `https://v2.tauri.app/develop/tests/webdriver/example/webdriverio/`
+  并严格遵循以下设计规格:
+- **边界**:覆盖 Tauri v2 的日常开发工作流(调试、资源、sidecar、图标、插件与测试)。
+- **关键点**:能在“前端 dev server”与“本地静态资源加载”两种模式间切换并解释差异;同时指导如何定位 Rust 与 WebView 双端问题。
+- **质量门控**:引导为关键能力补齐自动化测试策略(mocking / webdriver / CI)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能进行 Tauri 技术栈项目的开发工作。
+
+- tauri-window ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-window 的 skills,必须参考
+- `https://v2.tauri.app/learn/window-customization/`
+- `https://v2.tauri.app/zh-cn/learn/window-customization/`
+- `https://v2.tauri.app/reference/config/#windows-config`
+  并严格遵循以下设计规格:
+- **边界**:窗口的创建、配置与生命周期管理。
+- **关键点**:包含自定义标题栏(Custom Titlebar)的 CSS 与 JS 实现逻辑。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能构建现代化的桌面窗口 UI。
+
+- tauri-menu-tray ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-menu-tray 的 skills,必须参考
+- `https://v2.tauri.app/plugin/tray-icon/`
+- `https://v2.tauri.app/plugin/menu/`
+  并严格遵循以下设计规格:
+- **边界**:原生应用菜单(Menu)与系统托盘(Tray Icon)。
+- **关键点**:处理 macOS 与 Windows 在菜单规范上的差异。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现原生系统交互体验。
+
+- tauri-concept ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-concept 的 skills,必须参考
+- `https://v2.tauri.app/concept/`
+- `https://v2.tauri.app/concept/architecture/`
+- `https://v2.tauri.app/concept/process-model/`
+- `https://v2.tauri.app/concept/size/`
+- `https://v2.tauri.app/concept/inter-process-communication/`
+- `https://v2.tauri.app/concept/inter-process-communication/brownfield/`
+- `https://v2.tauri.app/concept/inter-process-communication/isolation/`
+- `https://v2.tauri.app/zh-cn/concept/`
+- `https://v2.tauri.app/zh-cn/concept/architecture/`
+- `https://v2.tauri.app/zh-cn/concept/process-model/`
+- `https://v2.tauri.app/zh-cn/concept/size/`
+- `https://v2.tauri.app/zh-cn/concept/inter-process-communication/`
+- `https://v2.tauri.app/zh-cn/concept/inter-process-communication/brownfield/`
+- `https://v2.tauri.app/zh-cn/concept/inter-process-communication/isolation/`
+  并严格遵循以下设计规格:
+- **核心**:解释 Core Process (Rust) 与 WebView Process (Frontend) 的隔离模型。
+- **关键点**:Brownfield 模式与 Isolation 模式的区别与应用场景。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能深入理解 Tauri 架构原理。
+
+### 3. Security & Configuration (安全与配置层)
+
+- tauri-config ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-config 的 skills,必须参考
+- `https://v2.tauri.app/reference/config/`
+- `https://v2.tauri.app/security/csp/`
+  并严格遵循以下设计规格:
+- **边界**:`tauri.conf.json` 全生命周期管理。
+- **关键点**:解释 v2 中配置文件的结构变化(如插件配置位置、Android/iOS 配置段)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能正确管理项目配置。
+
+- tauri-security ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-security 的 skills,必须参考
+- `https://v2.tauri.app/security/capabilities/`
+- `https://v2.tauri.app/security/scope/`
+- `https://v2.tauri.app/security/acl/`
+  并严格遵循以下设计规格:
+- **边界**:Capabilities (ACL) 权限系统。
+- **v2 特性**:这是 v2 最核心的变化。必须指导用户如何配置 Scope(作用域),生成 `capabilities/default.json`,精确控制插件权限。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能构建安全合规的 Tauri 应用。
+
+- tauri-framework-security ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-framework-security 的 skills,必须参考
+- `https://v2.tauri.app/security/`
+- `https://v2.tauri.app/security/permissions/`
+- `https://v2.tauri.app/security/scope/`
+- `https://v2.tauri.app/security/capabilities/`
+- `https://v2.tauri.app/security/csp/`
+- `https://v2.tauri.app/security/http-headers/`
+- `https://v2.tauri.app/security/ecosystem/`
+- `https://v2.tauri.app/security/lifecycle/`
+- `https://v2.tauri.app/security/future/`
+- `https://v2.tauri.app/security/runtime-authority/`
+  并严格遵循以下设计规格:
+- **边界**:Tauri v2 安全模型与安全基线(Capabilities/Scope/CSP/Headers)。
+- **关键点**:以“最小权限”为原则,指导如何从业务需求反推 Capabilities 与 Scope,并避免默认放开高风险能力。
+- **输出**:给出可落地的安全检查清单(上线前的权限审计、CSP/Headers 验证、插件权限收敛)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能完成 Tauri 框架安全支撑相关工作。
+
+- tauri-app-plugin-permissions ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-plugin-permissions 的 skills,必须参考
+- `https://v2.tauri.app/learn/using-plugin-permissions/`
+- `https://v2.tauri.app/zh-cn/learn/security/using-plugin-permissions/`
+- `https://v2.tauri.app/learn/security/capabilities-for-windows-and-platforms/`
+- `https://v2.tauri.app/zh-cn/learn/security/capabilities-for-windows-and-platforms/`
+- `https://v2.tauri.app/learn/security/writing-plugin-permissions/`
+- `https://v2.tauri.app/zh-cn/learn/security/writing-plugin-permissions/`
+  并严格遵循以下设计规格:
+- **边界**:插件权限声明、Capabilities 生成与跨平台差异处理。
+- **关键点**:区分“插件提供的权限项”与“应用启用的能力”;强调 Windows/平台能力差异时的最小可用配置。
+- **输出**:可复用的权限模板(capabilities/default.json)与权限收敛策略。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能完成插件权限的安全配置工作。
+
+- tauri-framework-upgrade ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-framework-upgrade 的 skills,必须参考
+- `https://v2.tauri.app/start/migrate/`
+- `https://v2.tauri.app/start/migrate/from-tauri-1/`
+- `https://v2.tauri.app/start/migrate/from-tauri-2-beta/`
+  并严格遵循以下设计规格:
+- **边界**:从 Tauri v1 或 v2 beta 迁移到稳定的 Tauri v2。
+- **关键点**:识别破坏性变更(配置结构、插件体系、Capabilities 权限系统)并提供逐项迁移检查表。
+- **输出**:迁移后的可运行验证步骤(启动、IPC、关键插件能力、权限与 CSP)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能完成 Tauri 版本升级工作。
+
+### 4. Feature Plugins (特定能力插件层)
+
+- tauri-app-shell ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-shell 的 skills,必须参考
+- `https://v2.tauri.app/plugin/shell/`
+- `https://v2.tauri.app/zh-cn/plugin/shell/`
+  并严格遵循以下设计规格:
+- **关键点**:Shell 插件的高风险性质。必须强调在 Capabilities 中配置 `shell:allow-execute` 和 `shell:allow-open`,以及使用正则 (regex) 严格限制参数。
+- **功能**:生成子进程、打开外部链接。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能为应用添加安全的 Shell 执行能力。
+
+- tauri-app-single-instance ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-single-instance 的 skills,必须参考
+- `https://v2.tauri.app/plugin/single-instance/`
+- `https://v2.tauri.app/zh-cn/plugin/single-instance/`
+  并严格遵循以下设计规格:
+- **关键点**:在 Rust `main.rs` 或 `lib.rs` 中配置 `init` 闭包,处理后续实例启动时的参数传递(如 Deep Link 唤起)。
+- **功能**:防止多开、聚焦主窗口。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现单例运行模式。
+
+- tauri-app-sql ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-sql 的 skills,必须参考
+- `https://v2.tauri.app/plugin/sql/`
+- `https://v2.tauri.app/zh-cn/plugin/sql/`
+  并严格遵循以下设计规格:
+- **关键点**:支持 SQLite, MySQL, PostgreSQL。
+- **配置**:`tauri.conf.json` 中的 migrations 路径配置。
+- **功能**:前端直接执行 SQL(需谨慎配置 Capabilities 权限)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能集成数据库能力。
+
+- tauri-app-store ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-store 的 skills,必须参考
+- `https://v2.tauri.app/plugin/store/`
+- `https://v2.tauri.app/zh-cn/plugin/store/`
+  并严格遵循以下设计规格:
+- **关键点**:区分 `Store` (自动加载) 和 `LazyStore`。
+- **功能**:简单的 Key-Value 持久化存储(类似 `localStorage` 但持久化到磁盘文件)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现应用配置或轻量数据的持久化。
+
+- tauri-app-stronghold ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-stronghold 的 skills,必须参考
+- `https://v2.tauri.app/plugin/stronghold/`
+- `https://v2.tauri.app/zh-cn/plugin/stronghold/`
+  并严格遵循以下设计规格:
+- **关键点**:基于 IOTA Stronghold 的加密存储。
+- **功能**:安全存储敏感数据(如 API Keys, 密码),涉及 Snapshot 管理和 Client/Store 概念。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现高安全性的数据存储。
+
+- tauri-app-upload ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-upload 的 skills,必须参考
+- `https://v2.tauri.app/plugin/upload/`
+- `https://v2.tauri.app/zh-cn/plugin/upload/`
+  并严格遵循以下设计规格:
+- **功能**:高效的文件上传(从本地磁盘到 HTTP 服务器)。
+- **关键点**:支持进度回调(Progress Handler)和自定义 Headers。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现大文件上传功能。
+
+- tauri-app-websocket ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-websocket 的 skills,必须参考
+- `https://v2.tauri.app/plugin/websocket/`
+- `https://v2.tauri.app/zh-cn/plugin/websocket/`
+  并严格遵循以下设计规格:
+- **功能**:在 Rust 层建立 WebSocket 连接,绕过浏览器的 CORS 限制和 Mixed Content 限制。
+- **关键点**:生命周期管理(Connect, Message, Disconnect)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现实时通讯能力。
+
+- tauri-app-window-state ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-window-state 的 skills,必须参考
+- `https://v2.tauri.app/plugin/window-state/`
+- `https://v2.tauri.app/zh-cn/plugin/window-state/`
+  并严格遵循以下设计规格:
+- **功能**:自动保存和恢复窗口的大小、位置和最大化状态。
+- **关键点**:`StateFlags` 的使用,以及如何在应用启动时自动恢复状态。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能优化用户体验。
+
+- tauri-app-sidecar-nodejs ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-sidecar-nodejs 的 skills,必须参考
+- `https://v2.tauri.app/learn/sidecar-nodejs/`
+- `https://v2.tauri.app/zh-cn/learn/sidecar-nodejs/`
+  并严格遵循以下设计规格:
+- **边界**:在 Tauri 应用中以 sidecar 方式集成 Node.js 运行时。
+- **关键点**:处理跨平台打包、sidecar 可执行文件分发、启动/停止生命周期与权限门控(Capabilities)。
+- **输出**:提供端到端示例(Rust 启动 sidecar、前端触发、日志与错误处理、release 打包验证)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能为应用添加 sidecar-nodejs 能力。
+
+- tauri-app-splashscreen ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-splashscreen 的 skills,必须参考
+- `https://v2.tauri.app/learn/splashscreen/`
+- `https://v2.tauri.app/zh-cn/learn/splashscreen/`
+  并严格遵循以下设计规格:
+- **边界**:启动画面(Splashscreen)的配置与生命周期控制。
+- **关键点**:处理“前端资源加载慢/首次渲染”场景,避免白屏;明确何时隐藏 Splashscreen 与显示主窗口。
+- **输出**:提供跨平台一致的启动体验实现方案(含常见错误排查)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能为应用添加启动画面能力。
+
+- tauri-app-system-tray ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-system-tray 的 skills,必须参考
+- `https://v2.tauri.app/learn/system-tray/`
+- `https://v2.tauri.app/zh-cn/learn/system-tray/`
+  并严格遵循以下设计规格:
+- **边界**:实现系统托盘/状态栏图标的交互模式(显示/隐藏窗口、菜单、通知等)。
+- **关键点**:处理 macOS/Windows/Linux 的行为差异与用户习惯(关闭窗口 vs 退出应用)。
+- **安全门控**:涉及打开链接/执行命令/读写文件等能力时,必须触发 `tauri-security` 收敛权限。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 system-tray 能力。
+
+- tauri-app-window-menu ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-window-menu 的 skills,必须参考
+- `https://v2.tauri.app/learn/window-menu/`
+- `https://v2.tauri.app/zh-cn/learn/window-menu/`
+  并严格遵循以下设计规格:
+- **边界**:窗口菜单(Menu)定义、事件处理与平台差异适配。
+- **关键点**:菜单项与命令分离(Command/Handler),并提供可测试的事件分发策略。
+- **输出**:示例包含常用菜单(File/Edit/View/Help)与快捷键绑定。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 window-menu 能力。
+
+- tauri-app-autostart ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-autostart 的 skills,必须参考
+- `https://v2.tauri.app/plugin/autostart/`
+- `https://v2.tauri.app/zh-cn/plugin/autostart/`
+  并严格遵循以下设计规格:
+- **边界**:配置应用开机自启动与禁用自启动的用户控制。
+- **关键点**:解释不同平台的自启动机制差异,并确保提供可回滚与可观测的配置方式。
+- **输出**:给出最小可用实现(启用/禁用 API、配置项、权限与发布验证)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 autostart 能力。
+
+- tauri-app-barcode-scanner ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-barcode-scanner 的 skills,必须参考
+- `https://v2.tauri.app/plugin/barcode-scanner/`
+- `https://v2.tauri.app/zh-cn/plugin/barcode-scanner/`
+  并严格遵循以下设计规格:
+- **边界**:在支持的平台上集成条码/二维码扫描能力。
+- **关键点**:处理权限申请、扫描结果回调与错误场景(无摄像头/权限拒绝)。
+- **输出**:提供前端触发与 Rust 侧能力封装的端到端示例。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 Barcode Scanner 能力。
+
+- tauri-app-biometric ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-biometric 的 skills,必须参考
+- `https://v2.tauri.app/plugin/biometric/`
+- `https://v2.tauri.app/zh-cn/plugin/biometric/`
+  并严格遵循以下设计规格:
+- **边界**:生物识别(指纹/Face ID 等)认证流程集成。
+- **关键点**:强调“认证”与“加密存储”的职责分离;敏感数据仍需配合 stronghold 等安全存储。
+- **输出**:提供统一的认证 API 与失败重试/降级策略。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 Biometric 能力。
+
+- tauri-app-cli ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-cli 的 skills,必须参考
+- `https://v2.tauri.app/plugin/cli/`
+- `https://v2.tauri.app/zh-cn/plugin/cli/`
+  并严格遵循以下设计规格:
+- **边界**:为应用提供命令行参数解析与处理能力。
+- **关键点**:定义参数 schema、处理启动参数与二次唤起参数(可结合 single-instance)。
+- **输出**:提供“参数 -> 业务命令 -> 窗口行为”联动示例。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 CLI 能力。
+
+- tauri-app-clipboard ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-clipboard 的 skills,必须参考
+- `https://v2.tauri.app/plugin/clipboard/`
+- `https://v2.tauri.app/zh-cn/plugin/clipboard/`
+  并严格遵循以下设计规格:
+- **边界**:读写系统剪贴板(文本/必要时扩展到图片等类型)。
+- **关键点**:限制剪贴板能力的滥用风险(权限收敛、仅在用户操作触发时访问)。
+- **输出**:提供常用用例(复制/粘贴/监听变更)的实现范式。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 clipboard 能力。
+
+- tauri-app-deep-linking ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-deep-linking 的 skills,必须参考
+- `https://v2.tauri.app/plugin/deep-linking/`
+- `https://v2.tauri.app/zh-cn/plugin/deep-linking/`
+  并严格遵循以下设计规格:
+- **边界**:注册并处理应用深度链接(URL Scheme/Universal Links 等)。
+- **关键点**:与 single-instance 联动,确保二次唤起参数能可靠传递到前端路由/业务逻辑。
+- **安全门控**:对外部输入做严格校验与白名单限制,防止注入与越权。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 deep-linking 能力。
+
+- tauri-app-dialog ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-dialog 的 skills,必须参考
+- `https://v2.tauri.app/plugin/dialog/`
+- `https://v2.tauri.app/zh-cn/plugin/dialog/`
+  并严格遵循以下设计规格:
+- **边界**:原生对话框能力(消息提示、确认框、文件选择等)。
+- **关键点**:统一封装对话框调用,避免在业务代码中散落平台差异;处理异步与取消场景。
+- **输出**:提供可复用的对话框服务层 API 设计(前端调用与 Rust 侧支持)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 dialog 能力。
+
+- tauri-app-file-system ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-file-system 的 skills,必须参考
+- `https://v2.tauri.app/plugin/file-system/`
+- `https://v2.tauri.app/zh-cn/plugin/file-system/`
+  并严格遵循以下设计规格:
+- **边界**:文件系统读写、目录访问与路径权限控制。
+- **关键点**:必须结合 Scope/Capabilities 精确限制可访问目录与文件模式,避免“任意路径读写”。
+- **输出**:提供常用用例(选择文件、读写配置、导入导出)的安全实现方案。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 file-system 能力。
+
+- tauri-app-geolocation ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-geolocation 的 skills,必须参考
+- `https://v2.tauri.app/plugin/geolocation/`
+- `https://v2.tauri.app/zh-cn/plugin/geolocation/`
+  并严格遵循以下设计规格:
+- **边界**:获取地理位置与相关权限管理。
+- **关键点**:处理权限请求、精度/频率控制与隐私合规(最小必要、可关闭)。
+- **输出**:提供统一的定位 API 与错误处理(权限拒绝/不可用/超时)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 geolocation 能力。
+
+- tauri-app-global-shortcut ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-global-shortcut 的 skills,必须参考
+- `https://v2.tauri.app/plugin/global-shortcut/`
+- `https://v2.tauri.app/zh-cn/plugin/global-shortcut/`
+  并严格遵循以下设计规格:
+- **边界**:注册全局快捷键并在应用后台响应。
+- **关键点**:处理快捷键冲突、平台差异与用户可配置;确保退出应用时释放注册。
+- **输出**:提供“快捷键 -> 聚焦窗口/触发命令”的完整实现示例。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 global-shortcut 能力。
+
+- tauri-app-haptics ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-haptics 的 skills,必须参考
+- `https://v2.tauri.app/plugin/haptics/`
+- `https://v2.tauri.app/zh-cn/plugin/haptics/`
+  并严格遵循以下设计规格:
+- **边界**:触觉反馈能力(主要面向移动端与支持的设备)。
+- **关键点**:提供可降级策略(不支持时静默失败或替代提示),并避免过度打扰用户。
+- **输出**:给出典型交互场景(按钮点击/成功失败提示)的实现范式。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 haptics 能力。
+
+- tauri-app-http-client ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-http-client 的 skills,必须参考
+- `https://v2.tauri.app/plugin/http-client/`
+- `https://v2.tauri.app/zh-cn/plugin/http-client/`
+  并严格遵循以下设计规格:
+- **边界**:在 Rust 侧发起 HTTP 请求(可绕过部分 WebView 限制),并将结果安全暴露给前端。
+- **关键点**:处理证书、代理、超时、重试与敏感信息保护;避免将任意 URL 请求能力暴露给不受信任输入。
+- **安全门控**:结合 Capabilities/Scope 为请求域名与方法建立白名单。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 http-client 能力。
+
+- tauri-app-localhost ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-localhost 的 skills,必须参考
+- `https://v2.tauri.app/plugin/localhost/`
+- `https://v2.tauri.app/zh-cn/plugin/localhost/`
+  并严格遵循以下设计规格:
+- **边界**:本地回环服务访问与相关配置。
+- **关键点**:区分开发期 localhost 与生产期本地服务(sidecar/server)模式;避免扩大网络访问面。
+- **输出**:提供可审计的配置与最小权限访问方案。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 localhost 能力。
+
+- tauri-app-logging ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-logging 的 skills,必须参考
+- `https://v2.tauri.app/plugin/logging/`
+- `https://v2.tauri.app/zh-cn/plugin/logging/`
+  并严格遵循以下设计规格:
+- **边界**:统一日志采集、过滤、输出与持久化(开发与生产)。
+- **关键点**:避免日志泄露敏感信息;提供分级(debug/info/warn/error)与可开关的诊断模式。
+- **输出**:给出日志定位与上报的最佳实践(含 release 构建排障路径)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 logging 能力。
+
+- tauri-app-nfc ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-nfc 的 skills,必须参考
+- `https://v2.tauri.app/plugin/nfc/`
+- `https://v2.tauri.app/zh-cn/plugin/nfc/`
+  并严格遵循以下设计规格:
+- **边界**:NFC 读写与会话管理(适用的平台与设备)。
+- **关键点**:权限处理、用户交互提示与数据格式校验,避免将原始数据直接信任用于业务决策。
+- **输出**:提供典型用例(读标签/写标签/一次性会话)的实现示例。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 nfc 能力。
+
+- tauri-app-notification ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-notification 的 skills,必须参考
+- `https://v2.tauri.app/plugin/notification/`
+- `https://v2.tauri.app/zh-cn/plugin/notification/`
+  并严格遵循以下设计规格:
+- **边界**:本地通知/系统通知的发送与交互回调。
+- **关键点**:处理权限请求、通知点击事件与深链联动;避免滥发通知。
+- **输出**:提供统一通知服务与跨平台一致的行为定义。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 notification 能力。
+
+- tauri-app-opener ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-opener 的 skills,必须参考
+- `https://v2.tauri.app/plugin/opener/`
+- `https://v2.tauri.app/zh-cn/plugin/opener/`
+  并严格遵循以下设计规格:
+- **边界**:打开外部链接/文件/目录等系统级“打开”能力。
+- **关键点**:对可打开的协议与路径做白名单限制;避免成为钓鱼跳转与本地敏感文件泄露的入口。
+- **输出**:提供安全的 opener 封装(仅允许 http/https、受控目录等)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 opener 能力。
+
+- tauri-app-os-info ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-os-info 的 skills,必须参考
+- `https://v2.tauri.app/plugin/os-info/`
+- `https://v2.tauri.app/zh-cn/plugin/os-info/`
+  并严格遵循以下设计规格:
+- **边界**:采集系统信息(版本、架构等)用于诊断与兼容性判断。
+- **关键点**:明确哪些信息可上报、如何脱敏;避免采集与业务无关的敏感字段。
+- **输出**:提供“系统信息 -> 诊断报告/兼容性策略”的实现示例。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 os-info 能力。
+
+- tauri-app-persisted-scope ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-persisted-scope 的 skills,必须参考
+- `https://v2.tauri.app/plugin/persisted-scope/`
+- `https://v2.tauri.app/zh-cn/plugin/persisted-scope/`
+  并严格遵循以下设计规格:
+- **边界**:将权限 scope 持久化到本地并在合适时机恢复/更新。
+- **关键点**:避免“永久放权”;提供权限过期、撤销与重新授权机制。
+- **输出**:给出与 capabilities/scope 配套的最佳实践与落地示例。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 persisted-scope 能力。
+
+- tauri-app-positioner ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-positioner 的 skills,必须参考
+- `https://v2.tauri.app/plugin/positioner/`
+- `https://v2.tauri.app/zh-cn/plugin/positioner/`
+  并严格遵循以下设计规格:
+- **边界**:窗口定位与对齐策略(贴边、跟随托盘、屏幕多显示器适配)。
+- **关键点**:处理多屏、缩放比例与不同平台窗口坐标系差异。
+- **输出**:提供常见 UI 模式(弹出面板/下拉窗口)的定位实现示例。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 positioner 能力。
+
+- tauri-app-process ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-process 的 skills,必须参考
+- `https://v2.tauri.app/plugin/process/`
+- `https://v2.tauri.app/zh-cn/plugin/process/`
+  并严格遵循以下设计规格:
+- **边界**:进程级能力(获取/管理当前进程信息或相关操作,依平台支持而定)。
+- **关键点**:避免暴露高风险进程控制能力给不可信输入;所有能力必须受 Capabilities 约束。
+- **输出**:提供“受控能力暴露”的设计模板(Rust 端封装 + 前端受限调用)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现 process 能力。
+
+- tauri-app-wasm ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-wasm 的 skills,必须参考
+- `https://crates.io/crates/tauri-wasm`
+- `https://v2.tauri.app/develop/calling-rust/#wasm`
+- `https://github.com/p1mo/tauri-wasm`
+- `https://zhuanlan.zhihu.com/p/533025312`
+- `https://blog.csdn.net/qq_63401240/article/details/147340217`
+  并严格遵循以下设计规格:
+- **功能**:在前端直接运行编译为 WASM 的 Rust 代码。
+- **关键点**:区别于 Tauri 的 IPC 模式,WASM 是纯前端运行,适合高计算量但不涉及系统 API 的任务。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现高性能前端计算。
+
+### 5. Mobile & Distribution (移动端与发布层)
+
+- tauri-mobile ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-mobile 的 skills,必须参考
+- `https://v2.tauri.app/mobile/`
+- `https://v2.tauri.app/mobile/development/`
+  并严格遵循以下设计规格:
+- **边界**:移动端(Android/iOS)特有的初始化与调试。
+- **关键点**:指导修改 Bundle ID 以符合移动端规范,以及前端响应式适配建议。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能进行移动端开发。
+
+- tauri-build ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-build 的 skills,必须参考
+- `https://v2.tauri.app/distribute/`
+- `https://v2.tauri.app/distribute/app-store/`
+- `https://v2.tauri.app/distribute/appimage/`
+- `https://v2.tauri.app/distribute/aur/`
+- `https://v2.tauri.app/distribute/crabnebula-cloud/`
+- `https://v2.tauri.app/distribute/debian/`
+- `https://v2.tauri.app/distribute/dmg/`
+- `https://v2.tauri.app/distribute/google-play/`
+- `https://v2.tauri.app/distribute/macos-application-bundle/`
+- `https://v2.tauri.app/distribute/microsoft-store/`
+- `https://v2.tauri.app/distribute/rpm/`
+- `https://v2.tauri.app/distribute/snapcraft/`
+- `https://v2.tauri.app/distribute/windows-installer/`
+- `https://v2.tauri.app/distribute/sign/macos/`
+- `https://v2.tauri.app/distribute/sign/windows/`
+- `https://v2.tauri.app/distribute/sign/linux/`
+- `https://v2.tauri.app/distribute/sign/ios/`
+- `https://v2.tauri.app/distribute/sign/android/`
+- `https://v2.tauri.app/distribute/pipelines/crabnebula-cloud/`
+- `https://v2.tauri.app/distribute/pipelines/github/`
+  并严格遵循以下设计规格:
+- **边界**:生产环境构建、代码签名、安装包生成。
+- **关键点**:区分 Debug 与 Release 构建,解释不同平台安装包格式(DMG, MSI, DEB, APK)。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现自动化构建发布。
+
+- tauri-app-updater ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-app-updater 的 skills,必须参考
+- `https://v2.tauri.app/plugin/updater/`
+- `https://v2.tauri.app/zh-cn/plugin/updater/`
+  并严格遵循以下设计规格:
+- **功能**:配置 OTA 更新机制。
+- **关键点**:生成签名密钥对 (`tauri signer generate`) 的流程,配置更新服务器 URL,以及在应用中实现自动检查更新的逻辑。
+严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型基于此技能实现应用自更新功能。
+
+### 6. Orchestration (编排层)
+
+- tauri-orchestrator ✅
+
+遵循 Agent skills 规范: `https://support.claude.com/zh-CN/articles/12512198-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E8%87%AA%E5%AE%9A%E4%B9%89-skills` 和 `https://agentskills.io/what-are-skills`
+参考 /Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid,创建一个名称为 tauri-orchestrator 的 skills,必须参考
+- `https://v2.tauri.app/concept/architecture/`
+- 上述所有 Skill Units
+  并严格遵循以下设计规格:
+- **角色**:Tauri Tech Lead(技术负责人)。
+- **边界**:编排与规划,不直接替代具体 Skill 的落地实现。
+- **功能**:接收模糊的高级需求,输出完整的开发计划和 Skill 调用链。
+- **输出**:给出可执行的任务树(含依赖、顺序与验收点),并指明需要调用的 Skill Units。
+- **核心逻辑**:
+1.  **场景分析**:识别需求阶段(从零开始 vs 功能迭代)。
+2.  **任务拆解**:将大需求拆解为 `tauri-scaffold` -> `tauri-app-shell` -> `tauri-ipc` 等原子步骤。
+3.  **依赖管理**:强制检查前置条件(如:调用 `tauri-build` 前必须先调用 `tauri-config` 配置 ID)。
+4.  **安全门控**:一旦检测到插件安装,自动触发 `tauri-security` 任务以配置权限。
+  严格参考
+- 官方示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/skill-creator 
+- 个人示例:/Users/wandl/workspaces/workspace-partme-ai/full-stack-skills/skills/mermaid 
+SKILL.md 内容规划,结构清晰,触发逻辑清晰,流程完善,一一对应,可以指导 大模型作为“总指挥”协调调用所有子技能完成复杂的开发任务。

+ 202 - 0
skills/ascii-ansi-colorizer/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 59 - 0
skills/ascii-ansi-colorizer/SKILL.md

@@ -0,0 +1,59 @@
+---
+name: ascii-ansi-colorizer
+description: Add an ANSI color layer to existing ASCII/plain-text output (gradient/rainbow/highlights) with alignment-safe rules and a required no-color fallback.
+license: Complete terms in LICENSE.txt
+dependencies:
+  - python>=3.8
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-ansi-colorizer`.
+
+**Trigger phrases include:**
+- "ascii-ansi-colorizer"
+- "use ascii-ansi-colorizer"
+- "用 ascii-ansi-colorizer 给 ASCII 上色"
+- "使用 ascii-ansi-colorizer 做 ANSI 渐变/彩虹"
+
+## Boundary
+- This skill only adds color to existing text. It does not generate the ASCII art itself (pair with `ascii-cli-logo-banner` if needed).
+- Required outputs: `coloredText` + `plainTextFallback`.
+- ANSI must not break alignment: do not colorize spaces by default; colorize visible characters only.
+
+## How to use this skill
+### Inputs
+- textOrAscii (required)
+- palette (rainbow | gradient | brandColors)
+- direction (leftToRight | topToBottom, default leftToRight)
+- colorDepth (ansi16 | ansi256 | truecolor, default ansi256)
+- scope (logoOnly | highlightsOnly | fullText, default logoOnly)
+
+### Outputs (required)
+- coloredText: ANSI-colored output
+- plainTextFallback: no-color fallback (identical content, no ANSI)
+- compatNotes: copy/paste and redirection guidance (NO_COLOR / --no-color suggestions)
+
+### Steps
+1. Pick `colorDepth` (default: ansi256).
+2. Choose a stable coloring strategy:
+   - Column-wise gradients (leftToRight) are usually the safest
+   - Colorize non-space characters only
+3. Output both `coloredText` and `plainTextFallback`.
+4. Provide no-color guidance (semantic suggestions): `NO_COLOR` / `--no-color`.
+
+## Script
+- `scripts/colorize.py`: apply ANSI 256 gradient or rainbow to stdin
+
+## Examples
+- `examples/gradient.md`
+
+## Quality checklist
+1. Removing ANSI keeps the same readable content (`plainTextFallback`).
+2. Alignment does not change after coloring.
+3. Colors should not overpower the informational lines.
+
+## Keywords
+**English:** ascii-ansi-colorizer, ansi, color, gradient, rainbow, terminal, no-color, plain text, ascii
+**中文:** ascii-ansi-colorizer, ANSI, 上色, 渐变, 彩虹, 终端, 无色回退, 纯文本, ASCII

+ 24 - 0
skills/ascii-ansi-colorizer/examples/gradient.md

@@ -0,0 +1,24 @@
+# ascii-ansi-colorizer:渐变示例
+
+## Input
+
+```
+PARTME
+AI CLI
+```
+
+## Script usage
+
+```bash
+python3 scripts/colorize.py --mode gradient --direction lr < ./input.txt
+```
+
+## Output(示意,带 ANSI)
+
+```
+\x1b[38;5;33mP\x1b[0m\x1b[38;5;39mA\x1b[0m\x1b[38;5;45mR\x1b[0m...
+```
+
+## Notes
+- 真实终端中会显示为渐变色文字
+- 若重定向到文件,建议禁用颜色并输出无色版本

+ 103 - 0
skills/ascii-ansi-colorizer/scripts/colorize.py

@@ -0,0 +1,103 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+import sys
+from dataclasses import dataclass
+from typing import Iterable, Sequence
+
+
+@dataclass(frozen=True)
+class Options:
+    """ANSI 上色参数。"""
+
+    mode: str
+    direction: str
+    start: int
+    end: int
+    keep_spaces: bool
+
+
+def parse_args(argv: Sequence[str] | None = None) -> Options:
+    """解析命令行参数。"""
+
+    p = argparse.ArgumentParser(description="ANSI colorize text (gradient/rainbow). Reads stdin, writes stdout.")
+    p.add_argument("--mode", choices=["gradient", "rainbow"], default="gradient")
+    p.add_argument("--direction", choices=["lr", "tb"], default="lr", help="lr=left->right, tb=top->bottom")
+    p.add_argument("--start", type=int, default=33, help="ANSI 256 start color (0-255)")
+    p.add_argument("--end", type=int, default=129, help="ANSI 256 end color (0-255)")
+    p.add_argument("--keep-spaces", action="store_true", help="Colorize spaces too (not recommended)")
+    ns = p.parse_args(argv)
+    return Options(
+        mode=ns.mode,
+        direction=ns.direction,
+        start=max(0, min(255, ns.start)),
+        end=max(0, min(255, ns.end)),
+        keep_spaces=bool(ns.keep_spaces),
+    )
+
+
+def _ansi_fg(code: int) -> str:
+    """生成 ANSI 256 前景色控制序列。"""
+
+    return f"\x1b[38;5;{code}m"
+
+
+def _reset() -> str:
+    """生成 ANSI 重置序列。"""
+
+    return "\x1b[0m"
+
+
+def _lerp(a: int, b: int, t: float) -> int:
+    """线性插值计算 ANSI 颜色码。"""
+
+    return int(round(a + (b - a) * t))
+
+
+def colorize_lines(lines: Sequence[str], opt: Options) -> Iterable[str]:
+    """对文本行应用 ANSI 上色。"""
+
+    reset = _reset()
+    if not lines:
+        return []
+
+    max_len = max(len(l.rstrip("\n")) for l in lines) or 1
+    total_lines = len(lines)
+
+    def pick_color(x: int, y: int) -> int:
+        if opt.mode == "rainbow":
+            # 使用 256 色中较饱和的一段
+            base = [196, 202, 208, 214, 220, 46, 51, 39, 27, 93, 129]
+            idx = (x if opt.direction == "lr" else y) % len(base)
+            return base[idx]
+        if opt.direction == "tb":
+            t = 0.0 if total_lines <= 1 else y / (total_lines - 1)
+        else:
+            t = 0.0 if max_len <= 1 else x / (max_len - 1)
+        return _lerp(opt.start, opt.end, t)
+
+    for y, raw in enumerate(lines):
+        line = raw.rstrip("\n")
+        out = []
+        for x, ch in enumerate(line):
+            if ch == " " and not opt.keep_spaces:
+                out.append(ch)
+                continue
+            code = pick_color(x, y)
+            out.append(_ansi_fg(code) + ch + reset)
+        yield "".join(out)
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+    """程序入口:从 stdin 读取并上色输出。"""
+
+    opt = parse_args(argv)
+    data = sys.stdin.read().splitlines()
+    for line in colorize_lines(data, opt):
+        print(line)
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 202 - 0
skills/ascii-cli-logo-banner-figletjs/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 63 - 0
skills/ascii-cli-logo-banner-figletjs/SKILL.md

@@ -0,0 +1,63 @@
+---
+name: ascii-cli-logo-banner-figletjs
+description: Generate TAAG/FIGlet-style ASCII art banners using figlet.js (FIGfont spec), with layout controls (horizontal/vertical layout, width, whitespaceBreak) and optional ANSI 256 coloring.
+license: Complete terms in LICENSE.txt
+dependencies:
+  - node>=18
+  - npm
+  - figlet (npm, powered by figlet.js)
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-cli-logo-banner-figletjs`.
+
+**Trigger phrases include:**
+- "ascii-cli-logo-banner-figletjs"
+- "use ascii-cli-logo-banner-figletjs"
+- "用 ascii-cli-logo-banner-figletjs 生成 TAAG/FIGlet 大字"
+- "使用 ascii-cli-logo-banner-figletjs 调 horizontalLayout / verticalLayout"
+
+## Boundary
+- Output copy-pastable text and layout rules only. Do not modify project code.
+- FIGlet/TAAG style is driven by FIGfont (.flf) rendering and layout “smushing/kerning” options.
+- ANSI coloring is optional and MUST not break alignment (spaces are not colorized).
+- Dependency note: `figlet` npm package is commonly used as the Node interface and is powered by `figlet.js`.
+
+## How to use this skill
+### Inputs (recommended)
+- brand (required)
+- width (default 80; if `< 60` use compact mode)
+- font (default Standard)
+- horizontalLayout (default | full | fitted | controlled smushing | universal smushing)
+- verticalLayout (default | full | fitted | controlled smushing | universal smushing)
+- whitespaceBreak (true|false, default true)
+- slogan/hint (optional; centered lines under the logo)
+- center (default true)
+- rule (default true; set false for hero output)
+- version/repo/docs/author (optional; only used when `rule=true`)
+- colorMode (none | ansi256, default none; logo only)
+- colorStart/colorEnd (0-255, defaults 33/129; only when `colorMode=ansi256`)
+
+### Outputs (required)
+- bannerPlain: banner text (no-color)
+- coloredText: when `colorMode=ansi256`, provide colored logo output
+- plainTextFallback: when colored, also provide a no-color fallback (same layout)
+
+## Script
+- `scripts/figlet_banner.mjs`
+
+## Examples
+- `examples/taag-figlet.md`
+- `examples/color-ansi256.md`
+
+## Quality checklist
+1. Layout options are honored (horizontal/vertical layout)
+2. 80-column output does not wrap; no trailing spaces
+3. Color mode does not break alignment (spaces are not colorized)
+4. Never prints secrets (tokens, internal URLs, personal data)
+
+## Keywords
+**English:** ascii-cli-logo-banner-figletjs, figlet, figlet.js, FIGfont, taag, ascii, banner, smushing, kerning, ansi256
+**中文:** ascii-cli-logo-banner-figletjs, FIGlet 大字, TAAG, FIGfont 字体, 横向布局, 纵向布局, ANSI256 上色

+ 21 - 0
skills/ascii-cli-logo-banner-figletjs/examples/color-ansi256.md

@@ -0,0 +1,21 @@
+# ascii-cli-logo-banner-figletjs: ANSI color (ansi256)
+
+This example colorizes the logo using ANSI 256 colors while keeping spacing alignment safe (spaces are not colorized).
+
+## Node (FIGlet/TAAG-like)
+
+```bash
+node scripts/figlet_banner.mjs \
+  --brand "SPECIFY" \
+  --width 80 \
+  --font "Standard" \
+  --slogan "GitHub Spec Kit - Spec-Driven Development Toolkit" \
+  --hint "Run 'specify --help' for usage information" \
+  --no-rule \
+  --colorMode ansi256 \
+  --colorStart 46 \
+  --colorEnd 196
+```
+
+## Notes
+- If output is redirected to a file, consider disabling color (`--colorMode none`) to keep raw text clean.

+ 30 - 0
skills/ascii-cli-logo-banner-figletjs/examples/taag-figlet.md

@@ -0,0 +1,30 @@
+# ascii-cli-logo-banner-figletjs: FIGlet/TAAG-style output (via figlet.js options)
+
+This example shows how to reproduce TAAG-like text output by using the `figlet` npm package (powered by `figlet.js`).
+
+## Install dependency
+
+```bash
+npm install figlet
+```
+
+## Run
+
+```bash
+node scripts/figlet_banner.mjs \
+  --brand "PartmeAI" \
+  --version "1.2.3" \
+  --repo "https://github.com/partme-ai/partme-cli" \
+  --width 80 \
+  --font "Ghost" \
+  --slogan "GitHub Spec Kit - Spec-Driven Development Toolkit" \
+  --hint "Run 'specify --help' for usage information" \
+  --no-rule \
+  --horizontalLayout "default" \
+  --verticalLayout "default" \
+  --whitespaceBreak true
+```
+
+## Notes
+- `horizontalLayout` and `verticalLayout` match the common FIGlet layout options (default/full/fitted/controlled smushing/universal smushing).
+- For narrow terminals (`width < 60`), the script prints a compact fallback banner (no big-letter logo).

+ 313 - 0
skills/ascii-cli-logo-banner-figletjs/scripts/figlet_banner.mjs

@@ -0,0 +1,313 @@
+#!/usr/bin/env node
+import process from "node:process";
+import path from "node:path";
+import { createRequire } from "node:module";
+import { fileURLToPath } from "node:url";
+
+process.stdout.on("error", (err) => {
+  if (err && err.code === "EPIPE") {
+    process.exit(0);
+  }
+  throw err;
+});
+
+function parseArgs(argv) {
+  const args = {
+    brand: null,
+    version: null,
+    repo: null,
+    docs: null,
+    author: null,
+    width: 80,
+    slogan: null,
+    hint: null,
+    font: "Standard",
+    horizontalLayout: "default",
+    verticalLayout: "default",
+    whitespaceBreak: true,
+    center: true,
+    rule: true,
+    colorMode: "none",
+    colorStart: 33,
+    colorEnd: 129,
+  };
+
+  for (let i = 0; i < argv.length; i++) {
+    const a = argv[i];
+    const next = argv[i + 1];
+    if (a === "--brand" && next) {
+      args.brand = next;
+      i++;
+      continue;
+    }
+    if (a === "--version" && next) {
+      args.version = next;
+      i++;
+      continue;
+    }
+    if (a === "--repo" && next) {
+      args.repo = next;
+      i++;
+      continue;
+    }
+    if (a === "--docs" && next) {
+      args.docs = next;
+      i++;
+      continue;
+    }
+    if (a === "--author" && next) {
+      args.author = next;
+      i++;
+      continue;
+    }
+    if (a === "--width" && next) {
+      args.width = Number.parseInt(next, 10);
+      i++;
+      continue;
+    }
+    if (a === "--slogan" && next) {
+      args.slogan = next;
+      i++;
+      continue;
+    }
+    if (a === "--hint" && next) {
+      args.hint = next;
+      i++;
+      continue;
+    }
+    if (a === "--colorMode" && next) {
+      args.colorMode = next;
+      i++;
+      continue;
+    }
+    if (a === "--colorStart" && next) {
+      args.colorStart = Number.parseInt(next, 10);
+      i++;
+      continue;
+    }
+    if (a === "--colorEnd" && next) {
+      args.colorEnd = Number.parseInt(next, 10);
+      i++;
+      continue;
+    }
+    if (a === "--font" && next) {
+      args.font = next;
+      i++;
+      continue;
+    }
+    if (a === "--horizontalLayout" && next) {
+      args.horizontalLayout = next;
+      i++;
+      continue;
+    }
+    if (a === "--verticalLayout" && next) {
+      args.verticalLayout = next;
+      i++;
+      continue;
+    }
+    if (a === "--whitespaceBreak" && next) {
+      args.whitespaceBreak = next === "true";
+      i++;
+      continue;
+    }
+    if (a === "--center") {
+      args.center = true;
+      continue;
+    }
+    if (a === "--no-center") {
+      args.center = false;
+      continue;
+    }
+    if (a === "--rule") {
+      args.rule = true;
+      continue;
+    }
+    if (a === "--no-rule") {
+      args.rule = false;
+      continue;
+    }
+    if (a === "--help" || a === "-h") {
+      args.help = true;
+      continue;
+    }
+  }
+  return args;
+}
+
+function hr(width, ch = "-") {
+  const c = (ch && ch.length > 0 ? ch[0] : "-");
+  return c.repeat(Math.max(0, width));
+}
+
+function centerLine(line, width) {
+  const s = String(line ?? "").replace(/\n/g, "").trimEnd();
+  if (width <= 0) return "";
+  if (s.length >= width) return s.slice(0, width).trimEnd();
+  const padLeft = Math.floor((width - s.length) / 2);
+  return " ".repeat(padLeft) + s;
+}
+
+function ansiFg256(code) {
+  return `\x1b[38;5;${code}m`;
+}
+
+function ansiReset() {
+  return "\x1b[0m";
+}
+
+function lerp(a, b, t) {
+  return Math.round(a + (b - a) * t);
+}
+
+function colorizeAnsi256Line(line, start, end) {
+  const reset = ansiReset();
+  const s = String(line ?? "");
+  const maxLen = Math.max(1, s.length);
+  let out = "";
+  for (let x = 0; x < s.length; x++) {
+    const ch = s[x];
+    if (ch === " ") {
+      out += ch;
+      continue;
+    }
+    const t = maxLen <= 1 ? 0 : x / (maxLen - 1);
+    const code = lerp(start, end, t);
+    out += ansiFg256(code) + ch + reset;
+  }
+  return out;
+}
+
+function compactBanner(args) {
+  const title = args.version ? `${args.brand} (v${args.version})` : args.brand;
+  const lines = [title.slice(0, args.width)];
+  if (args.slogan) lines.push(centerLine(args.slogan, args.width));
+  if (args.hint) lines.push(centerLine(args.hint, args.width));
+  if (args.rule) {
+    lines.push(hr(args.width, "-"));
+    if (args.repo) lines.push(`Repo: ${args.repo}`.slice(0, args.width));
+    if (args.docs) lines.push(`Docs: ${args.docs}`.slice(0, args.width));
+    if (args.author) lines.push(`Author: ${args.author}`.slice(0, args.width));
+  }
+  return lines.join("\n").trimEnd();
+}
+
+async function loadFiglet() {
+  try {
+    const mod = await import("figlet");
+    return mod.default ?? mod;
+  } catch {
+    const require = createRequire(import.meta.url);
+    const here = path.dirname(fileURLToPath(import.meta.url));
+    const repoRoot = path.resolve(here, "../../../..");
+    const candidatePaths = [
+      process.cwd(),
+      repoRoot,
+      path.join(repoRoot, "partme-cli-ts"),
+      here,
+    ];
+    try {
+      const resolved = require.resolve("figlet", { paths: candidatePaths });
+      const mod = require(resolved);
+      return mod.default ?? mod;
+    } catch {
+      throw new Error(
+        "Missing dependency: figlet (npm). Install with: npm install figlet (or provide it via partme-cli-ts/node_modules)."
+      );
+    }
+  }
+}
+
+async function main() {
+  const args = parseArgs(process.argv.slice(2));
+  if (args.help || !args.brand) {
+    process.stdout.write(
+      [
+        "Usage:",
+        "  node scripts/figlet_banner.mjs --brand <NAME> [options]",
+        "",
+        "Options:",
+        "  --version <v>             Optional version",
+        "  --repo <url>              Repo URL",
+        "  --docs <url>              Docs URL",
+        "  --author <name>           Author/team",
+        "  --width <n>               Banner width (default 80)",
+        "  --slogan <text>           Centered slogan line under the logo",
+        "  --hint <text>             Centered hint line under the slogan",
+        "  --no-rule                 Hero output (logo + centered lines only)",
+        "  --no-center               Do not center-align logo/slogan/hint",
+        "  --colorMode <mode>        none|ansi256 (logo only)",
+        "  --colorStart <n>          ANSI 256 start color (0-255, default 33)",
+        "  --colorEnd <n>            ANSI 256 end color (0-255, default 129)",
+        "  --font <name>             FIGlet font (default Standard)",
+        "  --horizontalLayout <val>  default|full|fitted|controlled smushing|universal smushing",
+        "  --verticalLayout <val>    default|full|fitted|controlled smushing|universal smushing",
+        "  --whitespaceBreak <bool>  true|false (default true)",
+        "",
+        "Install dependency:",
+        "  npm install figlet",
+        "",
+      ].join("\n")
+    );
+    process.exit(args.brand ? 0 : 1);
+  }
+
+  const width = Number.isFinite(args.width) ? Math.max(10, args.width) : 80;
+  args.width = width;
+  if (width < 60) {
+    process.stdout.write(compactBanner(args) + "\n");
+    return;
+  }
+
+  const figlet = await loadFiglet();
+  const logo = figlet.textSync(args.brand, {
+    font: args.font,
+    horizontalLayout: args.horizontalLayout,
+    verticalLayout: args.verticalLayout,
+    width: args.width,
+    whitespaceBreak: args.whitespaceBreak,
+  });
+
+  const lines = [];
+  const rawLogoLines = logo.trimEnd().split("\n");
+  const colorMode = args.colorMode === "ansi256" ? "ansi256" : "none";
+  const colorStart = Number.isFinite(args.colorStart) ? Math.max(0, Math.min(255, args.colorStart)) : 33;
+  const colorEnd = Number.isFinite(args.colorEnd) ? Math.max(0, Math.min(255, args.colorEnd)) : 129;
+
+  if (args.center) {
+    for (const l of rawLogoLines) {
+      const centered = centerLine(l, args.width);
+      lines.push(colorMode === "ansi256" ? colorizeAnsi256Line(centered, colorStart, colorEnd) : centered);
+    }
+  } else {
+    const joined = rawLogoLines.join("\n").trimEnd();
+    if (colorMode === "ansi256") {
+      for (const l of joined.split("\n")) lines.push(colorizeAnsi256Line(l, colorStart, colorEnd));
+    } else {
+      lines.push(joined);
+    }
+  }
+
+  if (args.slogan || args.hint) lines.push("");
+  if (args.slogan) lines.push(args.center ? centerLine(args.slogan, args.width) : String(args.slogan));
+  if (args.hint) {
+    lines.push("");
+    lines.push(args.center ? centerLine(args.hint, args.width) : String(args.hint));
+  }
+
+  if (args.rule) {
+    lines.push("");
+    lines.push(hr(args.width, "-"));
+    lines.push(`Name: ${args.brand}`.slice(0, args.width));
+    if (args.version) lines.push(`Version: ${args.version}`.slice(0, args.width));
+    if (args.author) lines.push(`Author: ${args.author}`.slice(0, args.width));
+    if (args.repo) lines.push(`Repo: ${args.repo}`.slice(0, args.width));
+    if (args.docs) lines.push(`Docs: ${args.docs}`.slice(0, args.width));
+  }
+
+  process.stdout.write(lines.join("\n").trimEnd() + "\n");
+}
+
+main().catch((err) => {
+  process.stderr.write(`Error: ${err?.message ?? String(err)}\n`);
+  process.exit(1);
+});

+ 202 - 0
skills/ascii-cli-logo-banner-python/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 61 - 0
skills/ascii-cli-logo-banner-python/SKILL.md

@@ -0,0 +1,61 @@
+---
+name: ascii-cli-logo-banner-python
+description: Generate copy-pastable ASCII banners with a built-in font (no external font deps), including compact fallback and optional ANSI 256 coloring for the logo.
+license: Complete terms in LICENSE.txt
+dependencies:
+  - python>=3.8
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-cli-logo-banner-python`.
+
+**Trigger phrases include:**
+- "ascii-cli-logo-banner-python"
+- "use ascii-cli-logo-banner-python"
+- "用 ascii-cli-logo-banner-python 生成启动 Banner"
+- "使用 ascii-cli-logo-banner-python 输出 ASCII Logo + slogan(居中)"
+
+## Boundary
+- Output copy-pastable text and layout rules only. Do not modify project code.
+- Default output is width-safe and copy/paste safe (no trailing spaces).
+- ANSI coloring is optional and MUST be applied to visible characters only (spaces are not colorized).
+- This skill uses a built-in 5x5 font. It is not a full FIGlet engine.
+
+## How to use this skill
+### Inputs (recommended)
+- brand (required)
+- width (default 80; if `< 60` use compact mode)
+- slogan (optional; centered line under the logo)
+- hint (optional; centered line under the slogan)
+- glyph (ascii | block, default ascii)
+- center (default true)
+- rule (default true; set false for hero output)
+- version/repo/docs/author (optional; only used when `rule=true`)
+- colorMode (none | ansi256, default none; logo only)
+- colorStart/colorEnd (0-255, defaults 33/129; only when `colorMode=ansi256`)
+
+### Outputs (required)
+- bannerPlain: banner text (ASCII-only when colorMode=none)
+- compactPlain: compact banner when width < 60
+- plainTextFallback: if colorMode is enabled, also provide a no-color fallback (same layout)
+
+## Script
+- `scripts/generate_banner.py`
+
+## Examples
+- `examples/banner-80.md`
+- `examples/banner-compact.md`
+- `examples/banner-slogan-centered.md`
+- `examples/color-ansi256.md`
+
+## Quality checklist
+1. 80-column output does not wrap; no trailing spaces
+2. Width < 60 uses compact mode
+3. Color mode does not break alignment (spaces are not colorized)
+4. Never prints secrets (tokens, internal URLs, personal data)
+
+## Keywords
+**English:** ascii-cli-logo-banner-python, ascii, banner, logo, cli, terminal, startup, slogan, ansi256
+**中文:** ascii-cli-logo-banner-python, ASCII 启动横幅, 终端 Banner, 居中标语, ANSI256 上色

+ 26 - 0
skills/ascii-cli-logo-banner-python/examples/banner-80.md

@@ -0,0 +1,26 @@
+# ascii-cli-logo-banner-python (80 columns)
+
+## Input
+- brandName: PartmeAI
+- version: 1.2.3
+- repoUrl: https://github.com/partme-ai/partme-cli
+- width: 80
+- colorMode: none
+
+## Output (example, ASCII-only)
+
+```
+PPPP    AAAA   RRRR   TTTTT  MMMM    MMMM  EEEE      AAAA   IIII
+P   P  A    A  R   R    T    M   M  M   M  E        A    A   II
+PPPP   AAAAAA  RRRR     T    M    MM    M  EEEE     AAAAAA   II
+P      A    A  R  R     T    M          M  E        A    A   II
+P      A    A  R   R    T    M          M  EEEE     A    A  IIII
+--------------------------------------------------------------------------------
+Name: PartmeAI
+Version: 1.2.3
+Repo: https://github.com/partme-ai/partme-cli
+```
+
+## Notes
+- This example focuses on structure/alignment. The exact glyph font may differ.
+- If ANSI color is enabled, also provide a no-color fallback.

+ 18 - 0
skills/ascii-cli-logo-banner-python/examples/banner-compact.md

@@ -0,0 +1,18 @@
+# ascii-cli-logo-banner-python (compact fallback)
+
+## Input
+- brandName: PartmeAI
+- version: 1.2.3
+- repoUrl: https://github.com/partme-ai/partme-cli
+- width: 50
+
+## Output (compactPlain)
+
+```
+PartmeAI (v1.2.3)
+--------------------------------------------------
+Repo: https://github.com/partme-ai/partme-cli
+```
+
+## Notes
+- For `width < 60`, prefer compact mode (log-friendly).

+ 17 - 0
skills/ascii-cli-logo-banner-python/examples/banner-slogan-centered.md

@@ -0,0 +1,17 @@
+# ascii-cli-logo-banner-python: centered slogan + hint
+
+## Run
+
+```bash
+python3 scripts/generate_banner.py \
+  --brand "SPECIFY" \
+  --width 80 \
+  --glyph block \
+  --slogan "GitHub Spec Kit - Spec-Driven Development Toolkit" \
+  --hint "Run 'specify --help' for usage information" \
+  --no-rule
+```
+
+## Notes
+- `--glyph block` uses `█` for a solid logo look.
+- `--no-rule` prints a “hero” style output (logo + centered lines), without the info block.

+ 22 - 0
skills/ascii-cli-logo-banner-python/examples/color-ansi256.md

@@ -0,0 +1,22 @@
+# ascii-cli-logo-banner-python: ANSI color (ansi256)
+
+This example colorizes the logo using ANSI 256 colors while keeping spacing alignment safe (spaces are not colorized).
+
+## Run
+
+```bash
+python3 scripts/generate_banner.py \
+  --brand "SPECIFY" \
+  --width 80 \
+  --glyph ascii \
+  --slogan "GitHub Spec Kit - Spec-Driven Development Toolkit" \
+  --hint "Run 'specify --help' for usage information" \
+  --no-rule \
+  --colorMode ansi256 \
+  --colorStart 46 \
+  --colorEnd 196
+```
+
+
+## Notes
+- If output is redirected to a file, consider disabling color (`--colorMode none`) to keep raw text clean.

+ 505 - 0
skills/ascii-cli-logo-banner-python/scripts/generate_banner.py

@@ -0,0 +1,505 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+from dataclasses import dataclass
+from typing import Dict, List, Sequence
+
+
+@dataclass(frozen=True)
+class BannerInput:
+    brand: str
+    version: str | None
+    repo: str | None
+    docs: str | None
+    author: str | None
+    width: int
+    color: str
+    slogan: str | None
+    hint: str | None
+    center: bool
+    rule: bool
+    glyph: str
+    color_mode: str
+    color_start: int
+    color_end: int
+
+
+_FONT_5X5: Dict[str, List[str]] = {
+    "A": [
+        " XXX ",
+        "X   X",
+        "XXXXX",
+        "X   X",
+        "X   X",
+    ],
+    "B": [
+        "XXXX ",
+        "X   X",
+        "XXXX ",
+        "X   X",
+        "XXXX ",
+    ],
+    "C": [
+        " XXX ",
+        "X   X",
+        "X    ",
+        "X   X",
+        " XXX ",
+    ],
+    "D": [
+        "XXXX ",
+        "X   X",
+        "X   X",
+        "X   X",
+        "XXXX ",
+    ],
+    "E": [
+        "XXXXX",
+        "X    ",
+        "XXXX ",
+        "X    ",
+        "XXXXX",
+    ],
+    "F": [
+        "XXXXX",
+        "X    ",
+        "XXXX ",
+        "X    ",
+        "X    ",
+    ],
+    "G": [
+        " XXX ",
+        "X    ",
+        "X XXX",
+        "X   X",
+        " XXXX",
+    ],
+    "H": [
+        "X   X",
+        "X   X",
+        "XXXXX",
+        "X   X",
+        "X   X",
+    ],
+    "I": [
+        "XXXXX",
+        "  X  ",
+        "  X  ",
+        "  X  ",
+        "XXXXX",
+    ],
+    "J": [
+        "XXXXX",
+        "   X ",
+        "   X ",
+        "X  X ",
+        " XX  ",
+    ],
+    "K": [
+        "X   X",
+        "X  X ",
+        "XXX  ",
+        "X  X ",
+        "X   X",
+    ],
+    "L": [
+        "X    ",
+        "X    ",
+        "X    ",
+        "X    ",
+        "XXXXX",
+    ],
+    "M": [
+        "X   X",
+        "XX XX",
+        "X X X",
+        "X   X",
+        "X   X",
+    ],
+    "N": [
+        "X   X",
+        "XX  X",
+        "X X X",
+        "X  XX",
+        "X   X",
+    ],
+    "O": [
+        " XXX ",
+        "X   X",
+        "X   X",
+        "X   X",
+        " XXX ",
+    ],
+    "P": [
+        "XXXX ",
+        "X   X",
+        "XXXX ",
+        "X    ",
+        "X    ",
+    ],
+    "Q": [
+        " XXX ",
+        "X   X",
+        "X   X",
+        "X  XX",
+        " XXXX",
+    ],
+    "R": [
+        "XXXX ",
+        "X   X",
+        "XXXX ",
+        "X  X ",
+        "X   X",
+    ],
+    "S": [
+        " XXXX",
+        "X    ",
+        " XXX ",
+        "    X",
+        "XXXX ",
+    ],
+    "T": [
+        "XXXXX",
+        "  X  ",
+        "  X  ",
+        "  X  ",
+        "  X  ",
+    ],
+    "U": [
+        "X   X",
+        "X   X",
+        "X   X",
+        "X   X",
+        " XXX ",
+    ],
+    "V": [
+        "X   X",
+        "X   X",
+        "X   X",
+        " X X ",
+        "  X  ",
+    ],
+    "W": [
+        "X   X",
+        "X   X",
+        "X X X",
+        "XX XX",
+        "X   X",
+    ],
+    "X": [
+        "X   X",
+        " X X ",
+        "  X  ",
+        " X X ",
+        "X   X",
+    ],
+    "Y": [
+        "X   X",
+        " X X ",
+        "  X  ",
+        "  X  ",
+        "  X  ",
+    ],
+    "Z": [
+        "XXXXX",
+        "   X ",
+        "  X  ",
+        " X   ",
+        "XXXXX",
+    ],
+    "0": [
+        " XXX ",
+        "X   X",
+        "X   X",
+        "X   X",
+        " XXX ",
+    ],
+    "1": [
+        "  X  ",
+        " XX  ",
+        "  X  ",
+        "  X  ",
+        " XXX ",
+    ],
+    "2": [
+        " XXX ",
+        "X   X",
+        "   X ",
+        "  X  ",
+        "XXXXX",
+    ],
+    "3": [
+        "XXXX ",
+        "    X",
+        " XXX ",
+        "    X",
+        "XXXX ",
+    ],
+    "4": [
+        "X   X",
+        "X   X",
+        "XXXXX",
+        "    X",
+        "    X",
+    ],
+    "5": [
+        "XXXXX",
+        "X    ",
+        "XXXX ",
+        "    X",
+        "XXXX ",
+    ],
+    "6": [
+        " XXX ",
+        "X    ",
+        "XXXX ",
+        "X   X",
+        " XXX ",
+    ],
+    "7": [
+        "XXXXX",
+        "   X ",
+        "  X  ",
+        " X   ",
+        "X    ",
+    ],
+    "8": [
+        " XXX ",
+        "X   X",
+        " XXX ",
+        "X   X",
+        " XXX ",
+    ],
+    "9": [
+        " XXX ",
+        "X   X",
+        " XXXX",
+        "    X",
+        " XXX ",
+    ],
+    " ": [
+        "     ",
+        "     ",
+        "     ",
+        "     ",
+        "     ",
+    ],
+    "-": [
+        "     ",
+        "     ",
+        "XXXXX",
+        "     ",
+        "     ",
+    ],
+    "_": [
+        "     ",
+        "     ",
+        "     ",
+        "     ",
+        "XXXXX",
+    ],
+    ".": [
+        "     ",
+        "     ",
+        "     ",
+        "     ",
+        "  X  ",
+    ],
+    "'": [
+        "  X  ",
+        "  X  ",
+        "     ",
+        "     ",
+        "     ",
+    ],
+    "!": [
+        "  X  ",
+        "  X  ",
+        "  X  ",
+        "     ",
+        "  X  ",
+    ],
+}
+
+
+def _fill_char(glyph: str) -> str:
+    if glyph == "block":
+        return "█"
+    return "#"
+
+
+def render_block_text(text: str, glyph: str) -> List[str]:
+    fill = _fill_char(glyph)
+    rows = [""] * 5
+    for ch in text.upper():
+        g = _FONT_5X5.get(ch, _FONT_5X5[" "])
+        for i in range(5):
+            painted = "".join(fill if c != " " else " " for c in g[i])
+            rows[i] += painted + " "
+    return [r.rstrip() for r in rows]
+
+
+def truncate_line(line: str, width: int) -> str:
+    """截断行内容,确保不超过指定列宽。"""
+
+    if width <= 0:
+        return ""
+    return line[:width]
+
+
+def center_line(line: str, width: int) -> str:
+    if width <= 0:
+        return ""
+    s = line.rstrip("\n")
+    if len(s) >= width:
+        return s[:width].rstrip()
+    pad_left = (width - len(s)) // 2
+    return (" " * pad_left) + s
+
+
+def _ansi_fg_256(code: int) -> str:
+    return f"\x1b[38;5;{code}m"
+
+
+def _ansi_reset() -> str:
+    return "\x1b[0m"
+
+
+def _lerp(a: int, b: int, t: float) -> int:
+    return int(round(a + (b - a) * t))
+
+
+def colorize_ansi256(lines: List[str], start: int, end: int) -> List[str]:
+    reset = _ansi_reset()
+    if not lines:
+        return []
+    max_len = max(len(l) for l in lines) or 1
+    out_lines: List[str] = []
+    for line in lines:
+        out = []
+        for x, ch in enumerate(line):
+            if ch == " ":
+                out.append(ch)
+                continue
+            t = 0.0 if max_len <= 1 else x / (max_len - 1)
+            code = _lerp(start, end, t)
+            out.append(_ansi_fg_256(code) + ch + reset)
+        out_lines.append("".join(out))
+    return out_lines
+
+
+def hr(width: int, ch: str = "-") -> str:
+    """生成水平分隔线。"""
+
+    width = max(0, width)
+    ch = (ch or "-")[0]
+    return ch * width
+
+
+def render_compact(b: BannerInput) -> str:
+    """渲染窄屏降级 banner。"""
+
+    title = b.brand
+    if b.version:
+        title += f" (v{b.version})"
+    lines: List[str] = [truncate_line(title, b.width)]
+    if b.slogan:
+        lines.append(center_line(b.slogan, b.width))
+    if b.hint:
+        lines.append(center_line(b.hint, b.width))
+    lines.append(hr(b.width, "-"))
+    if b.repo:
+        lines.append(truncate_line(f"Repo: {b.repo}", b.width))
+    if b.docs:
+        lines.append(truncate_line(f"Docs: {b.docs}", b.width))
+    return "\n".join(lines).rstrip()
+
+
+def render_plain(b: BannerInput) -> str:
+    """渲染标准 ASCII-only banner。"""
+
+    logo_lines = render_block_text(b.brand, b.glyph)
+    if b.color_mode == "ansi256":
+        logo_lines = colorize_ansi256(logo_lines, b.color_start, b.color_end)
+    if b.center:
+        lines: List[str] = [center_line(truncate_line(l, b.width), b.width) for l in logo_lines]
+    else:
+        lines = [truncate_line(l, b.width) for l in logo_lines]
+
+    if b.slogan or b.hint:
+        lines.append("")
+    if b.slogan:
+        lines.append(center_line(b.slogan, b.width))
+    if b.hint:
+        lines.append("")
+        lines.append(center_line(b.hint, b.width))
+
+    if b.rule:
+        lines.append("")
+        lines.append(hr(b.width, "-"))
+        lines.append(truncate_line(f"Name: {b.brand}", b.width))
+        if b.version:
+            lines.append(truncate_line(f"Version: {b.version}", b.width))
+        if b.author:
+            lines.append(truncate_line(f"Author: {b.author}", b.width))
+        if b.repo:
+            lines.append(truncate_line(f"Repo: {b.repo}", b.width))
+        if b.docs:
+            lines.append(truncate_line(f"Docs: {b.docs}", b.width))
+    return "\n".join(lines).rstrip()
+
+
+def parse_args(argv: Sequence[str] | None = None) -> BannerInput:
+    """解析命令行参数并构造 BannerInput。"""
+
+    p = argparse.ArgumentParser(description="Generate ASCII-only CLI banner (with compact fallback).")
+    p.add_argument("--brand", required=True, help="Brand name, e.g. PartmeAI")
+    p.add_argument("--version", default=None, help="Version, e.g. 1.2.3")
+    p.add_argument("--repo", default=None, help="Repository URL")
+    p.add_argument("--docs", default=None, help="Docs URL")
+    p.add_argument("--author", default=None, help="Author or team")
+    p.add_argument("--width", type=int, default=80, help="Banner width, default 80")
+    p.add_argument("--slogan", default=None, help="Centered slogan line under the logo")
+    p.add_argument("--hint", default=None, help="Centered hint line under the slogan")
+    p.add_argument("--glyph", default="ascii", choices=["ascii", "block"], help="Logo glyph style: ascii (#) or block (█)")
+    p.add_argument("--center", dest="center", action="store_true", default=True, help="Center the logo within the width")
+    p.add_argument("--no-center", dest="center", action="store_false", help="Do not center the logo")
+    p.add_argument("--rule", dest="rule", action="store_true", default=True, help="Include horizontal rule + info block")
+    p.add_argument("--no-rule", dest="rule", action="store_false", help="Only output logo + slogan/hint (no info block)")
+    p.add_argument("--colorMode", default="none", choices=["none", "ansi256"], help="Color mode: none|ansi256 (logo only)")
+    p.add_argument("--colorStart", type=int, default=33, help="ANSI 256 start color (0-255)")
+    p.add_argument("--colorEnd", type=int, default=129, help="ANSI 256 end color (0-255)")
+    ns = p.parse_args(argv)
+    return BannerInput(
+        brand=ns.brand,
+        version=ns.version,
+        repo=ns.repo,
+        docs=ns.docs,
+        author=ns.author,
+        width=max(10, int(ns.width)),
+        color="none",
+        slogan=ns.slogan,
+        hint=ns.hint,
+        center=bool(ns.center),
+        rule=bool(ns.rule),
+        glyph=ns.glyph,
+        color_mode=str(ns.colorMode),
+        color_start=max(0, min(255, int(ns.colorStart))),
+        color_end=max(0, min(255, int(ns.colorEnd))),
+    )
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+    """程序入口:根据 width 选择标准或 compact 输出。"""
+
+    b = parse_args(argv)
+    if b.width < 60:
+        print(render_compact(b))
+        return 0
+    print(render_plain(b))
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 202 - 0
skills/ascii-cli-logo-banner/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 81 - 0
skills/ascii-cli-logo-banner/SKILL.md

@@ -0,0 +1,81 @@
+---
+name: ascii-cli-logo-banner
+description: Entry point for ASCII CLI banners. Choose the Python built-in font skill or the figlet.js/FIGfont skill depending on needs.
+license: Complete terms in LICENSE.txt
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-cli-logo-banner`.
+
+**Use this skill when the user says they want:**
+- A startup banner / logo / welcome screen for a CLI or service
+
+**Trigger phrases include:**
+- "ascii-cli-logo-banner"
+- "use ascii-cli-logo-banner"
+- "用 ascii-cli-logo-banner"
+- "使用 ascii-cli-logo-banner 生成启动 Banner"
+- "用 ascii-cli-logo-banner 做一个 ASCII Logo"
+
+## Boundary
+- This skill is a routing/selection entry point. It does not provide its own generator implementation.
+- For built-in (no external font engine): use `ascii-cli-logo-banner-python`.
+- For TAAG/FIGlet style (FIGfont spec, smushing layouts): use `ascii-cli-logo-banner-figletjs`.
+
+## How to use this skill
+### Inputs (recommended)
+- brandName (required)
+- version (optional)
+- author (optional)
+- repoUrl / docsUrl (optional)
+- width (default 80)
+- slogan (optional, centered line under the logo)
+- hint (optional, centered line under the slogan)
+- glyph (ascii | block, default ascii)
+- center (default true)
+- rule (default true; set false for logo-only hero output)
+- style (block | outline | thin, default block)
+- colorMode (none | ansi256, default none; logo only in scripts)
+- includeCta (default true)
+
+### Outputs (required)
+- bannerPlain: ASCII-only full banner (logo area + info block + horizontal rule)
+- compactPlain: compact banner for `width < 60` (single-line title + rule + 1-2 info lines)
+- plainTextFallback: no-color fallback when ANSI is enabled (same structure as bannerPlain)
+- embedNotes: 3-5 embedding notes (CLI start / service start / README / tickets)
+
+### Steps
+1. Decide width and fallback:
+   - Default `width=80`
+   - If `width < 60`, output `compactPlain` and skip the big-letter logo
+2. Generate an ASCII-only logo:
+   - Avoid full-width characters and ambiguous-width Unicode
+   - Ensure each line is `<= width`
+3. Compose the banner structure (recommended order):
+   - Logo area (or a single-line title in compact mode)
+   - Horizontal rule: exactly `width` characters (`-` or `=`)
+   - Info block: Name / Version / Repo / Docs / Author (only include fields provided)
+   - Optional CTA: e.g. `Run: <command>` or `Docs: <url>`
+4. Optional ANSI coloring (must not break alignment):
+   - Colorize visible characters only; do not colorize spaces
+   - Always provide `plainTextFallback`
+
+## Script (optional)
+- Use `ascii-cli-logo-banner-python` for the Python implementation.
+- Use `ascii-cli-logo-banner-figletjs` for the figlet.js/FIGfont implementation.
+
+## Examples
+- See examples in the two implementation skills:
+  - `ascii-cli-logo-banner-python/examples/*`
+  - `ascii-cli-logo-banner-figletjs/examples/*`
+
+## Quality checklist
+1. Does not wrap or misalign at 80 columns; no trailing spaces
+2. Copy-pastes cleanly into logs/email/tickets
+3. Never prints secrets (tokens, internal URLs, personal data)
+
+## Keywords
+**English:** ascii, banner, logo, cli, terminal, startup, welcome, plain text, ansi, no-color
+**中文:** ASCII, 启动横幅, 终端 Banner, CLI Logo, 欢迎页, 纯文本, ANSI 上色, 无色回退

+ 26 - 0
skills/ascii-cli-logo-banner/examples/banner-80.md

@@ -0,0 +1,26 @@
+# ascii-cli-logo-banner (entry point)
+
+## Input
+- brandName: PartmeAI
+- version: 1.2.3
+- repoUrl: https://github.com/partme-ai/partme-cli
+- width: 80
+- colorMode: none
+
+## Output(示例结构,ASCII-only)
+
+```
+PPPP    AAAA   RRRR   TTTTT  MMMM    MMMM  EEEE      AAAA   IIII
+P   P  A    A  R   R    T    M   M  M   M  E        A    A   II
+PPPP   AAAAAA  RRRR     T    M    MM    M  EEEE     AAAAAA   II
+P      A    A  R  R     T    M          M  E        A    A   II
+P      A    A  R   R    T    M          M  EEEE     A    A  IIII
+--------------------------------------------------------------------------------
+Name: PartmeAI
+Version: 1.2.3
+Repo: https://github.com/partme-ai/partme-cli
+```
+
+## Notes
+- Use `ascii-cli-logo-banner-python` for the built-in Python generator.
+- Use `ascii-cli-logo-banner-figletjs` for TAAG/FIGlet-style output.

+ 18 - 0
skills/ascii-cli-logo-banner/examples/banner-compact.md

@@ -0,0 +1,18 @@
+# ascii-cli-logo-banner (entry point)
+
+## Input
+- brandName: PartmeAI
+- version: 1.2.3
+- repoUrl: https://github.com/partme-ai/partme-cli
+- width: 50
+
+## Output(compactPlain)
+
+```
+PartmeAI (v1.2.3)
+--------------------------------------------------
+Repo: https://github.com/partme-ai/partme-cli
+```
+
+## Notes
+- Use `ascii-cli-logo-banner-python` or `ascii-cli-logo-banner-figletjs` for implementations.

+ 202 - 0
skills/ascii-diagram-boxflow/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 52 - 0
skills/ascii-diagram-boxflow/SKILL.md

@@ -0,0 +1,52 @@
+---
+name: ascii-diagram-boxflow
+description: Generate plain ASCII box-flow diagrams (boxes + arrows) for environments without renderers, with alignment rules and split strategies for complex graphs.
+license: Complete terms in LICENSE.txt
+dependencies:
+  - python>=3.8
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-diagram-boxflow`.
+
+**Trigger phrases include:**
+- "ascii-diagram-boxflow"
+- "use ascii-diagram-boxflow"
+- "用 ascii-diagram-boxflow 画 ASCII 流程图/框图"
+- "使用 ascii-diagram-boxflow 生成 box + 箭头连接图"
+
+## Boundary
+- ASCII output only. Do not output Mermaid/PlantUML.
+- Recommended nodes <= 12; if larger, split into sub-diagrams.
+- Auto-layout is best-effort for linear and simple branching. Complex layouts require manual ordering or splitting.
+
+## How to use this skill
+### Inputs
+- nodes (node list; names required)
+- edges (connections: from/to)
+- direction (TB | LR, default TB)
+- width (default 80)
+- boxWidth (default 16)
+- numbering (default false)
+
+### Outputs (required)
+- diagram (ASCII-only)
+- layoutRules (box width + arrow/line rules)
+- splitAdvice (how to split complex diagrams)
+
+## Script
+- `scripts/boxflow.py`: best-effort for linear flows and single 2-way branching
+
+## Examples
+- `examples/login-flow.md`
+
+## Quality checklist
+1. Arrow direction is unambiguous; avoid crossings
+2. Line width `<= width`; no trailing spaces
+3. Long node names must be truncated or wrapped consistently
+
+## Keywords
+**English:** ascii-diagram-boxflow, ascii diagram, flowchart, box, arrow, plain text, terminal
+**中文:** ascii-diagram-boxflow, ASCII 框图, 流程图, 纯文本, 盒子, 箭头, 终端

+ 50 - 0
skills/ascii-diagram-boxflow/examples/login-flow.md

@@ -0,0 +1,50 @@
+# ascii-diagram-boxflow:登录流程(TB)示例
+
+## Input
+
+nodes:
+- Start
+- Input
+- Validate
+- Success
+- Fail
+
+edges:
+- Start -> Input
+- Input -> Validate
+- Validate -> Success
+- Validate -> Fail
+
+## Output(示意,ASCII-only)
+
+```
++--------------+
+|    Start     |
++--------------+
+       |
+       v
++--------------+
+|    Input     |
++--------------+
+       |
+       v
++--------------+
+|   Validate   |
++--------------+
+    |     |
+    v     v
++--------+  +--------+
+|Success |  |  Fail  |
++--------+  +--------+
+```
+
+## Script usage(线性/简单分支 best-effort)
+
+```bash
+cat << 'JSON' | python3 scripts/boxflow.py
+{
+  "nodes": ["Start", "Input", "Validate", "Success", "Fail"],
+  "edges": [["Start","Input"], ["Input","Validate"], ["Validate","Success"], ["Validate","Fail"]]
+}
+JSON
+```

+ 105 - 0
skills/ascii-diagram-boxflow/scripts/boxflow.py

@@ -0,0 +1,105 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import json
+import sys
+from dataclasses import dataclass
+from typing import Dict, List, Sequence, Tuple
+
+
+@dataclass(frozen=True)
+class Spec:
+    """boxflow 图规格(简化版)。"""
+
+    nodes: List[str]
+    edges: List[Tuple[str, str]]
+    box_width: int
+
+
+def _box(label: str, width: int) -> List[str]:
+    """生成固定宽度的 ASCII 盒子。"""
+
+    inner = max(1, width - 2)
+    text = (label or "")[:inner].center(inner)
+    top = "+" + "-" * inner + "+"
+    mid = "|" + text + "|"
+    return [top, mid, top]
+
+
+def _parse(stdin_text: str) -> Spec:
+    """解析 stdin JSON 到 Spec。"""
+
+    data = json.loads(stdin_text)
+    nodes = [str(n) for n in data.get("nodes", [])]
+    edges = [(str(a), str(b)) for a, b in data.get("edges", [])]
+    box_width = int(data.get("boxWidth", 14))
+    return Spec(nodes=nodes, edges=edges, box_width=max(10, box_width))
+
+
+def _children_map(edges: List[Tuple[str, str]]) -> Dict[str, List[str]]:
+    """构建 from -> children 映射。"""
+
+    m: Dict[str, List[str]] = {}
+    for a, b in edges:
+        m.setdefault(a, []).append(b)
+    return m
+
+
+def render_tb(spec: Spec) -> str:
+    """渲染 TB 方向(线性 + 单点二分支)。"""
+
+    if not spec.nodes:
+        return ""
+    children = _children_map(spec.edges)
+    w = spec.box_width
+
+    # 选择一个起点:优先用 nodes[0]
+    start = spec.nodes[0]
+    lines: List[str] = []
+
+    def add_box(label: str) -> None:
+        for l in _box(label, w):
+            lines.append(l)
+
+    cur = start
+    visited: set[str] = set()
+    while cur and cur not in visited:
+        visited.add(cur)
+        add_box(cur)
+        kids = children.get(cur, [])
+        if not kids:
+            break
+        if len(kids) == 1:
+            lines.append(" " * (w // 2) + "|")
+            lines.append(" " * (w // 2) + "v")
+            cur = kids[0]
+            continue
+
+        # 仅支持二分支展示
+        left, right = kids[0], kids[1]
+        lines.append(" " * (w // 2 - 1) + "|     |")
+        lines.append(" " * (w // 2 - 1) + "v     v")
+
+        left_box = _box(left, w)
+        right_box = _box(right, w)
+        for i in range(3):
+            lines.append(left_box[i] + "  " + right_box[i])
+        break
+
+    return "\n".join(lines).rstrip()
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+    """程序入口:从 stdin 读取 JSON,输出 TB boxflow。"""
+
+    raw = sys.stdin.read().strip()
+    if not raw:
+        print("Error: empty stdin. Provide JSON {nodes:[], edges:[[]]}.", file=sys.stderr)
+        return 1
+    spec = _parse(raw)
+    print(render_tb(spec))
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 202 - 0
skills/ascii-image-to-ascii/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 70 - 0
skills/ascii-image-to-ascii/SKILL.md

@@ -0,0 +1,70 @@
+---
+name: ascii-image-to-ascii
+description: Convert an image into ASCII art (readable + detail variants, width/charset controls, optional ANSI), for terminal previews and plain-text “image substitutes”.
+license: Complete terms in LICENSE.txt
+dependencies:
+  - python>=3.8
+  - pillow
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-image-to-ascii`.
+
+**Trigger phrases include:**
+- "ascii-image-to-ascii"
+- "use ascii-image-to-ascii"
+- "用 ascii-image-to-ascii 把图片转字符画"
+- "使用 ascii-image-to-ascii 生成可读优先/细节优先两版"
+
+## Boundary
+- Default output is ASCII-only; ANSI coloring is optional.
+- The bundled script is for local conversion/verification only. Do not fetch/upload images on the user’s behalf.
+- Always give pre-processing advice (crop subject, raise contrast, simplify background) before generating the final ASCII art.
+
+## How to use this skill
+### Inputs
+- imagePath (local path, required)
+- width (default 100; common: 80/100/120)
+- charset (default ` .:-=+*#%@`, from light to dark)
+- mode (readable | detail; if outputting both, this can be ignored)
+- background (light | dark | unknown, default unknown)
+- colorMode (none | ansi256, default none)
+
+### Outputs (required)
+- asciiReadable: readable-first (less noise, clearer silhouette)
+- asciiDetail: detail-first (more levels, richer texture)
+- paramsGuide: recommended width/charset + pre-processing tips
+- pitfalls: 3-5 common failure modes with fixes
+
+### Steps
+1. Pre-processing advice (required):
+   - Crop the subject, remove irrelevant background
+   - Increase contrast to reduce gradient noise
+   - Target width usually 80–120 columns
+2. Charset + mapping direction:
+   - Space is the lightest, `@` is the darkest (or invert consistently)
+3. Generate two variants:
+   - readable: fewer levels (less noise)
+   - detail: more levels (more texture)
+4. Optional ANSI:
+   - Use color only as a hint; keep the silhouette readable
+   - Always provide a no-color fallback
+
+## Script
+- `scripts/image_to_ascii.py`
+  - Requires Python + Pillow (`pip install pillow`)
+  - Supports: readable/detail variants, optional `--ansi256`
+
+## Examples
+- `examples/readable-vs-detail.md`
+
+## Quality checklist
+1. Lines are consistent and `<= width`
+2. The readable variant must preserve the main silhouette
+3. No trailing spaces (copy/paste safe)
+
+## Keywords
+**English:** ascii-image-to-ascii, image to ascii, ascii art, terminal preview, charset, grayscale, dithering, ansi
+**中文:** ascii-image-to-ascii, 图片转字符画, ASCII 字符画, 终端预览, 字符集, 灰度映射, 降噪, ANSI 彩色

+ 39 - 0
skills/ascii-image-to-ascii/examples/readable-vs-detail.md

@@ -0,0 +1,39 @@
+# ascii-image-to-ascii:readable vs detail
+
+## Script usage
+
+```bash
+python3 scripts/image_to_ascii.py --image ./example.png --width 100 --mode readable
+python3 scripts/image_to_ascii.py --image ./example.png --width 100 --mode detail
+```
+
+## Output(示意)
+
+readable(轮廓优先):
+
+```
+          ....:::::::....
+       ..::---======---::..
+     .:--==+++******+++==--:.
+    :--=++**##########**++=--:
+    :--=++**##########**++=--:
+     .:--==+++******+++==--:.
+       ..::---======---::..
+          ....:::::::....
+```
+
+detail(细节优先):
+
+```
+        .:-=+*#%@%#*+=-:.
+     .:-=+*#%@@@@@@%#*+=-:.
+    .-=+*#%@@@%%%%@@@%#*+=-.
+    :=+*#%@@%#*++*#%@@%#*+=:
+    .-=+*#%@@@%%%%@@@%#*+=-.
+     .:-=+*#%@@@@@@%#*+=-:.
+        .:-=+*#%@%#*+=-:.
+```
+
+## Notes
+- 输出效果强依赖图片预处理:裁剪主体、提升对比度、简化背景
+- 如果出现“噪点很多/看不出轮廓”,优先用 readable 或缩小宽度

+ 145 - 0
skills/ascii-image-to-ascii/scripts/image_to_ascii.py

@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+import math
+import sys
+from dataclasses import dataclass
+from typing import Iterable, Sequence
+
+
+try:
+    from PIL import Image  # type: ignore
+except Exception:  # pragma: no cover
+    Image = None  # type: ignore
+
+
+@dataclass(frozen=True)
+class Options:
+    """图片转 ASCII 的参数。"""
+
+    image_path: str
+    width: int
+    charset: str
+    mode: str
+    invert: bool
+    ansi256: bool
+
+
+def parse_args(argv: Sequence[str] | None = None) -> Options:
+    """解析命令行参数。"""
+
+    p = argparse.ArgumentParser(description="Convert image to ASCII art (readable/detail). Requires Pillow.")
+    p.add_argument("--image", required=True, help="Image path")
+    p.add_argument("--width", type=int, default=100, help="Target width in characters")
+    p.add_argument("--charset", default=" .:-=+*#%@", help="ASCII charset from light to dark")
+    p.add_argument("--mode", choices=["readable", "detail"], default="readable", help="Output mode")
+    p.add_argument("--invert", action="store_true", help="Invert brightness mapping")
+    p.add_argument("--ansi256", action="store_true", help="Add ANSI 256 colors (best-effort)")
+    ns = p.parse_args(argv)
+    return Options(
+        image_path=ns.image,
+        width=max(10, ns.width),
+        charset=ns.charset,
+        mode=ns.mode,
+        invert=bool(ns.invert),
+        ansi256=bool(ns.ansi256),
+    )
+
+
+def _ensure_pillow() -> None:
+    """确保 Pillow 可用。"""
+
+    if Image is None:
+        raise RuntimeError("Pillow 未安装:请先执行 `pip install pillow`")
+
+
+def _resize_for_terminal(img: "Image.Image", target_width: int) -> "Image.Image":
+    """按终端字符比例缩放图片(字符通常比宽更“高”)。"""
+
+    w, h = img.size
+    if w <= 0 or h <= 0:
+        return img
+    aspect = h / w
+    target_height = max(1, int(math.ceil(target_width * aspect * 0.55)))
+    return img.resize((target_width, target_height))
+
+
+def _normalize_charset(charset: str, mode: str) -> str:
+    """根据模式对字符集做降级或增强。"""
+
+    chars = [c for c in charset if 0x20 <= ord(c) <= 0x7E]
+    if not chars:
+        chars = list(" .:-=+*#%@")
+    if mode == "readable":
+        # 稀疏层级:减少噪点
+        sparse = []
+        for c in chars:
+            if c in [" ", ".", ":", "-", "=", "+", "*", "#", "@"]:
+                sparse.append(c)
+        return "".join(sparse) if len(sparse) >= 6 else " .:-=+*#%@"
+    return "".join(chars)
+
+
+def _to_gray(img: "Image.Image") -> "Image.Image":
+    """转换为灰度。"""
+
+    return img.convert("L")
+
+
+def _pixel_to_char(value: int, charset: str, invert: bool) -> str:
+    """将 0-255 灰度映射到字符。"""
+
+    v = 255 - value if invert else value
+    idx = int((v / 255) * (len(charset) - 1))
+    return charset[idx]
+
+
+def _ansi256_fg(gray: int) -> str:
+    """将灰度映射到 ANSI 256 色(灰阶区间)。"""
+
+    # 232-255 是灰阶
+    idx = 232 + int((gray / 255) * 23)
+    return f"\x1b[38;5;{idx}m"
+
+
+def image_to_ascii_lines(img: "Image.Image", charset: str, invert: bool, ansi256: bool) -> Iterable[str]:
+    """把灰度图转换为 ASCII 行。"""
+
+    pixels = img.load()
+    w, h = img.size
+    reset = "\x1b[0m"
+    for y in range(h):
+        line_chars = []
+        for x in range(w):
+            gray = int(pixels[x, y])
+            ch = _pixel_to_char(gray, charset, invert)
+            if ansi256 and ch != " ":
+                line_chars.append(_ansi256_fg(gray) + ch + reset)
+            else:
+                line_chars.append(ch)
+        yield "".join(line_chars).rstrip()
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+    """程序入口。"""
+
+    try:
+        _ensure_pillow()
+        opt = parse_args(argv)
+        charset = _normalize_charset(opt.charset, opt.mode)
+
+        img = Image.open(opt.image_path)  # type: ignore[misc]
+        img = _resize_for_terminal(img, opt.width)
+        img = _to_gray(img)
+
+        for line in image_to_ascii_lines(img, charset, opt.invert, opt.ansi256):
+            print(line)
+        return 0
+    except Exception as e:
+        print(f"Error: {e}", file=sys.stderr)
+        return 1
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 202 - 0
skills/ascii-mini-charts/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 52 - 0
skills/ascii-mini-charts/SKILL.md

@@ -0,0 +1,52 @@
+---
+name: ascii-mini-charts
+description: Generate ASCII mini charts (sparkline/bar/simple line) for plain-text trend inspection, with minimal + annotated variants and normalization notes.
+license: Complete terms in LICENSE.txt
+dependencies:
+  - python>=3.8
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-mini-charts`.
+
+**Trigger phrases include:**
+- "ascii-mini-charts"
+- "use ascii-mini-charts"
+- "用 ascii-mini-charts 生成 sparkline / 火花线"
+- "使用 ascii-mini-charts 标注 min/max/current"
+
+## Boundary
+- No statistical inference. Visualization only.
+- Default output is ASCII-only. Unicode blocks are optional and MUST include an ASCII-only fallback.
+- Default output width should stay <= 60 columns. For longer series, provide a compression strategy (sampling/bucketing).
+
+## How to use this skill
+### Inputs
+- series (required numeric list)
+- type (sparkline | bar | line, default sparkline)
+- width (default min(len(series), 30))
+- height (default 10 for bar/line)
+- normalize (linear | log, default linear)
+- showLabels (default true)
+
+### Outputs (required)
+- chartMinimal
+- chartAnnotated (with min/max/current)
+- scaleNotes (normalization + outlier strategy)
+
+## Script
+- `scripts/mini_charts.py`: generate ASCII mini charts from JSON stdin
+
+## Examples
+- `examples/sparkline.md`
+
+## Quality checklist
+1. Trend is clear; labels are short and non-spammy
+2. ASCII-only output copy/pastes cleanly
+3. Provide a compression strategy for long series
+
+## Keywords
+**English:** ascii-mini-charts, sparkline, ascii chart, bar chart, line chart, trend, normalize
+**中文:** ascii-mini-charts, 火花线, ASCII 图表, 柱状图, 折线图, 趋势, 归一化

+ 31 - 0
skills/ascii-mini-charts/examples/sparkline.md

@@ -0,0 +1,31 @@
+# ascii-mini-charts:sparkline 示例
+
+## Input
+
+```json
+{
+  "series": [3, 4, 5, 8, 6, 9, 12, 10, 11, 14]
+}
+```
+
+## Output(ASCII-only,示意)
+
+minimal:
+
+```
+..:-=+**#@
+```
+
+annotated:
+
+```
+..:-=+**#@  min=3 max=14 cur=14
+```
+
+## Script usage
+
+```bash
+cat << 'JSON' | python3 scripts/mini_charts.py --type sparkline --width 20
+{ "series": [3,4,5,8,6,9,12,10,11,14] }
+JSON
+```

+ 130 - 0
skills/ascii-mini-charts/scripts/mini_charts.py

@@ -0,0 +1,130 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+import json
+import math
+import sys
+from dataclasses import dataclass
+from typing import List, Sequence
+
+
+@dataclass(frozen=True)
+class Options:
+    """迷你图输出参数。"""
+
+    chart_type: str
+    width: int
+    height: int
+    normalize: str
+    annotated: bool
+
+
+def parse_args(argv: Sequence[str] | None = None) -> Options:
+    """解析命令行参数。"""
+
+    p = argparse.ArgumentParser(description="Generate ASCII mini charts from JSON on stdin.")
+    p.add_argument("--type", choices=["sparkline", "bar"], default="sparkline")
+    p.add_argument("--width", type=int, default=30)
+    p.add_argument("--height", type=int, default=10)
+    p.add_argument("--normalize", choices=["linear", "log"], default="linear")
+    p.add_argument("--annotated", action="store_true", help="Append min/max/current labels")
+    ns = p.parse_args(argv)
+    return Options(
+        chart_type=ns.type,
+        width=max(5, ns.width),
+        height=max(3, ns.height),
+        normalize=ns.normalize,
+        annotated=bool(ns.annotated),
+    )
+
+
+def _normalize(values: List[float], mode: str) -> List[float]:
+    """归一化到 0..1。"""
+
+    if not values:
+        return []
+    if mode == "log":
+        safe = [math.log(v + 1.0) for v in values]
+        mn, mx = min(safe), max(safe)
+        if mx == mn:
+            return [0.5] * len(values)
+        return [(v - mn) / (mx - mn) for v in safe]
+    mn, mx = min(values), max(values)
+    if mx == mn:
+        return [0.5] * len(values)
+    return [(v - mn) / (mx - mn) for v in values]
+
+
+def _sample(values: List[float], width: int) -> List[float]:
+    """将序列压缩到指定宽度(均匀采样)。"""
+
+    if len(values) <= width:
+        return values
+    out: List[float] = []
+    for i in range(width):
+        idx = int(i * (len(values) - 1) / (width - 1))
+        out.append(values[idx])
+    return out
+
+
+def render_sparkline(values: List[float], width: int, normalize: str) -> str:
+    """渲染 ASCII-only sparkline。"""
+
+    charset = " .:-=+*#%@"
+    sampled = _sample(values, width)
+    norm = _normalize(sampled, normalize)
+    chars = []
+    for t in norm:
+        idx = int(round(t * (len(charset) - 1)))
+        chars.append(charset[idx])
+    return "".join(chars).rstrip()
+
+
+def render_bar(values: List[float], width: int, height: int, normalize: str) -> str:
+    """渲染纵向柱状图(ASCII-only)。"""
+
+    sampled = _sample(values, width)
+    norm = _normalize(sampled, normalize)
+    levels = [int(round(t * height)) for t in norm]
+    lines: List[str] = []
+    for row in range(height, 0, -1):
+        line = []
+        for lv in levels:
+            line.append("#" if lv >= row else " ")
+        lines.append("".join(line).rstrip())
+    return "\n".join(lines).rstrip()
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+    """程序入口。"""
+
+    opt = parse_args(argv)
+    raw = sys.stdin.read().strip()
+    if not raw:
+        print("Error: empty stdin. Provide JSON with series.", file=sys.stderr)
+        return 1
+    data = json.loads(raw)
+    series = data.get("series", [])
+    values = [float(x) for x in series]
+    if not values:
+        print("", end="")
+        return 0
+
+    if opt.chart_type == "bar":
+        out = render_bar(values, opt.width, opt.height, opt.normalize)
+    else:
+        out = render_sparkline(values, opt.width, opt.normalize)
+
+    if opt.annotated:
+        mn, mx, cur = min(values), max(values), values[-1]
+        if "\n" in out:
+            out += f"\nmin={mn:g} max={mx:g} cur={cur:g}"
+        else:
+            out += f"  min={mn:g} max={mx:g} cur={cur:g}"
+    print(out)
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 202 - 0
skills/ascii-motd-profile-banner/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 50 - 0
skills/ascii-motd-profile-banner/SKILL.md

@@ -0,0 +1,50 @@
+---
+name: ascii-motd-profile-banner
+description: Generate ASCII-only MOTD / SSH login banner / shell profile welcome messages (short/long variants, quiet mode guidance, security notices).
+license: Complete terms in LICENSE.txt
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-motd-profile-banner`.
+
+**Trigger phrases include:**
+- "ascii-motd-profile-banner"
+- "use ascii-motd-profile-banner"
+- "用 ascii-motd-profile-banner 生成 SSH 登录欢迎"
+- "使用 ascii-motd-profile-banner 输出 MOTD(短版/长版)"
+
+## Boundary
+- Produce templates and placement guidance only; do not modify system files.
+- Never include sensitive information (tokens, internal URLs, account details, personal data).
+- Default output is ASCII-only; ANSI color is optional and must have a no-color fallback.
+
+## How to use this skill
+### Inputs
+- title (required)
+- messageBullets (1–5 bullet points, required)
+- mode (short | long, default short)
+- width (default 80)
+- includeLinks (optional: Docs / Tickets / Repo)
+- colorMode (none | ansi256, default none)
+- quietHint (default true: recommend quiet output for non-interactive shells)
+
+### Outputs (required)
+- bannerShort (<= 12 lines)
+- bannerLong (<= 30 lines)
+- safetyNotes (>= 3 actionable security notes)
+- toggleAdvice (interactive vs non-interactive display guidance)
+
+## Examples
+- `examples/ssh-short.md`
+- `examples/ssh-long.md`
+
+## Quality checklist
+1. Short mode does not spam (<= 12 lines)
+2. Copy/paste safe (no trailing spaces)
+3. Security notes are clear, short, and actionable
+
+## Keywords
+**English:** ascii-motd-profile-banner, motd, ssh banner, profile, welcome message, security notice, terminal
+**中文:** ascii-motd-profile-banner, MOTD, SSH Banner, 登录欢迎, Profile, 安全提示, 终端

+ 22 - 0
skills/ascii-motd-profile-banner/examples/ssh-long.md

@@ -0,0 +1,22 @@
+# ascii-motd-profile-banner:SSH 长版示例
+
+```
+Welcome to PartmeAI DevBox
+================================================================================
+Quick links:
+- Docs:   https://example.com/docs
+- Repo:   https://github.com/partme-ai/partme-cli
+- Ticket: https://example.com/tickets
+
+Security rules:
+- Do NOT paste API keys, tokens, passwords.
+- Prefer --no-color when redirecting output to files.
+- Use least privilege accounts for operations.
+
+Help:
+- Run: partme --help
+- Skills: partme skills list
+```
+
+## Notes
+- long 模式建议 <= 30 行,仍要避免刷屏

+ 14 - 0
skills/ascii-motd-profile-banner/examples/ssh-short.md

@@ -0,0 +1,14 @@
+# ascii-motd-profile-banner:SSH 短版示例
+
+```
+Welcome to PartmeAI DevBox
+--------------------------------------------------------------------------------
+IMPORTANT:
+- Do NOT paste tokens or secrets here.
+- Use company VPN for internal resources.
+- Report issues via https://example.com/tickets
+```
+
+## Notes
+- short 模式建议 <= 12 行
+- 可选:只对标题上色,正文保持单色,避免影响可读性

+ 202 - 0
skills/ascii-progress-and-spinner/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 59 - 0
skills/ascii-progress-and-spinner/SKILL.md

@@ -0,0 +1,59 @@
+---
+name: ascii-progress-and-spinner
+description: Design ASCII progress bars and spinners for CLI UX (determinate/indeterminate, TTY single-line refresh, non-interactive log fallback) with copy-pastable style specs.
+license: Complete terms in LICENSE.txt
+dependencies:
+  - python>=3.8
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-progress-and-spinner`.
+
+**Trigger phrases include:**
+- "ascii-progress-and-spinner"
+- "use ascii-progress-and-spinner"
+- "用 ascii-progress-and-spinner 生成 ASCII 进度条"
+- "使用 ascii-progress-and-spinner 做 spinner / loading"
+
+## Boundary
+- Do not integrate a specific UI framework; output styles + refresh rules + fallback protocol + examples.
+- Must cover:
+  - determinate progress bars
+  - indeterminate spinners
+  - non-TTY / redirected-output fallback (log lines, no carriage-return updates)
+
+## How to use this skill
+### Inputs
+- mode (determinate | indeterminate)
+- width (default 40)
+- showPercent (default true)
+- showEta (optional)
+- multiTask (optional)
+- colorMode (none | ansi256, default none)
+
+### Outputs (required)
+- progressBarStyles (>= 3)
+- spinnerStyles (>= 2)
+- renderRules (TTY single-line refresh vs logLines)
+- fallbackRules (non-interactive / redirected output)
+
+### Recommended render rules
+- **TTY (interactive):** single-line refresh (overwrite previous line), avoid log spam
+- **Non-TTY (logs):** print log lines (no overwrite). Each line may include task name + percent.
+
+## Script
+- `scripts/demo.py`: local demo for progress bar + spinner shapes
+
+## Examples
+- `examples/styles.md`
+
+## Quality checklist
+1. Fixed width (percent field is fixed-width to avoid jitter)
+2. Log mode is grep-friendly (no overwrite)
+3. ASCII-only defaults are available (avoid ambiguous-width Unicode)
+
+## Keywords
+**English:** ascii-progress-and-spinner, progress bar, spinner, loading, tty, non-interactive, log output, ascii
+**中文:** ascii-progress-and-spinner, 进度条, Spinner, Loading, 终端, TTY, 日志降级, ASCII

+ 40 - 0
skills/ascii-progress-and-spinner/examples/styles.md

@@ -0,0 +1,40 @@
+# ascii-progress-and-spinner:样式库示例
+
+## Progress bars(determinate)
+
+宽度=20 示例(固定宽度,避免抖动):
+
+1) block
+```
+[#######-------------] 35%
+```
+
+2) line
+```
+|=======-------------| 35%
+```
+
+3) dots
+```
+(ooooooo.............) 35%
+```
+
+## Spinners(indeterminate)
+
+1) classic
+```
+| / - \ (循环)
+```
+
+2) dots
+```
+loading.
+loading..
+loading...
+```
+
+## Log fallback(non-TTY)
+```
+task=build step=compile progress=35%
+task=build step=compile progress=36%
+```

+ 97 - 0
skills/ascii-progress-and-spinner/scripts/demo.py

@@ -0,0 +1,97 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+import sys
+import time
+from dataclasses import dataclass
+from typing import Sequence
+
+
+@dataclass(frozen=True)
+class Options:
+    """进度条/Spinner 演示参数。"""
+
+    mode: str
+    width: int
+    seconds: float
+    log: bool
+
+
+def parse_args(argv: Sequence[str] | None = None) -> Options:
+    """解析命令行参数。"""
+
+    p = argparse.ArgumentParser(description="ASCII progress/spinner demo.")
+    p.add_argument("--mode", choices=["bar", "spinner"], default="bar")
+    p.add_argument("--width", type=int, default=40)
+    p.add_argument("--seconds", type=float, default=3.0)
+    p.add_argument("--log", action="store_true", help="Log mode (no carriage return)")
+    ns = p.parse_args(argv)
+    return Options(mode=ns.mode, width=max(10, ns.width), seconds=max(0.5, ns.seconds), log=bool(ns.log))
+
+
+def render_bar(progress: float, width: int) -> str:
+    """渲染 ASCII 进度条。"""
+
+    progress = max(0.0, min(1.0, progress))
+    filled = int(round(progress * width))
+    bar = "#" * filled + "-" * (width - filled)
+    pct = int(round(progress * 100))
+    return f"[{bar}] {pct:3d}%"
+
+
+def run_bar(opt: Options) -> int:
+    """运行进度条演示。"""
+
+    start = time.time()
+    while True:
+        t = time.time() - start
+        p = min(1.0, t / opt.seconds)
+        line = render_bar(p, opt.width)
+        if opt.log:
+            print(f"task=demo progress={int(p*100)}%")
+        else:
+            sys.stdout.write("\r" + line)
+            sys.stdout.flush()
+        if p >= 1.0:
+            break
+        time.sleep(0.05)
+    if not opt.log:
+        sys.stdout.write("\n")
+    return 0
+
+
+def run_spinner(opt: Options) -> int:
+    """运行 spinner 演示。"""
+
+    frames = ["|", "/", "-", "\\"]
+    start = time.time()
+    i = 0
+    while True:
+        t = time.time() - start
+        if t >= opt.seconds:
+            break
+        frame = frames[i % len(frames)]
+        if opt.log:
+            print(f"task=demo status=running spinner={frame}")
+        else:
+            sys.stdout.write("\r" + f"loading {frame}")
+            sys.stdout.flush()
+        i += 1
+        time.sleep(0.08)
+    if not opt.log:
+        sys.stdout.write("\n")
+    return 0
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+    """程序入口。"""
+
+    opt = parse_args(argv)
+    if opt.mode == "spinner":
+        return run_spinner(opt)
+    return run_bar(opt)
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 202 - 0
skills/ascii-table-renderer/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 62 - 0
skills/ascii-table-renderer/SKILL.md

@@ -0,0 +1,62 @@
+---
+name: ascii-table-renderer
+description: Render structured data as aligned ASCII tables (column width rules, truncate/wrap, border styles, compact/readable variants) for terminal/log/email.
+license: Complete terms in LICENSE.txt
+dependencies:
+  - python>=3.8
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-table-renderer`.
+
+**Trigger phrases include:**
+- "ascii-table-renderer"
+- "use ascii-table-renderer"
+- "用 ascii-table-renderer 把列表打印成表格"
+- "使用 ascii-table-renderer 生成 ASCII 表格(对齐/列宽)"
+
+## Boundary
+- Do not fetch data (DB/API). Only render and format output.
+- Default borders are ASCII-only: `+ - |`.
+- Out of scope: merged cells, multi-row headers, complex spanning layouts.
+
+## How to use this skill
+### Inputs
+- headers (required)
+- rows (required)
+- maxWidth (default 80)
+- maxColWidth (default 20)
+- borderStyle (light | minimal, default light)
+- overflow (ellipsis | wrap, default ellipsis)
+- align (left | right | center, default left)
+
+### Outputs (required)
+- tableCompact (log-friendly)
+- tableReadable (interactive-friendly)
+- rules (width/truncation/null/alignment rules)
+
+### Steps
+1. Compute per-column widths: `min(maxColWidth, max(contentWidth))`
+2. Handle overflow:
+   - ellipsis: use `...` consistently
+   - wrap: wrap within column width while keeping row alignment
+3. Output two variants:
+   - compact: minimal or fewer separators
+   - readable: clearer borders
+
+## Script
+- `scripts/render_table.py`: render tables from JSON stdin (compact/readable)
+
+## Examples
+- `examples/basic.md`
+
+## Quality checklist
+1. Columns align consistently; each line does not exceed maxWidth
+2. Null values are rendered as `-`
+3. Copy/paste safe (no trailing spaces)
+
+## Keywords
+**English:** ascii-table-renderer, ascii table, align, columns, rows, truncate, wrap, terminal, log
+**中文:** ascii-table-renderer, ASCII 表格, 对齐, 列宽, 截断, 换行, 终端, 日志, 工单

+ 41 - 0
skills/ascii-table-renderer/examples/basic.md

@@ -0,0 +1,41 @@
+# ascii-table-renderer:基础示例
+
+## Input
+
+headers:
+- name
+- status
+- cost
+
+rows:
+- ["build", "ok", 12.3]
+- ["deploy", "fail", 3.2]
+- ["test", "ok", 8.0]
+
+maxWidth: 80
+maxColWidth: 20
+overflow: ellipsis
+borderStyle: light
+
+## Output(readable)
+
+```
++--------+--------+------+
+| name   | status | cost |
++--------+--------+------+
+| build  | ok     | 12.3 |
+| deploy | fail   |  3.2 |
+| test   | ok     |  8.0 |
++--------+--------+------+
+```
+
+## Script usage
+
+```bash
+cat << 'JSON' | python3 scripts/render_table.py --format readable
+{
+  "headers": ["name", "status", "cost"],
+  "rows": [["build","ok",12.3], ["deploy","fail",3.2], ["test","ok",8.0]]
+}
+JSON
+```

+ 154 - 0
skills/ascii-table-renderer/scripts/render_table.py

@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+import json
+import sys
+from dataclasses import dataclass
+from typing import Any, List, Sequence
+
+
+@dataclass(frozen=True)
+class Options:
+    """ASCII 表格渲染参数。"""
+
+    fmt: str
+    max_width: int
+    max_col_width: int
+    overflow: str
+    border: str
+    align: str
+
+
+def parse_args(argv: Sequence[str] | None = None) -> Options:
+    """解析命令行参数。"""
+
+    p = argparse.ArgumentParser(description="Render ASCII table from JSON on stdin.")
+    p.add_argument("--format", choices=["compact", "readable"], default="readable")
+    p.add_argument("--max-width", type=int, default=80)
+    p.add_argument("--max-col-width", type=int, default=20)
+    p.add_argument("--overflow", choices=["ellipsis", "wrap"], default="ellipsis")
+    p.add_argument("--border", choices=["light", "minimal"], default="light")
+    p.add_argument("--align", choices=["left", "right", "center"], default="left")
+    ns = p.parse_args(argv)
+    return Options(
+        fmt=ns.format,
+        max_width=max(20, ns.max_width),
+        max_col_width=max(4, ns.max_col_width),
+        overflow=ns.overflow,
+        border=ns.border,
+        align=ns.align,
+    )
+
+
+def _stringify(value: Any) -> str:
+    """把值转换为可显示字符串。"""
+
+    if value is None:
+        return "-"
+    return str(value)
+
+
+def _truncate(text: str, width: int) -> str:
+    """按列宽截断文本。"""
+
+    if width <= 0:
+        return ""
+    if len(text) <= width:
+        return text
+    if width <= 3:
+        return text[:width]
+    return text[: width - 3] + "..."
+
+
+def _pad(text: str, width: int, align: str) -> str:
+    """按对齐方式填充字符串到固定宽度。"""
+
+    text = text[:width]
+    if align == "right":
+        return text.rjust(width)
+    if align == "center":
+        return text.center(width)
+    return text.ljust(width)
+
+
+def _compute_widths(headers: List[str], rows: List[List[str]], max_col_width: int) -> List[int]:
+    """计算列宽(按最大内容宽度,受 max_col_width 限制)。"""
+
+    widths = [min(max_col_width, max(1, len(h))) for h in headers]
+    for r in rows:
+        for i, cell in enumerate(r):
+            widths[i] = min(max_col_width, max(widths[i], len(cell)))
+    return widths
+
+
+def render_table(headers: List[str], rows: List[List[str]], opt: Options) -> str:
+    """渲染 ASCII 表格。"""
+
+    if not headers:
+        return ""
+    normalized_rows = [[_stringify(c) for c in row] for row in rows]
+    for r in normalized_rows:
+        while len(r) < len(headers):
+            r.append("-")
+        if len(r) > len(headers):
+            del r[len(headers) :]
+
+    widths = _compute_widths(headers, normalized_rows, opt.max_col_width)
+
+    def cell(text: str, w: int) -> str:
+        if opt.overflow == "ellipsis":
+            text = _truncate(text, w)
+        else:
+            text = text[:w]
+        return _pad(text, w, opt.align)
+
+    def sep(ch: str = "-") -> str:
+        if opt.border == "minimal":
+            return ""
+        return "+" + "+".join((ch * (w + 2)) for w in widths) + "+"
+
+    def row_line(vals: List[str]) -> str:
+        if opt.border == "minimal":
+            return "  ".join(cell(v, w) for v, w in zip(vals, widths))
+        return "| " + " | ".join(cell(v, w) for v, w in zip(vals, widths)) + " |"
+
+    lines: List[str] = []
+    if opt.border != "minimal":
+        lines.append(sep("-"))
+    lines.append(row_line(headers))
+    if opt.border == "minimal":
+        lines.append("-" * min(opt.max_width, max(10, sum(widths) + (len(widths) - 1) * 2)))
+    else:
+        lines.append(sep("-"))
+    for r in normalized_rows:
+        lines.append(row_line(r))
+    if opt.border != "minimal" and opt.fmt == "readable":
+        lines.append(sep("-"))
+
+    out = "\n".join(lines)
+    # maxWidth 只做保底截断(避免极端输入刷屏)
+    return "\n".join(line[: opt.max_width].rstrip() for line in out.splitlines()).rstrip()
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+    """程序入口:从 stdin 读取 JSON 并输出表格。"""
+
+    opt = parse_args(argv)
+    raw = sys.stdin.read().strip()
+    if not raw:
+        print("Error: empty stdin. Provide JSON with headers and rows.", file=sys.stderr)
+        return 1
+    data = json.loads(raw)
+    headers = [str(x) for x in data.get("headers", [])]
+    rows = data.get("rows", [])
+    if not isinstance(rows, list):
+        print("Error: rows must be a list.", file=sys.stderr)
+        return 1
+    str_rows: List[List[str]] = [[_stringify(c) for c in (row if isinstance(row, list) else [row])] for row in rows]
+    print(render_table(headers, str_rows, opt))
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 202 - 0
skills/ascii-terminal-animation-pack/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 54 - 0
skills/ascii-terminal-animation-pack/SKILL.md

@@ -0,0 +1,54 @@
+---
+name: ascii-terminal-animation-pack
+description: Plan and generate terminal ASCII animations/screensaver-style output (FPS, refresh rules, loop policy, low-flicker guidance), with a static poster frame and an optional local demo script.
+license: Complete terms in LICENSE.txt
+dependencies:
+  - python>=3.8
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-terminal-animation-pack`.
+
+**Trigger phrases include:**
+- "ascii-terminal-animation-pack"
+- "use ascii-terminal-animation-pack"
+- "用 ascii-terminal-animation-pack 做终端动画"
+- "使用 ascii-terminal-animation-pack 生成矩阵雨 demo"
+
+## Boundary
+- Animations must be explicitly triggered demos. Never default to animated output in normal logs.
+- Must provide an ASCII-only static poster frame for README/tickets.
+- Must provide disable guidance: skip animations for non-interactive / redirected output.
+
+## How to use this skill
+### Inputs
+- theme (matrix | waves | custom, default matrix)
+- width (default 80)
+- height (default 24)
+- fps (default 10)
+- durationSeconds (default 3)
+- loop (default false)
+- colorMode (none | ansi256, default ansi256)
+
+### Outputs (required)
+- animationSpec (refresh rules, FPS, loop policy, disable conditions)
+- staticPosterFrame (ASCII-only)
+- safetyNotes (exit/disable guidance, avoid log spam)
+
+## Script
+- `scripts/matrix_demo.py`: best-effort matrix rain demo (short-run, TTY-only)
+
+## Examples
+- `examples/spec.md`
+- `examples/poster.md`
+
+## Quality checklist
+1. Non-spam by default: short duration, easy exit, disabled for non-interactive output
+2. Static frame is ASCII-only and copy/paste safe
+3. Animated output should not mix with normal application logs (recommend separate command or stream)
+
+## Keywords
+**English:** ascii-terminal-animation-pack, terminal animation, ascii animation, matrix rain, demo, fps, non-interactive
+**中文:** ascii-terminal-animation-pack, 终端动画, ASCII 动效, 矩阵雨, 演示, 帧率, 非交互禁用

+ 12 - 0
skills/ascii-terminal-animation-pack/examples/poster.md

@@ -0,0 +1,12 @@
+# ascii-terminal-animation-pack:静态海报帧示例(ASCII-only)
+
+```
+  .-.
+ (o o)  PartmeAI Terminal Demo
+  |=|   -----------------------
+ __|__  Press 'q' to quit (demo)
+```
+
+## Notes
+- 静态帧用于 README/工单/邮件等纯文本环境
+- 动画仅应在显式 demo 命令下运行

+ 17 - 0
skills/ascii-terminal-animation-pack/examples/spec.md

@@ -0,0 +1,17 @@
+# ascii-terminal-animation-pack:动画规格示例(matrix)
+
+## animationSpec(建议)
+- theme: matrix
+- width: 80
+- height: 24
+- fps: 10(8-15 更舒适)
+- durationSeconds: 3(demo 默认短时)
+- loop: false(默认不循环)
+- 禁用条件:
+  - 非交互终端(stdout 不是 TTY)
+  - 输出重定向到文件
+  - 用户显式设置 NO_COLOR / --no-ansi(可选语义)
+
+## Refresh strategy(低闪烁)
+- 避免频繁全屏清空;尽量使用“光标定位 + 局部重绘”
+- 帧间隔 = 1 / fps;不要超过 20fps

+ 111 - 0
skills/ascii-terminal-animation-pack/scripts/matrix_demo.py

@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+import random
+import sys
+import time
+from dataclasses import dataclass
+from typing import Sequence
+
+
+@dataclass(frozen=True)
+class Options:
+    """矩阵雨演示参数(短时运行)。"""
+
+    width: int
+    height: int
+    fps: int
+    seconds: float
+    ansi256: bool
+
+
+def parse_args(argv: Sequence[str] | None = None) -> Options:
+    """解析命令行参数。"""
+
+    p = argparse.ArgumentParser(description="Matrix rain demo (short-run).")
+    p.add_argument("--width", type=int, default=80)
+    p.add_argument("--height", type=int, default=24)
+    p.add_argument("--fps", type=int, default=10)
+    p.add_argument("--seconds", type=float, default=3.0)
+    p.add_argument("--ansi256", action="store_true", help="Enable ANSI 256 green (best-effort)")
+    ns = p.parse_args(argv)
+    return Options(
+        width=max(20, ns.width),
+        height=max(10, ns.height),
+        fps=max(1, min(30, ns.fps)),
+        seconds=max(0.5, ns.seconds),
+        ansi256=bool(ns.ansi256),
+    )
+
+
+def _is_tty() -> bool:
+    """判断 stdout 是否为交互终端。"""
+
+    return sys.stdout.isatty()
+
+
+def _ansi(code: int) -> str:
+    """ANSI 256 前景色。"""
+
+    return f"\x1b[38;5;{code}m"
+
+
+def _reset() -> str:
+    """ANSI reset。"""
+
+    return "\x1b[0m"
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+    """程序入口:仅在 TTY 中运行,避免刷屏日志。"""
+
+    opt = parse_args(argv)
+    if not _is_tty():
+        print("Non-interactive output detected. Skip animation.", file=sys.stderr)
+        return 0
+
+    charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+    drops = [random.randint(0, opt.height - 1) for _ in range(opt.width)]
+    start = time.time()
+    frame_delay = 1.0 / opt.fps
+    reset = _reset()
+    green = _ansi(46)  # bright green
+
+    # 清屏 + 隐藏光标
+    sys.stdout.write("\x1b[2J\x1b[?25l")
+    sys.stdout.flush()
+    try:
+        while time.time() - start < opt.seconds:
+            # 光标回到左上角
+            sys.stdout.write("\x1b[H")
+            lines = []
+            for y in range(opt.height):
+                row = []
+                for x in range(opt.width):
+                    if drops[x] == y:
+                        ch = random.choice(charset)
+                        if opt.ansi256:
+                            row.append(green + ch + reset)
+                        else:
+                            row.append(ch)
+                    else:
+                        row.append(" ")
+                lines.append("".join(row))
+            sys.stdout.write("\n".join(lines))
+            sys.stdout.flush()
+
+            # 更新 drop
+            for x in range(opt.width):
+                if random.random() < 0.2:
+                    drops[x] = (drops[x] + 1) % opt.height
+            time.sleep(frame_delay)
+        return 0
+    finally:
+        # 显示光标 + reset
+        sys.stdout.write("\x1b[?25h" + reset + "\n")
+        sys.stdout.flush()
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 202 - 0
skills/ascii-text-art-library/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 51 - 0
skills/ascii-text-art-library/SKILL.md

@@ -0,0 +1,51 @@
+---
+name: ascii-text-art-library
+description: Generate a reusable ASCII-only text template library (titles, dividers, notice boxes, slogans/CTA), with naming conventions and selection rules for consistent CLI/log/README output.
+license: Complete terms in LICENSE.txt
+dependencies:
+  - python>=3.8
+---
+
+
+## When to use this skill
+**CRITICAL TRIGGER RULE**
+- Use this skill ONLY when the user explicitly mentions the exact skill name: `ascii-text-art-library`.
+
+**Trigger phrases include:**
+- "ascii-text-art-library"
+- "use ascii-text-art-library"
+- "用 ascii-text-art-library 生成 ASCII 模板库"
+- "使用 ascii-text-art-library 输出提示框/分隔线/标题样式"
+
+## Boundary
+- Output templates + naming/selection rules only; do not modify repository files.
+- ASCII-only by default to avoid ambiguous-width Unicode.
+- Templates must be width-tunable (default 80 columns).
+
+## How to use this skill
+### Inputs
+- width (default 80)
+- language (zh | en, default zh)
+- tone (serious | fun, default serious)
+- categories (title/divider/info/warn/error/success/cta, default all)
+- variantsPerCategory (default 2)
+
+### Outputs (required)
+- templates: grouped by category (>= 2 variants per category)
+- namingRules: e.g. `TITLE_COMPACT_A`, `WARN_BOX_B`
+- usageRules: selection guidance + anti-spam thresholds
+
+## Script
+- `scripts/generate_templates.py`: generate a baseline template set for a given width (local preview)
+
+## Examples
+- `examples/templates-80.md`
+
+## Quality checklist
+1. Stable alignment at 80 columns; no trailing spaces
+2. Templates are semantically clear and not over-decorated
+3. Notice boxes support multi-line content and remain readable
+
+## Keywords
+**English:** ascii-text-art-library, templates, ascii, divider, banner, notice box, warning, error, success, plain text
+**中文:** ascii-text-art-library, 模板库, ASCII, 分隔线, 标题, 提示框, 警告, 错误, 成功, 纯文本

+ 60 - 0
skills/ascii-text-art-library/examples/templates-80.md

@@ -0,0 +1,60 @@
+# ascii-text-art-library:80 列模板示例(ASCII-only)
+
+## Titles
+
+```
+============================== PartmeAI ==============================
+```
+
+```
+--- PartmeAI ----------------------------------------------------------
+```
+
+## Dividers
+
+```
+--------------------------------------------------------------------------------
+```
+
+```
+===============================================================================
+```
+
+## Notice boxes
+
+INFO:
+
+```
++------------------------------------------------------------------------------+
+| INFO:                                                                        |
+| - This is an informational message.                                          |
+| - Keep it short and actionable.                                              |
++------------------------------------------------------------------------------+
+```
+
+WARN:
+
+```
++------------------------------------------------------------------------------+
+| WARN:                                                                        |
+| - Do NOT paste tokens here.                                                  |
++------------------------------------------------------------------------------+
+```
+
+ERROR:
+
+```
++------------------------------------------------------------------------------+
+| ERROR:                                                                       |
+| - Operation failed. Check logs and retry.                                    |
++------------------------------------------------------------------------------+
+```
+
+SUCCESS:
+
+```
++------------------------------------------------------------------------------+
+| SUCCESS:                                                                     |
+| - Completed successfully.                                                    |
++------------------------------------------------------------------------------+
+```

+ 79 - 0
skills/ascii-text-art-library/scripts/generate_templates.py

@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+from dataclasses import dataclass
+from typing import Sequence
+
+
+@dataclass(frozen=True)
+class Options:
+    """模板生成参数。"""
+
+    width: int
+    title: str
+
+
+def parse_args(argv: Sequence[str] | None = None) -> Options:
+    """解析命令行参数。"""
+
+    p = argparse.ArgumentParser(description="Generate ASCII-only text templates.")
+    p.add_argument("--width", type=int, default=80)
+    p.add_argument("--title", default="PartmeAI")
+    ns = p.parse_args(argv)
+    return Options(width=max(40, ns.width), title=str(ns.title))
+
+
+def hr(width: int, ch: str) -> str:
+    """生成水平分隔线。"""
+
+    return (ch or "-")[0] * max(0, width)
+
+
+def title_line(title: str, width: int, ch: str) -> str:
+    """生成标题行(居中)。"""
+
+    title = f" {title.strip()} "
+    if len(title) >= width:
+        return title[:width]
+    left = (width - len(title)) // 2
+    right = width - len(title) - left
+    return (ch * left) + title + (ch * right)
+
+
+def box(title: str, bullets: list[str], width: int) -> str:
+    """生成提示框。"""
+
+    inner = max(10, width - 4)
+    top = "+" + "-" * (width - 2) + "+"
+    lines = [top]
+    header = (title + ":").ljust(inner)[:inner]
+    lines.append("| " + header + " |")
+    for b in bullets:
+        msg = ("- " + b).ljust(inner)[:inner]
+        lines.append("| " + msg + " |")
+    lines.append(top)
+    return "\n".join(lines)
+
+
+def main(argv: Sequence[str] | None = None) -> int:
+    """程序入口:输出一套基础模板。"""
+
+    opt = parse_args(argv)
+    print(title_line(opt.title, opt.width, "="))
+    print(title_line(opt.title, opt.width, "-"))
+    print(hr(opt.width, "-"))
+    print(hr(opt.width, "="))
+    print()
+    print(box("INFO", ["This is an informational message.", "Keep it short and actionable."], opt.width))
+    print()
+    print(box("WARN", ["Do NOT paste tokens here."], opt.width))
+    print()
+    print(box("ERROR", ["Operation failed. Check logs and retry."], opt.width))
+    print()
+    print(box("SUCCESS", ["Completed successfully."], opt.width))
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 68 - 0
skills/cli-ascii-logo/SKILL.md

@@ -0,0 +1,68 @@
+---
+name: cli-ascii-logo
+description: 生成 CLI 的 ASCII 艺术 Logo/Banner(支持 box drawing 边框、█ 块字符、ANSI 24-bit 渐变色)并提供可运行脚本与集成代码。适用于“做一个像 Spec Kit CLI 的终端 Logo / 彩色 ASCII banner / figlet 风格标题 / CLI 启动欢迎页”等需求。
+---
+
+# CLI ASCII Logo
+
+## 目标
+
+- 生成可直接在终端输出的 ASCII 艺术 Logo(含边框与渐变色)
+- 输出“可复制粘贴”的结果(纯文本/带 ANSI 颜色),并提供在 CLI 启动时展示的集成方式
+- 提供可运行的生成脚本:`scripts/generate_logo.py`
+
+## 工作流
+
+1. 明确输入
+   - 名称:如 `auto-cli`
+   - 副标题:如 `Command Line Interface`
+   - 终端宽度:默认 80(可根据项目/CI 输出调整)
+   - 风格:粗块(`█`)/ 细线条(`#`/`*`)/ 无颜色
+   - 边框:`╔═╗║ ║╚═╝` 或纯文本
+   - 配色:青 → 紫(Spec Kit 风格)、青 → 蓝、橙 → 粉等
+
+2. 生成结果
+   - 直接运行脚本生成(最可靠):见下方“快速开始”
+   - 或按需在目标语言里生成(Node/Python/Go),核心是:
+     - 先得到“等宽字符画”(多行字符串)
+     - 再做边框拼接
+     - 再做逐字符渐变(输出 ANSI TrueColor 序列)
+
+3. 集成到 CLI
+   - 运行入口(`main`/`bin`/`__main__`)启动时输出一次
+   - 支持禁用颜色:
+     - 尊重 `NO_COLOR=1`
+     - 提供 `--no-color` 参数
+     - CI 环境默认关闭(可按需打开)
+
+## 快速开始(脚本)
+
+在支持 TrueColor 的终端(macOS Terminal / iTerm2 / VS Code 终端)效果最佳。
+
+```bash
+python3 scripts/generate_logo.py --text auto-cli --subtitle "Command Line Interface"
+```
+
+常用参数:
+
+```bash
+python3 scripts/generate_logo.py \
+  --text auto-cli \
+  --subtitle "Command Line Interface" \
+  --width 46 \
+  --palette spec-kit \
+  --frame box
+```
+
+## 交付格式
+
+- 纯文本(无颜色):适合 README / 日志 / 不支持 ANSI 的环境
+- ANSI 颜色文本:适合 CLI 启动页(建议提供 `--no-color` 切换)
+- 建议同时提供:
+  - `banner.txt`(无颜色)
+  - `banner.ansi.txt`(带颜色)
+  - `renderBanner()`(在你的 CLI 里按环境输出)
+
+## 参考
+
+- 配色与兼容性建议见 [palettes.md](references/palettes.md)

+ 22 - 0
skills/cli-ascii-logo/references/palettes.md

@@ -0,0 +1,22 @@
+# 配色与兼容性
+
+## 内置配色(`--palette`)
+
+- `spec-kit`:青 → 紫(推荐,用于 Spec Kit 风格)
+- `cyan-purple`:青 → 紫(更偏紫)
+- `cyan-blue`:青 → 蓝
+- `orange-pink`:橙 → 粉
+- `green-cyan`:绿 → 青
+- `mono`:单色白(也可用于调试)
+
+## 颜色开关建议
+
+- 通过 `--no-color` 显式关闭颜色
+- 尊重 `NO_COLOR=1`(脚本默认遵守)
+- 在 CI / 日志场景建议默认关闭,必要时用 `--force-color` 打开
+
+## 终端兼容性
+
+- ANSI TrueColor(24-bit)在 macOS Terminal、iTerm2、VS Code 终端中通常可用
+- 如果用户终端只支持 256 色,TrueColor 也可能“看起来还行”,但渐变会变粗糙
+

+ 577 - 0
skills/cli-ascii-logo/scripts/generate_logo.py

@@ -0,0 +1,577 @@
+#!/usr/bin/env python3
+"""
+Generate a Spec-Kit-like ASCII logo/banner for CLI tools.
+
+This script renders a small block font, optionally wraps it in a box frame,
+and optionally applies a 24-bit ANSI gradient for terminals that support it.
+"""
+
+from __future__ import annotations
+
+import argparse
+import os
+import sys
+from dataclasses import dataclass
+from typing import Dict, Iterable, List, Tuple
+
+
+RGB = Tuple[int, int, int]
+
+
+@dataclass(frozen=True)
+class Palette:
+    """Represents a gradient palette from start RGB to end RGB."""
+
+    start: RGB
+    end: RGB
+
+
+def clamp_u8(value: int) -> int:
+    """Clamp an integer to the [0, 255] range."""
+
+    return max(0, min(255, int(value)))
+
+
+def lerp(a: float, b: float, t: float) -> float:
+    """Linearly interpolate between a and b by t (0..1)."""
+
+    return a + (b - a) * t
+
+
+def lerp_rgb(start: RGB, end: RGB, t: float) -> RGB:
+    """Linearly interpolate between two RGB colors by t (0..1)."""
+
+    r = clamp_u8(round(lerp(start[0], end[0], t)))
+    g = clamp_u8(round(lerp(start[1], end[1], t)))
+    b = clamp_u8(round(lerp(start[2], end[2], t)))
+    return (r, g, b)
+
+
+def ansi_fg(rgb: RGB) -> str:
+    """Return an ANSI escape sequence for 24-bit foreground color."""
+
+    r, g, b = rgb
+    return f"\x1b[38;2;{r};{g};{b}m"
+
+
+def ansi_reset() -> str:
+    """Return an ANSI reset escape sequence."""
+
+    return "\x1b[0m"
+
+
+def default_palettes() -> Dict[str, Palette]:
+    """Return built-in palette presets."""
+
+    return {
+        "spec-kit": Palette((0, 255, 204), (153, 102, 255)),
+        "cyan-purple": Palette((0, 230, 255), (170, 0, 255)),
+        "cyan-blue": Palette((0, 255, 204), (0, 120, 255)),
+        "orange-pink": Palette((255, 153, 51), (255, 51, 153)),
+        "green-cyan": Palette((80, 255, 120), (0, 255, 255)),
+        "mono": Palette((255, 255, 255), (255, 255, 255)),
+    }
+
+
+def supports_color(force: bool, no_color: bool) -> bool:
+    """Decide whether ANSI coloring should be enabled."""
+
+    if force:
+        return True
+    if no_color:
+        return False
+    if os.environ.get("NO_COLOR"):
+        return False
+    return sys.stdout.isatty()
+
+
+def block_font() -> Dict[str, List[str]]:
+    """Return a 5x7 block font mapping for A-Z, 0-9, dash, and space."""
+
+    return {
+        "A": [
+            " ███ ",
+            "█   █",
+            "█   █",
+            "█████",
+            "█   █",
+            "█   █",
+            "█   █",
+        ],
+        "B": [
+            "████ ",
+            "█   █",
+            "█   █",
+            "████ ",
+            "█   █",
+            "█   █",
+            "████ ",
+        ],
+        "C": [
+            " ████",
+            "█    ",
+            "█    ",
+            "█    ",
+            "█    ",
+            "█    ",
+            " ████",
+        ],
+        "D": [
+            "████ ",
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+            "████ ",
+        ],
+        "E": [
+            "█████",
+            "█    ",
+            "█    ",
+            "████ ",
+            "█    ",
+            "█    ",
+            "█████",
+        ],
+        "F": [
+            "█████",
+            "█    ",
+            "█    ",
+            "████ ",
+            "█    ",
+            "█    ",
+            "█    ",
+        ],
+        "G": [
+            " ████",
+            "█    ",
+            "█    ",
+            "█ ███",
+            "█   █",
+            "█   █",
+            " ████",
+        ],
+        "H": [
+            "█   █",
+            "█   █",
+            "█   █",
+            "█████",
+            "█   █",
+            "█   █",
+            "█   █",
+        ],
+        "I": [
+            "█████",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+            "█████",
+        ],
+        "J": [
+            "█████",
+            "   █ ",
+            "   █ ",
+            "   █ ",
+            "   █ ",
+            "█  █ ",
+            " ██  ",
+        ],
+        "K": [
+            "█   █",
+            "█  █ ",
+            "█ █  ",
+            "██   ",
+            "█ █  ",
+            "█  █ ",
+            "█   █",
+        ],
+        "L": [
+            "█    ",
+            "█    ",
+            "█    ",
+            "█    ",
+            "█    ",
+            "█    ",
+            "█████",
+        ],
+        "M": [
+            "█   █",
+            "██ ██",
+            "█ █ █",
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+        ],
+        "N": [
+            "█   █",
+            "██  █",
+            "█ █ █",
+            "█  ██",
+            "█   █",
+            "█   █",
+            "█   █",
+        ],
+        "O": [
+            " ███ ",
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+            " ███ ",
+        ],
+        "P": [
+            "████ ",
+            "█   █",
+            "█   █",
+            "████ ",
+            "█    ",
+            "█    ",
+            "█    ",
+        ],
+        "Q": [
+            " ███ ",
+            "█   █",
+            "█   █",
+            "█   █",
+            "█ █ █",
+            "█  █ ",
+            " ██ █",
+        ],
+        "R": [
+            "████ ",
+            "█   █",
+            "█   █",
+            "████ ",
+            "█ █  ",
+            "█  █ ",
+            "█   █",
+        ],
+        "S": [
+            " ████",
+            "█    ",
+            "█    ",
+            " ███ ",
+            "    █",
+            "    █",
+            "████ ",
+        ],
+        "T": [
+            "█████",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+        ],
+        "U": [
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+            " ███ ",
+        ],
+        "V": [
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+            " █ █ ",
+            "  █  ",
+        ],
+        "W": [
+            "█   █",
+            "█   █",
+            "█   █",
+            "█   █",
+            "█ █ █",
+            "██ ██",
+            "█   █",
+        ],
+        "X": [
+            "█   █",
+            "█   █",
+            " █ █ ",
+            "  █  ",
+            " █ █ ",
+            "█   █",
+            "█   █",
+        ],
+        "Y": [
+            "█   █",
+            "█   █",
+            " █ █ ",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+        ],
+        "Z": [
+            "█████",
+            "    █",
+            "   █ ",
+            "  █  ",
+            " █   ",
+            "█    ",
+            "█████",
+        ],
+        "0": [
+            " ███ ",
+            "█   █",
+            "█  ██",
+            "█ █ █",
+            "██  █",
+            "█   █",
+            " ███ ",
+        ],
+        "1": [
+            "  █  ",
+            " ██  ",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+            "  █  ",
+            " ███ ",
+        ],
+        "2": [
+            " ███ ",
+            "█   █",
+            "    █",
+            "   █ ",
+            "  █  ",
+            " █   ",
+            "█████",
+        ],
+        "3": [
+            "████ ",
+            "    █",
+            "    █",
+            " ███ ",
+            "    █",
+            "    █",
+            "████ ",
+        ],
+        "4": [
+            "█   █",
+            "█   █",
+            "█   █",
+            "█████",
+            "    █",
+            "    █",
+            "    █",
+        ],
+        "5": [
+            "█████",
+            "█    ",
+            "█    ",
+            "████ ",
+            "    █",
+            "    █",
+            "████ ",
+        ],
+        "6": [
+            " ███ ",
+            "█    ",
+            "█    ",
+            "████ ",
+            "█   █",
+            "█   █",
+            " ███ ",
+        ],
+        "7": [
+            "█████",
+            "    █",
+            "   █ ",
+            "  █  ",
+            " █   ",
+            " █   ",
+            " █   ",
+        ],
+        "8": [
+            " ███ ",
+            "█   █",
+            "█   █",
+            " ███ ",
+            "█   █",
+            "█   █",
+            " ███ ",
+        ],
+        "9": [
+            " ███ ",
+            "█   █",
+            "█   █",
+            " ████",
+            "    █",
+            "    █",
+            " ███ ",
+        ],
+        "-": [
+            "     ",
+            "     ",
+            "     ",
+            "█████",
+            "     ",
+            "     ",
+            "     ",
+        ],
+        " ": [
+            "     ",
+            "     ",
+            "     ",
+            "     ",
+            "     ",
+            "     ",
+            "     ",
+        ],
+        "?": [
+            "████ ",
+            "    █",
+            "   █ ",
+            "  █  ",
+            "  █  ",
+            "     ",
+            "  █  ",
+        ],
+    }
+
+
+def normalize_text(text: str) -> str:
+    """Normalize text for the internal font renderer."""
+
+    return (text or "").upper()
+
+
+def render_block_text(text: str, font: Dict[str, List[str]]) -> List[str]:
+    """Render text using the built-in 5x7 block font."""
+
+    normalized = normalize_text(text)
+    glyphs = [font.get(ch, font["?"]) for ch in normalized]
+    height = len(font["A"])
+    lines: List[str] = []
+    for row in range(height):
+        parts = [g[row] for g in glyphs]
+        lines.append(" ".join(parts).rstrip())
+    return trim_trailing_blank_lines(lines)
+
+
+def trim_trailing_blank_lines(lines: List[str]) -> List[str]:
+    """Trim empty lines at the end of a multi-line block."""
+
+    while lines and not lines[-1].strip():
+        lines.pop()
+    return lines
+
+
+def pad_to_width(line: str, width: int) -> str:
+    """Right-pad a line with spaces to the requested width."""
+
+    if len(line) >= width:
+        return line[:width]
+    return line + (" " * (width - len(line)))
+
+
+def box_frame(lines: List[str], width: int) -> List[str]:
+    """Wrap lines in a box frame using box-drawing characters."""
+
+    inner_width = max(1, width)
+    top = "╔" + ("═" * inner_width) + "╗"
+    bottom = "╚" + ("═" * inner_width) + "╝"
+    framed = [top]
+    for line in lines:
+        framed.append("║" + pad_to_width(line, inner_width) + "║")
+    framed.append(bottom)
+    return framed
+
+
+def center_line(line: str, width: int) -> str:
+    """Center a line inside a fixed width with space padding."""
+
+    if width <= 0:
+        return line
+    text = line.rstrip()
+    if len(text) >= width:
+        return text[:width]
+    left = (width - len(text)) // 2
+    right = width - len(text) - left
+    return (" " * left) + text + (" " * right)
+
+
+def apply_gradient(line: str, palette: Palette) -> str:
+    """Apply an ANSI foreground gradient to a single line."""
+
+    length = len(line)
+    if length == 0:
+        return line
+    colored: List[str] = []
+    for i, ch in enumerate(line):
+        t = 0.0 if length == 1 else (i / (length - 1))
+        rgb = lerp_rgb(palette.start, palette.end, t)
+        if ch == " ":
+            colored.append(ch)
+        else:
+            colored.append(ansi_fg(rgb) + ch)
+    return "".join(colored) + ansi_reset()
+
+
+def parse_args(argv: Iterable[str]) -> argparse.Namespace:
+    """Parse CLI arguments."""
+
+    parser = argparse.ArgumentParser(prog="generate_logo.py")
+    parser.add_argument("--text", required=True, help="Logo text, e.g. auto-cli")
+    parser.add_argument("--subtitle", default="", help="Subtitle line under the logo")
+    parser.add_argument("--width", type=int, default=46, help="Inner width of the frame")
+    parser.add_argument("--palette", default="spec-kit", help="Palette preset name")
+    parser.add_argument("--frame", choices=["box", "none"], default="box", help="Frame style")
+    parser.add_argument("--no-color", action="store_true", help="Disable ANSI colors")
+    parser.add_argument("--force-color", action="store_true", help="Force ANSI colors even when not TTY")
+    return parser.parse_args(list(argv))
+
+
+def build_banner_lines(text: str, subtitle: str, width: int) -> Tuple[List[str], int]:
+    """Build the uncolored inner lines for the banner and return (lines, inner_width)."""
+
+    font = block_font()
+    logo_lines = render_block_text(text, font)
+    max_inner = max((len(l) for l in logo_lines), default=0)
+    inner_width = max(width, max_inner)
+
+    centered_logo = [center_line(l, inner_width) for l in logo_lines]
+    lines: List[str] = list(centered_logo)
+    if subtitle.strip():
+        lines.append(center_line(subtitle.strip(), inner_width))
+    return lines, inner_width
+
+
+def main(argv: Iterable[str]) -> int:
+    """Program entry point."""
+
+    args = parse_args(argv)
+    palettes = default_palettes()
+    palette = palettes.get(args.palette, palettes["spec-kit"])
+    use_color = supports_color(force=args.force_color, no_color=args.no_color)
+
+    inner_lines, inner_width = build_banner_lines(args.text, args.subtitle, args.width)
+
+    if args.frame == "box":
+        output_lines = box_frame(inner_lines, inner_width)
+        if use_color:
+            output_lines = [apply_gradient(line, palette) for line in output_lines]
+    else:
+        output_lines = inner_lines
+        if use_color:
+            output_lines = [apply_gradient(line, palette) for line in output_lines]
+
+    sys.stdout.write("\n".join(output_lines) + "\n")
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main(sys.argv[1:]))

+ 42 - 0
skills/skill-installer/SKILL.md

@@ -0,0 +1,42 @@
+---
+name: skill-installer
+description: Manages the installation and discovery of AI skills from the PartMe marketplace.
+---
+
+# Skill Installer
+
+## Overview
+
+The `skill-installer` is a core utility skill that allows users and agents to discover, install, and manage other AI skills within the PartMe ecosystem. It serves as the local package manager for the "Knowledge as a Service" (KaaS) and "Tool as a Service" (TaaS) architecture.
+
+## Features
+
+- **Search Skills**: Query the local marketplace for available skills by keyword.
+- **Install Skills**: Register skills into the local environment.
+- **List Installed Skills**: View currently active skills.
+
+## Usage
+
+### Search for a skill
+```
+skill-installer(action="search_skills", query="vue")
+```
+
+### Install a skill
+```
+skill-installer(action="install_skill", skill_path="./skills/vue3")
+```
+
+## Tools
+
+### `search_skills`
+- **Input**: `query` (string)
+- **Output**: JSON list of matching skills with descriptions and paths.
+
+### `install_skill`
+- **Input**: `skill_path` (string)
+- **Output**: Confirmation of installation.
+
+### `list_installed_skills`
+- **Input**: None
+- **Output**: JSON list of installed skills.

+ 3 - 0
skills/skill-installer/index.d.ts

@@ -0,0 +1,3 @@
+#!/usr/bin/env node
+export {};
+//# sourceMappingURL=index.d.ts.map

+ 1 - 0
skills/skill-installer/index.d.ts.map

@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":""}

+ 161 - 0
skills/skill-installer/index.js

@@ -0,0 +1,161 @@
+#!/usr/bin/env node
+import { Server } from "@modelcontextprotocol/sdk/server/index.js";
+import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
+import { CallToolRequestSchema, ListToolsRequestSchema, Tool, } from "@modelcontextprotocol/sdk/types.js";
+import { z } from "zod";
+import fs from "fs/promises";
+import path from "path";
+import { fileURLToPath } from "url";
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+// Define the path to marketplace.json
+// Assuming structure: full-stack-skills/skills/skill-installer/index.ts
+// Marketplace: full-stack-skills/.claude-plugin/marketplace.json
+const MARKETPLACE_PATH = path.resolve(__dirname, "../../.claude-plugin/marketplace.json");
+// Quick hack: The current marketplace.json only lists paths.
+// We will simulate a "Rich Marketplace" by reading the SKILL.md of each referenced skill.
+const server = new Server({
+    name: "skill-installer",
+    version: "1.0.0",
+}, {
+    capabilities: {
+        tools: {},
+    },
+});
+async function getMarketplaceSkills() {
+    try {
+        const data = await fs.readFile(MARKETPLACE_PATH, "utf-8");
+        const marketplace = JSON.parse(data);
+        // The current marketplace.json has a "skills" array of strings (paths)
+        // We need to resolve these paths to get names and descriptions from SKILL.md or package.json
+        const skillsList = [];
+        for (const skillPath of marketplace.skills) {
+            // skillPath is like "./skills/skill-creator"
+            // Resolve absolute path
+            const absoluteSkillPath = path.resolve(path.dirname(MARKETPLACE_PATH), skillPath);
+            try {
+                // Try reading SKILL.md
+                const skillMdPath = path.join(absoluteSkillPath, "SKILL.md");
+                const skillMdContent = await fs.readFile(skillMdPath, "utf-8");
+                // Extract name and description from SKILL.md (naively)
+                // Usually SKILL.md starts with # Name\n\n> Description
+                const lines = skillMdContent.split("\n");
+                let name = path.basename(skillPath);
+                let description = "No description available";
+                for (const line of lines) {
+                    if (line.startsWith("# ")) {
+                        name = line.substring(2).trim();
+                    }
+                    else if (line.trim().length > 0 && !line.startsWith("#") && description === "No description available") {
+                        // First non-header line is description
+                        description = line.trim();
+                    }
+                }
+                skillsList.push({
+                    name,
+                    description,
+                    path: skillPath
+                });
+            }
+            catch (e) {
+                console.error(`Failed to read metadata for ${skillPath}`, e);
+            }
+        }
+        return skillsList;
+    }
+    catch (error) {
+        console.error("Failed to read marketplace.json", error);
+        return [];
+    }
+}
+server.setRequestHandler(ListToolsRequestSchema, async () => {
+    return {
+        tools: [
+            {
+                name: "search_skills",
+                description: "Search for available AI skills in the PartMe marketplace",
+                inputSchema: {
+                    type: "object",
+                    properties: {
+                        query: {
+                            type: "string",
+                            description: "Search query (e.g., 'finance', 'image generation')",
+                        },
+                    },
+                    required: ["query"],
+                },
+            },
+            {
+                name: "install_skill",
+                description: "Install a skill from the marketplace",
+                inputSchema: {
+                    type: "object",
+                    properties: {
+                        skill_name: {
+                            type: "string",
+                            description: "The exact name or path of the skill to install",
+                        },
+                    },
+                    required: ["skill_name"],
+                },
+            },
+            {
+                name: "list_installed_skills",
+                description: "List currently installed skills",
+                inputSchema: {
+                    type: "object",
+                    properties: {},
+                },
+            },
+        ],
+    };
+});
+server.setRequestHandler(CallToolRequestSchema, async (request) => {
+    switch (request.params.name) {
+        case "search_skills": {
+            const query = String(request.params.arguments?.query).toLowerCase();
+            const skills = await getMarketplaceSkills();
+            const results = skills.filter((s) => s.name.toLowerCase().includes(query) ||
+                s.description.toLowerCase().includes(query));
+            return {
+                content: [
+                    {
+                        type: "text",
+                        text: JSON.stringify(results, null, 2),
+                    },
+                ],
+            };
+        }
+        case "install_skill": {
+            const skillName = String(request.params.arguments?.skill_name);
+            // In a real implementation, this would run `npm install` or register the MCP server config
+            // For now, we return a success message simulating the action
+            return {
+                content: [
+                    {
+                        type: "text",
+                        text: `Successfully installed skill: ${skillName}. \n\n(Note: This is a simulation. In a real environment, this would configure the MCP client to load the new server.)`,
+                    },
+                ],
+            };
+        }
+        case "list_installed_skills": {
+            // Mock installed skills
+            return {
+                content: [
+                    {
+                        type: "text",
+                        text: JSON.stringify([
+                            { name: "skill-installer", version: "1.0.0" },
+                            { name: "skill-sop-creator", version: "1.0.0" }
+                        ], null, 2)
+                    }
+                ]
+            };
+        }
+        default:
+            throw new Error("Unknown tool");
+    }
+});
+const transport = new StdioServerTransport();
+await server.connect(transport);
+//# sourceMappingURL=index.js.map

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
skills/skill-installer/index.js.map


+ 260 - 0
skills/skill-installer/index.ts

@@ -0,0 +1,260 @@
+#!/usr/bin/env node
+import { Server } from "@modelcontextprotocol/sdk/server/index.js";
+import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
+import {
+  CallToolRequestSchema,
+  ListToolsRequestSchema,
+  type Tool,
+} from "@modelcontextprotocol/sdk/types.js";
+import { z } from "zod";
+import fs from "fs/promises";
+import path from "path";
+import { fileURLToPath } from "url";
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+
+// Define the path to marketplace.json
+// Assuming structure: full-stack-skills/skills/skill-installer/index.ts
+// Marketplace: full-stack-skills/.claude-plugin/marketplace.json
+// From dist/index.js:
+// .. -> skill-installer
+// .. -> skills
+// .. -> full-stack-skills
+const MARKETPLACE_PATH = path.resolve(__dirname, "../../../.claude-plugin/marketplace.json");
+const INSTALLED_SKILLS_PATH = path.resolve(__dirname, "../installed_skills.json");
+
+interface Skill {
+  name: string;
+  description: string;
+  path: string;
+  installed_at?: string;
+}
+
+interface Marketplace {
+  plugins: {
+    skills: string[];
+  }[];
+}
+
+const server = new Server(
+  {
+    name: "skill-installer",
+    version: "1.0.0",
+  },
+  {
+    capabilities: {
+      tools: {},
+    },
+  }
+);
+
+async function getInstalledSkills(): Promise<Skill[]> {
+  try {
+    const data = await fs.readFile(INSTALLED_SKILLS_PATH, "utf-8");
+    return JSON.parse(data) as Skill[];
+  } catch (error) {
+    // If file doesn't exist, return empty array
+    return [];
+  }
+}
+
+async function saveInstalledSkill(skill: Skill): Promise<void> {
+  const currentSkills = await getInstalledSkills();
+  // Check if already installed
+  if (!currentSkills.some(s => s.path === skill.path)) {
+    skill.installed_at = new Date().toISOString();
+    currentSkills.push(skill);
+    await fs.writeFile(INSTALLED_SKILLS_PATH, JSON.stringify(currentSkills, null, 2));
+  }
+}
+
+async function getMarketplaceSkills(): Promise<Skill[]> {
+  try {
+    const data = await fs.readFile(MARKETPLACE_PATH, "utf-8");
+    const marketplace = JSON.parse(data) as Marketplace;
+    
+    const skillsList: Skill[] = [];
+    
+    if (marketplace.plugins) {
+      for (const plugin of marketplace.plugins) {
+        if (plugin.skills) {
+          for (const skillPath of plugin.skills) {
+            // skillPath is like "./skills/vue2"
+            // Resolve absolute path relative to project root (parent of .claude-plugin)
+            const projectRoot = path.resolve(path.dirname(MARKETPLACE_PATH), "..");
+            const absoluteSkillPath = path.resolve(projectRoot, skillPath);
+            
+            try {
+              // Try reading SKILL.md
+              const skillMdPath = path.join(absoluteSkillPath, "SKILL.md");
+              // Check if file exists first to avoid throwing too many errors
+              try {
+                  await fs.access(skillMdPath);
+              } catch {
+                  continue;
+              }
+
+              const skillMdContent = await fs.readFile(skillMdPath, "utf-8");
+              
+              // Extract name and description from SKILL.md.
+              // 1) If file has YAML frontmatter (--- ... ---), parse name/description from it and use first non-# line after --- as fallback for description (Trae/simple-parser compliance).
+              // 2) Otherwise use first # line as name and first non-# line as description.
+              const lines = skillMdContent.split("\n");
+              let name = path.basename(skillPath);
+              let description = "No description available";
+              let bodyStartIndex = 0;
+              const fmMatch = skillMdContent.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
+              if (fmMatch) {
+                bodyStartIndex = fmMatch[0].split("\n").length;
+                const fm = fmMatch[1];
+                const nameM = fm.match(/^name:\s*(.+)$/m);
+                const descM = fm.match(/^description:\s*(.+)$/m);
+                if (nameM) name = nameM[1].trim().replace(/^["']|["']$/g, "");
+                if (descM) description = descM[1].trim().replace(/^["']|["']$/g, "");
+              }
+              for (let i = bodyStartIndex; i < lines.length; i++) {
+                const line = lines[i];
+                if (line.startsWith("# ")) {
+                  name = line.substring(2).trim();
+                }
+                if (description === "No description available" && line.trim().length > 0 && !line.startsWith("#")) {
+                  description = line.trim();
+                  break;
+                }
+              }
+              
+              skillsList.push({
+                name,
+                description,
+                path: skillPath
+              });
+              
+            } catch (e) {
+              console.error(`Failed to read metadata for ${skillPath}`, e);
+            }
+          }
+        }
+      }
+    }
+    
+    return skillsList;
+    
+  } catch (error) {
+    console.error("Failed to read marketplace.json", error);
+    return [];
+  }
+}
+
+server.setRequestHandler(ListToolsRequestSchema, async () => {
+  return {
+    tools: [
+      {
+        name: "search_skills",
+        description: "Search for available AI skills in the PartMe marketplace",
+        inputSchema: {
+          type: "object",
+          properties: {
+            query: {
+              type: "string",
+              description: "Search query (e.g., 'finance', 'image generation')",
+            },
+          },
+          required: ["query"],
+        },
+      },
+      {
+        name: "install_skill",
+        description: "Install a skill from the marketplace. This will verify the skill exists and register it as installed.",
+        inputSchema: {
+          type: "object",
+          properties: {
+            skill_path: {
+              type: "string",
+              description: "The path of the skill to install (e.g., './skills/vue2')",
+            },
+          },
+          required: ["skill_path"],
+        },
+      },
+      {
+        name: "list_installed_skills",
+        description: "List currently installed skills",
+        inputSchema: {
+          type: "object",
+          properties: {},
+        },
+      },
+    ],
+  };
+});
+
+server.setRequestHandler(CallToolRequestSchema, async (request) => {
+  switch (request.params.name) {
+    case "search_skills": {
+      const query = String(request.params.arguments?.query).toLowerCase();
+      const skills = await getMarketplaceSkills();
+      
+      const results = skills.filter(
+        (s) =>
+          s.name.toLowerCase().includes(query) ||
+          s.description.toLowerCase().includes(query)
+      );
+
+      return {
+        content: [
+          {
+            type: "text",
+            text: JSON.stringify(results, null, 2),
+          },
+        ],
+      };
+    }
+
+    case "install_skill": {
+      const skillPath = String(request.params.arguments?.skill_path);
+      const skills = await getMarketplaceSkills();
+      const skillToInstall = skills.find(s => s.path === skillPath);
+      
+      if (!skillToInstall) {
+         return {
+            content: [
+               {
+                 type: "text",
+                 text: `Error: Skill with path '${skillPath}' not found in marketplace.`
+               }
+            ],
+            isError: true
+         };
+      }
+      
+      await saveInstalledSkill(skillToInstall);
+      
+      return {
+        content: [
+          {
+            type: "text",
+            text: `Successfully installed skill: ${skillToInstall.name} (${skillToInstall.path}).\n\nSkill Description: ${skillToInstall.description}\n\nNote: For knowledge skills, you can now ask questions about this topic. For executable skills, they are now registered.`,
+          },
+        ],
+      };
+    }
+
+    case "list_installed_skills": {
+        const installedSkills = await getInstalledSkills();
+        return {
+            content: [
+                {
+                    type: "text",
+                    text: JSON.stringify(installedSkills, null, 2),
+                }
+            ]
+        };
+    }
+
+    default:
+      throw new Error("Unknown tool");
+  }
+});
+
+const transport = new StdioServerTransport();
+await server.connect(transport);

+ 1254 - 0
skills/skill-installer/package-lock.json

@@ -0,0 +1,1254 @@
+{
+  "name": "skill-installer",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "skill-installer",
+      "version": "1.0.0",
+      "license": "ISC",
+      "bin": {
+        "skill-installer": "dist/index.js"
+      },
+      "devDependencies": {
+        "@modelcontextprotocol/sdk": "^1.25.3",
+        "@types/node": "^25.0.10",
+        "typescript": "^5.9.3",
+        "zod": "^4.3.6"
+      }
+    },
+    "node_modules/@hono/node-server": {
+      "version": "1.19.9",
+      "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz",
+      "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.14.1"
+      },
+      "peerDependencies": {
+        "hono": "^4"
+      }
+    },
+    "node_modules/@modelcontextprotocol/sdk": {
+      "version": "1.25.3",
+      "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.3.tgz",
+      "integrity": "sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@hono/node-server": "^1.19.9",
+        "ajv": "^8.17.1",
+        "ajv-formats": "^3.0.1",
+        "content-type": "^1.0.5",
+        "cors": "^2.8.5",
+        "cross-spawn": "^7.0.5",
+        "eventsource": "^3.0.2",
+        "eventsource-parser": "^3.0.0",
+        "express": "^5.0.1",
+        "express-rate-limit": "^7.5.0",
+        "jose": "^6.1.1",
+        "json-schema-typed": "^8.0.2",
+        "pkce-challenge": "^5.0.0",
+        "raw-body": "^3.0.0",
+        "zod": "^3.25 || ^4.0",
+        "zod-to-json-schema": "^3.25.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "peerDependencies": {
+        "@cfworker/json-schema": "^4.1.1",
+        "zod": "^3.25 || ^4.0"
+      },
+      "peerDependenciesMeta": {
+        "@cfworker/json-schema": {
+          "optional": true
+        },
+        "zod": {
+          "optional": false
+        }
+      }
+    },
+    "node_modules/@types/node": {
+      "version": "25.0.10",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz",
+      "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "undici-types": "~7.16.0"
+      }
+    },
+    "node_modules/accepts": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
+      "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "mime-types": "^3.0.0",
+        "negotiator": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "8.17.1",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
+      "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3",
+        "fast-uri": "^3.0.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ajv-formats": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
+      "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ajv": "^8.0.0"
+      },
+      "peerDependencies": {
+        "ajv": "^8.0.0"
+      },
+      "peerDependenciesMeta": {
+        "ajv": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/body-parser": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
+      "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "bytes": "^3.1.2",
+        "content-type": "^1.0.5",
+        "debug": "^4.4.3",
+        "http-errors": "^2.0.0",
+        "iconv-lite": "^0.7.0",
+        "on-finished": "^2.4.1",
+        "qs": "^6.14.1",
+        "raw-body": "^3.0.1",
+        "type-is": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/bytes": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+      "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/call-bound": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+      "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "get-intrinsic": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/content-disposition": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
+      "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/content-type": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+      "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/cookie": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+      "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/cookie-signature": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
+      "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.6.0"
+      }
+    },
+    "node_modules/cors": {
+      "version": "2.8.6",
+      "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
+      "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "object-assign": "^4",
+        "vary": "^1"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/debug": {
+      "version": "4.4.3",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+      "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/depd": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/encodeurl": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+      "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/eventsource": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
+      "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "eventsource-parser": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/eventsource-parser": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz",
+      "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/express": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
+      "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "accepts": "^2.0.0",
+        "body-parser": "^2.2.1",
+        "content-disposition": "^1.0.0",
+        "content-type": "^1.0.5",
+        "cookie": "^0.7.1",
+        "cookie-signature": "^1.2.1",
+        "debug": "^4.4.0",
+        "depd": "^2.0.0",
+        "encodeurl": "^2.0.0",
+        "escape-html": "^1.0.3",
+        "etag": "^1.8.1",
+        "finalhandler": "^2.1.0",
+        "fresh": "^2.0.0",
+        "http-errors": "^2.0.0",
+        "merge-descriptors": "^2.0.0",
+        "mime-types": "^3.0.0",
+        "on-finished": "^2.4.1",
+        "once": "^1.4.0",
+        "parseurl": "^1.3.3",
+        "proxy-addr": "^2.0.7",
+        "qs": "^6.14.0",
+        "range-parser": "^1.2.1",
+        "router": "^2.2.0",
+        "send": "^1.1.0",
+        "serve-static": "^2.2.0",
+        "statuses": "^2.0.1",
+        "type-is": "^2.0.1",
+        "vary": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 18"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/express-rate-limit": {
+      "version": "7.5.1",
+      "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz",
+      "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/express-rate-limit"
+      },
+      "peerDependencies": {
+        "express": ">= 4.11"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/fast-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
+      "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fastify"
+        },
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/fastify"
+        }
+      ],
+      "license": "BSD-3-Clause"
+    },
+    "node_modules/finalhandler": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
+      "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "^4.4.0",
+        "encodeurl": "^2.0.0",
+        "escape-html": "^1.0.3",
+        "on-finished": "^2.4.1",
+        "parseurl": "^1.3.3",
+        "statuses": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/forwarded": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+      "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/fresh": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
+      "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/hono": {
+      "version": "4.11.7",
+      "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz",
+      "integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==",
+      "dev": true,
+      "license": "MIT",
+      "peer": true,
+      "engines": {
+        "node": ">=16.9.0"
+      }
+    },
+    "node_modules/http-errors": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+      "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "depd": "~2.0.0",
+        "inherits": "~2.0.4",
+        "setprototypeof": "~1.2.0",
+        "statuses": "~2.0.2",
+        "toidentifier": "~1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/iconv-lite": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+      "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/ipaddr.js": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/is-promise": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+      "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/jose": {
+      "version": "6.1.3",
+      "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz",
+      "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/panva"
+      }
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json-schema-typed": {
+      "version": "8.0.2",
+      "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz",
+      "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==",
+      "dev": true,
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/media-typer": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
+      "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/merge-descriptors": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
+      "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.54.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+      "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+      "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "mime-db": "^1.54.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/negotiator": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
+      "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/object-inspect": {
+      "version": "1.13.4",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+      "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/on-finished": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ee-first": "1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-to-regexp": {
+      "version": "8.3.0",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
+      "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/pkce-challenge": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz",
+      "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=16.20.0"
+      }
+    },
+    "node_modules/proxy-addr": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+      "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "forwarded": "0.2.0",
+        "ipaddr.js": "1.9.1"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/qs": {
+      "version": "6.14.1",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
+      "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "side-channel": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=0.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/range-parser": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/raw-body": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
+      "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "bytes": "~3.1.2",
+        "http-errors": "~2.0.1",
+        "iconv-lite": "~0.7.0",
+        "unpipe": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/require-from-string": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/router": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
+      "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "^4.4.0",
+        "depd": "^2.0.0",
+        "is-promise": "^4.0.0",
+        "parseurl": "^1.3.3",
+        "path-to-regexp": "^8.0.0"
+      },
+      "engines": {
+        "node": ">= 18"
+      }
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/send": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
+      "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "^4.4.3",
+        "encodeurl": "^2.0.0",
+        "escape-html": "^1.0.3",
+        "etag": "^1.8.1",
+        "fresh": "^2.0.0",
+        "http-errors": "^2.0.1",
+        "mime-types": "^3.0.2",
+        "ms": "^2.1.3",
+        "on-finished": "^2.4.1",
+        "range-parser": "^1.2.1",
+        "statuses": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 18"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/serve-static": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
+      "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "encodeurl": "^2.0.0",
+        "escape-html": "^1.0.3",
+        "parseurl": "^1.3.3",
+        "send": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 18"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/setprototypeof": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/side-channel": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+      "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "object-inspect": "^1.13.3",
+        "side-channel-list": "^1.0.0",
+        "side-channel-map": "^1.0.1",
+        "side-channel-weakmap": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-list": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+      "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "object-inspect": "^1.13.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-map": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+      "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.5",
+        "object-inspect": "^1.13.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-weakmap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+      "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.5",
+        "object-inspect": "^1.13.3",
+        "side-channel-map": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/statuses": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+      "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/toidentifier": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/type-is": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
+      "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "content-type": "^1.0.5",
+        "media-typer": "^1.1.0",
+        "mime-types": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.9.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/undici-types": {
+      "version": "7.16.0",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+      "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/vary": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/zod": {
+      "version": "4.3.6",
+      "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
+      "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/colinhacks"
+      }
+    },
+    "node_modules/zod-to-json-schema": {
+      "version": "3.25.1",
+      "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz",
+      "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==",
+      "dev": true,
+      "license": "ISC",
+      "peerDependencies": {
+        "zod": "^3.25 || ^4"
+      }
+    }
+  }
+}

+ 23 - 0
skills/skill-installer/package.json

@@ -0,0 +1,23 @@
+{
+  "name": "skill-installer",
+  "version": "1.0.0",
+  "main": "dist/index.js",
+  "type": "module",
+  "bin": {
+    "skill-installer": "./dist/index.js"
+  },
+  "scripts": {
+    "build": "tsc",
+    "start": "node dist/index.js"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "ISC",
+  "description": "",
+  "devDependencies": {
+    "@modelcontextprotocol/sdk": "^1.25.3",
+    "@types/node": "^25.0.10",
+    "typescript": "^5.9.3",
+    "zod": "^4.3.6"
+  }
+}

+ 16 - 0
skills/skill-installer/tsconfig.json

@@ -0,0 +1,16 @@
+{
+  "compilerOptions": {
+    "target": "ES2022",
+    "module": "NodeNext",
+    "moduleResolution": "NodeNext",
+    "outDir": "./dist",
+    "rootDir": "./",
+    "strict": true,
+    "esModuleInterop": true,
+    "skipLibCheck": true,
+    "forceConsistentCasingInFileNames": true,
+    "types": ["node"]
+  },
+  "include": ["index.ts"],
+  "exclude": ["node_modules"]
+}

+ 69 - 0
skills/skill-sop-creator/SKILL.md

@@ -0,0 +1,69 @@
+---
+name: skill-sop-creator
+description: Guide for creating Standard Operating Procedures and SOPs and composite workflows by combining atomic Agent Skills. Use when users want to design, structure, or implement multi-step workflows that orchestrate multiple skills for complex business goals. Transforms loose tool collections into reliable, repeatable business processes.
+---
+
+# skill-sop-creator
+
+Guide for creating Standard Operating Procedures (SOPs) and composite workflows by combining atomic Agent Skills. Use this skill when users want to design, structure, or implement multi-step workflows (SOPs) that orchestrate multiple skills to achieve complex business goals. This skill transforms loose collections of tools into reliable, repeatable business processes.
+
+## Parameters
+
+| Name     | Type   | Required | Description |
+|----------|--------|----------|-------------|
+| action   | string | true     | The action to perform. One of `search_skills`, `draft_sop`, `validate_sop`. |
+| context  | string | false    | Context for the action (e.g. business goal for drafting, search query for searching). |
+
+## Actions
+
+### 1. Search Atomic Skills
+Finds available atomic skills to include in your SOP.
+- **Command**: `skill-sop-creator(action="search_skills", context="pdf processing")`
+- **Output**: List of relevant atomic skills (e.g., `pdf-split`, `pdf-merge`, `ocr-extract`) that can be steps in your SOP.
+
+### 2. Draft SOP Structure
+Generates a draft `SKILL.md` for a composite skill (SOP) based on a business goal.
+- **Command**: `skill-sop-creator(action="draft_sop", context="Daily Competitor Analysis Report")`
+- **Output**: A structured markdown template defining the workflow steps, required atomic skills, and decision logic.
+
+### 3. Validate SOP
+Checks if a proposed SOP structure is valid and if referenced skills exist.
+- **Command**: `skill-sop-creator(action="validate_sop", context="<sop_content>")`
+- **Behavior**: Verifies that steps are logical and dependencies are met.
+
+## SOP Design Principles
+
+1. **Atomic Foundation**: SOPs should rely on small, single-purpose skills (e.g., `pencil-draw-rect` not `draw-entire-ui`).
+2. **Deterministic Flow**: Define clear steps: Step 1 -> Step 2 -> Decision -> Step 3.
+3. **Human-in-the-loop**: Include checkpoints where the Agent should ask for user confirmation.
+
+## Example SOP Structure
+
+```markdown
+# Daily Competitor Analysis SOP
+
+## 1. Information Gathering
+- **Skill**: `web-search`
+- **Action**: Search for "competitor name" + "news"
+- **Output**: List of URLs
+
+## 2. Content Extraction
+- **Skill**: `web-scraper`
+- **Input**: URLs from Step 1
+- **Output**: Raw text
+
+## 3. Analysis
+- **Skill**: `llm-summarize`
+- **Input**: Raw text
+- **Prompt**: "Identify key pricing changes and feature launches."
+
+## 4. Reporting
+- **Skill**: `pdf-generator`
+- **Input**: Summary
+- **Output**: PDF Report
+```
+
+## Notes
+
+- An SOP is essentially a "Composite Skill" that acts as a conductor for other "Atomic Skills".
+- This skill helps you *design* that conductor.

+ 831 - 0
tools/generate_tui_skills.py

@@ -0,0 +1,831 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import json
+from pathlib import Path
+from typing import Any, Dict, List
+
+
+ROOT = Path(__file__).resolve().parents[1]
+SKILLS_DIR = ROOT / "skills"
+# tui-skills 已迁移至 t2ui-skills 仓库;生成目标为同级 t2ui-skills/skills
+TUI_SKILLS_DIR = ROOT.parent / "t2ui-skills" / "skills"
+SOURCES_INDEX = ROOT / "tui-sources" / "components.json"
+
+DO_NOT_OVERWRITE = {
+    "tui-button",
+    "tui-input",
+    "tui-form",
+    "tui-modal",
+    "tui-table",
+    "tui-tabs",
+    "tui-navbar",
+    "tui-select",
+    "tui-cell",
+    "tui-rate",
+}
+
+
+def title_from_slug(slug: str) -> str:
+    return " ".join(p.capitalize() for p in slug.split("-") if p).strip() or slug
+
+
+def classify(slug: str) -> str:
+    s = slug.lower()
+    if any(k in s for k in ["button", "fab"]):
+        return "action"
+    if any(k in s for k in ["input", "textarea", "field", "keyboard", "message-input", "verification-code"]):
+        return "text-input"
+    if "checkbox" in s:
+        return "checkbox"
+    if "radio" in s:
+        return "radio"
+    if "switch" in s:
+        return "switch"
+    if any(k in s for k in ["select", "picker", "dropdown"]):
+        return "select"
+    if "rate" in s:
+        return "rating"
+    if any(k in s for k in ["table", "grid"]):
+        return "data-table"
+    if any(k in s for k in ["tabs", "tabbar", "subsection", "swiper"]):
+        return "tabs"
+    if any(k in s for k in ["navbar", "top-tips", "notice-bar"]):
+        return "top-bar"
+    if any(k in s for k in ["modal", "popup", "mask", "action-sheet"]):
+        return "overlay"
+    if any(k in s for k in ["toast", "alert", "empty", "no-network", "loading"]):
+        return "feedback"
+    if any(k in s for k in ["progress", "count-down", "count-to"]):
+        return "progress"
+    if any(k in s for k in ["calendar", "time-line", "steps"]):
+        return "timeline"
+    if any(k in s for k in ["image", "avatar", "upload"]):
+        return "media"
+    if any(k in s for k in ["card", "cell", "section", "divider", "line"]):
+        return "container"
+    return "generic"
+
+
+def example_tui(title: str, kind: str, variant: str) -> str:
+    if kind == "action":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ [✓] Save changes                                             │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Keys: <enter> click  <esc> back                               │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ [ Save changes ]                                             │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ [ Continue ]                                                 │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "text-input":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Email                                                        │\n"
+                "│ [ ada@example.com|___________________________ ]   [x]         │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Keys: <tab> next  <enter> commit  <esc> back                  │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Password                                                     │\n"
+                "│ [ ••••••••••_______________________________ ]                │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ Search                                                       │\n"
+            "│ [ type here...______________________________ ]               │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "checkbox":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ [x] Email alerts                                             │\n"
+                "│ [ ] SMS alerts                                               │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ [x] Accept terms                                             │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ [ ] Remember me                                              │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "radio":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ ( ) Daily summary   (*) Weekly summary                        │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ (*) Weekly summary                                           │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ (*) Option A   ( ) Option B                                  │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "switch":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Enable feature:  [ ON ]                                      │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Enable feature:  [ ON ]                                      │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ Enable feature:  [ OFF ]                                     │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "select":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Plan: [ Pro ]                                                │\n"
+                "│                                                            │\n"
+                "│ > Pro                                                       │\n"
+                "│   Team (disabled)                                            │\n"
+                "│   Enterprise                                                 │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Plan: [ Pro ]                                                │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ Country: [ Select... ]                                       │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "rating":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ * * * * .  (4/5)                                             │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Keys: <left>/<right> adjust  <enter> confirm  <esc> back      │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ * * * + .  (3.5/5)                                           │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ * * . . .  (2/5)                                             │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "data-table":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Name ↑               | Role        | Last login              │\n"
+                "│ Ada Lovelace         | Engineer    | 2026-01-30 12:43         │\n"
+                "│ Grace Hopper         | Admiral     | 2026-01-29 09:10         │\n"
+                "│ A very very long na… | Analyst     | 2026-01-28 20:01         │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ (table is read-only)                                         │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ Name                 | Status                                │\n"
+            "│ Ada Lovelace         | Active                                │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "tabs":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ [Profile]  Settings  Security  Notific…  (Billing)           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Keys: <left>/<right> switch  <enter> activate  <esc> back     │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ [Profile]  (Settings)                                        │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ [Home]  Search  Settings                                     │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "top-bar":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ < Back              Settings                      Edit >     │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ (navigation disabled)                                        │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ Title                                                        │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "overlay":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ ┌──────────────────────────────────────────────────────────┐ │\n"
+                "│ │ Confirm action?                                          │ │\n"
+                "│ │ [Cancel]                              [Confirm]          │ │\n"
+                "│ └──────────────────────────────────────────────────────────┘ │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ (overlay hidden)                                             │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ (overlay)                                                    │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "feedback":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Success: Saved                                               │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ (no messages)                                                │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ Loading...                                                   │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "progress":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ [██████████░░░░░░░░░░░░░░░]  42%                             │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ [████████████████████████]  100%                             │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ [██░░░░░░░░░░░░░░░░░░░░░░]  10%                              │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "timeline":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ 1) Draft   →  2) Review  →  3) Done                          │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ (timeline is read-only)                                      │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ • 09:00  Check-in                                            │\n"
+            "│ • 12:00  Lunch                                               │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "media":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ [Image: 320x180]                                             │\n"
+                "│ ██████████████████████████████████████████████████████       │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ (media unavailable)                                          │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ [Avatar]  (A)                                                │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if kind == "container":
+        if variant == "styled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}]                                                    │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ Title: Account Overview                                      │\n"
+                "│ Balance: $2,340.18                                           │\n"
+                "│ Status: Active                                               │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        if variant == "disabled":
+            return (
+                "┌──────────────────────────────────────────────────────────────┐\n"
+                f"│ [{title}] Disabled                                           │\n"
+                "├──────────────────────────────────────────────────────────────┤\n"
+                "│ (content hidden)                                             │\n"
+                "└──────────────────────────────────────────────────────────────┘"
+            )
+        return (
+            "┌──────────────────────────────────────────────────────────────┐\n"
+            f"│ [{title}]                                                    │\n"
+            "├──────────────────────────────────────────────────────────────┤\n"
+            "│ Item A                                   >                   │\n"
+            "│ Item B                                   >                   │\n"
+            "└──────────────────────────────────────────────────────────────┘"
+        )
+
+    if variant == "disabled":
+        body = "Error: Something went wrong…"
+        status = "Disabled"
+    elif variant == "styled":
+        body = "(custom style example)"
+        status = ""
+    else:
+        body = "(default state)"
+        status = ""
+
+    status_suffix = f" {status}" if status else ""
+    return (
+        "┌──────────────────────────────────────────────────────────────┐\n"
+        f"│ [{title}]{status_suffix:<52}│\n"
+        "├──────────────────────────────────────────────────────────────┤\n"
+        f"│ {body:<60}│\n"
+        "└──────────────────────────────────────────────────────────────┘"
+    )
+
+
+def render_skill_md(skill_name: str, slug: str, tag: str) -> str:
+    title = title_from_slug(slug)
+    kind = classify(slug)
+    ex1_tui = example_tui(title, kind, "default")
+    ex2_tui = example_tui(title, kind, "styled")
+    ex3_tui = example_tui(title, kind, "disabled")
+    summary_row = (
+        f'| {skill_name} | {title} | 0 | 0 | 0 | 0 | 0 | keyProps=... | state=... | hotkeys=... |'
+    )
+
+    return f"""---
+name: {skill_name}
+description: Generate pixel-precise ASCII TUI for {title} ({tag}) with strict output blocks (TUI_RENDER, COMPONENT_SPEC, PENCIL_SPEC, PENCIL_BATCH_DESIGN) suitable for Pencil MCP drawing workflows.
+---
+
+## Purpose
+
+- Produce an ASCII Text UI (TUI) representation of **{title}**.
+- Always output layout attributes (top/left/width/height, spacing, colors, typography, zIndex).
+- Always output Pencil MCP–ready specs and a `batch_design` plan (≤25 operations per call).
+
+## Source Documentation
+
+This skill intentionally does not embed external doc URLs. Use the repository index:
+
+- `full-stack-skills/tui-sources/components.json` (lookup by `skill={skill_name}` or `slug={slug}`)
+
+## Input Model (Recommended)
+
+```json
+{{
+  "widthCols": 70,
+  "grid": {{ "cellWidthPx": 8, "cellHeightPx": 16 }},
+  "props": {{}},
+  "modelValue": null,
+  "state": {{ "focused": false, "disabled": false, "loading": false, "error": null }},
+  "style": {{
+    "fillColor": "#ffffff",
+    "textColor": "#111111",
+    "strokeColor": "#e5e7eb",
+    "strokeThickness": 1,
+    "cornerRadius": 12
+  }},
+  "typography": {{ "fontFamily": "Inter", "fontSize": 14, "fontWeight": 400, "lineHeight": 20 }},
+  "layout": {{ "paddingPx": 16, "gapPx": 8 }},
+  "hotkeys": []
+}}
+```
+
+## Output Contract (Mandatory)
+
+### OUTPUT: TUI_RENDER
+
+```text
+...monospace-only text...
+```
+
+### OUTPUT: COMPONENT_SPEC
+
+```json
+{{
+  "id": "{skill_name}_1",
+  "name": "{title}",
+  "type": "{skill_name}",
+  "bbox": {{ "topPx": 0, "leftPx": 0, "widthPx": 0, "heightPx": 0 }},
+  "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": "truncate", "ellipsis": "…", "maxLines": 1 }},
+  "state": {{ "focused": false, "disabled": false, "loading": false, "error": null }},
+  "hotkeys": []
+}}
+```
+
+### OUTPUT: PENCIL_SPEC
+
+```json
+{{
+  "canvas": {{ "widthPx": 390, "heightPx": 844, "backgroundColor": "#ffffff" }},
+  "grid": {{ "cellWidthPx": 8, "cellHeightPx": 16 }},
+  "nodes": [],
+  "components": []
+}}
+```
+
+### OUTPUT: PENCIL_BATCH_DESIGN
+
+```text
+CALL 1:
+root=G()
+screen=I(root,{{type:"frame",name:"Screen"}})
+U(screen,{{width:390,height:844,x:0,y:0}})
+
+CALL 2:
+cmpBg=I(screen,{{type:"rect",name:"{title}/Background"}})
+U(cmpBg,{{x:24,y:24,width:342,height:96,fillColor:"#ffffff",strokeColor:"#e5e7eb",strokeThickness:1,cornerRadius:12}})
+cmpText=I(screen,{{type:"text",name:"{title}/Text",content:"{title}"}})
+U(cmpText,{{x:40,y:56,width:310,height:20,textColor:"#111111",fontFamily:"Inter",fontSize:14,fontWeight:600}})
+```
+
+## Rendering Rules (Component-Level)
+
+Follow the shared rules from `tui-front-ui`:
+- No TAB characters.
+- Do not exceed `widthCols`.
+- Provide a header row, body area, and minimal hotkeys if interactive.
+- `disabled=true` must suppress interaction hints.
+- `loading=true` must show a stable placeholder.
+- `error!=null` must be printed in a single line footer (truncated to width).
+
+## Examples (Must include all output blocks)
+
+### Example 1 — Minimal / default
+
+### OUTPUT: TUI_RENDER
+
+```text
+{ex1_tui}
+```
+
+### OUTPUT: COMPONENT_SPEC
+
+```json
+{{
+  "id": "{skill_name}_ex1",
+  "name": "{title}",
+  "type": "{skill_name}",
+  "bbox": {{ "topPx": 24, "leftPx": 24, "widthPx": 342, "heightPx": 96 }},
+  "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": "truncate", "ellipsis": "…", "maxLines": 1 }},
+  "state": {{ "focused": false, "disabled": false, "loading": false, "error": null }},
+  "hotkeys": []
+}}
+```
+
+### OUTPUT: PENCIL_SPEC
+
+```json
+{{
+  "canvas": {{ "widthPx": 390, "heightPx": 844, "backgroundColor": "#ffffff" }},
+  "grid": {{ "cellWidthPx": 8, "cellHeightPx": 16 }},
+  "nodes": [],
+  "components": [
+    {{ "id": "{skill_name}_ex1", "name": "{title}", "bbox": {{ "topPx": 24, "leftPx": 24, "widthPx": 342, "heightPx": 96 }}, "zIndex": 1 }}
+  ]
+}}
+```
+
+### OUTPUT: PENCIL_BATCH_DESIGN
+
+```text
+CALL 1:
+root=G()
+screen=I(root,{{type:"frame",name:"Screen"}})
+U(screen,{{width:390,height:844,x:0,y:0}})
+
+CALL 2:
+cmpBg=I(screen,{{type:"rect",name:"{title}/Background"}})
+U(cmpBg,{{x:24,y:24,width:342,height:96,fillColor:"#ffffff",strokeColor:"#e5e7eb",strokeThickness:1,cornerRadius:12}})
+cmpText=I(screen,{{type:"text",name:"{title}/Text",content:"{title}"}})
+U(cmpText,{{x:40,y:56,width:310,height:20,textColor:"#111111",fontFamily:"Inter",fontSize:14,fontWeight:600}})
+```
+
+### Example 2 — Styled / customized
+
+### OUTPUT: TUI_RENDER
+
+```text
+{ex2_tui}
+```
+
+### OUTPUT: COMPONENT_SPEC
+
+```json
+{{
+  "id": "{skill_name}_ex2",
+  "name": "{title}",
+  "type": "{skill_name}",
+  "bbox": {{ "topPx": 24, "leftPx": 24, "widthPx": 342, "heightPx": 104 }},
+  "zIndex": 1,
+  "layout": {{ "paddingPx": 20, "gapPx": 10, "align": "left", "valign": "top" }},
+  "style": {{ "fillColor": "#ffffff", "textColor": "#111111", "strokeColor": "#111111", "strokeThickness": 2, "cornerRadius": 12, "opacity": 1 }},
+  "typography": {{ "fontFamily": "Inter", "fontSize": 14, "fontWeight": 600, "lineHeight": 20 }},
+  "overflow": {{ "mode": "truncate", "ellipsis": "…", "maxLines": 1 }},
+  "state": {{ "focused": false, "disabled": false, "loading": false, "error": null }},
+  "hotkeys": []
+}}
+```
+
+### OUTPUT: PENCIL_SPEC
+
+```json
+{{
+  "canvas": {{ "widthPx": 390, "heightPx": 844, "backgroundColor": "#ffffff" }},
+  "grid": {{ "cellWidthPx": 8, "cellHeightPx": 16 }},
+  "nodes": [],
+  "components": [
+    {{ "id": "{skill_name}_ex2", "name": "{title}", "bbox": {{ "topPx": 24, "leftPx": 24, "widthPx": 342, "heightPx": 104 }}, "zIndex": 1 }}
+  ]
+}}
+```
+
+### OUTPUT: PENCIL_BATCH_DESIGN
+
+```text
+CALL 1:
+root=G()
+screen=I(root,{{type:"frame",name:"Screen"}})
+U(screen,{{width:390,height:844,x:0,y:0}})
+
+CALL 2:
+cmpBg=I(screen,{{type:"rect",name:"{title}/Background"}})
+U(cmpBg,{{x:24,y:24,width:342,height:104,fillColor:"#ffffff",strokeColor:"#111111",strokeThickness:2,cornerRadius:12}})
+cmpText=I(screen,{{type:"text",name:"{title}/Text",content:"{title}"}})
+U(cmpText,{{x:40,y:60,width:310,height:20,textColor:"#111111",fontFamily:"Inter",fontSize:14,fontWeight:600}})
+```
+
+### Example 3 — Disabled / error / edge-case
+
+### OUTPUT: TUI_RENDER
+
+```text
+{ex3_tui}
+```
+
+### OUTPUT: COMPONENT_SPEC
+
+```json
+{{
+  "id": "{skill_name}_ex3",
+  "name": "{title}",
+  "type": "{skill_name}",
+  "bbox": {{ "topPx": 24, "leftPx": 24, "widthPx": 342, "heightPx": 112 }},
+  "zIndex": 1,
+  "layout": {{ "paddingPx": 16, "gapPx": 8, "align": "left", "valign": "top" }},
+  "style": {{ "fillColor": "#ffffff", "textColor": "#6b7280", "strokeColor": "#e5e7eb", "strokeThickness": 1, "cornerRadius": 12, "opacity": 1 }},
+  "typography": {{ "fontFamily": "Inter", "fontSize": 14, "fontWeight": 400, "lineHeight": 20 }},
+  "overflow": {{ "mode": "truncate", "ellipsis": "…", "maxLines": 1 }},
+  "state": {{ "focused": false, "disabled": true, "loading": false, "error": "Something went wrong" }},
+  "hotkeys": []
+}}
+```
+
+### OUTPUT: PENCIL_SPEC
+
+```json
+{{
+  "canvas": {{ "widthPx": 390, "heightPx": 844, "backgroundColor": "#ffffff" }},
+  "grid": {{ "cellWidthPx": 8, "cellHeightPx": 16 }},
+  "nodes": [],
+  "components": [
+    {{ "id": "{skill_name}_ex3", "name": "{title}", "bbox": {{ "topPx": 24, "leftPx": 24, "widthPx": 342, "heightPx": 112 }}, "zIndex": 1 }}
+  ]
+}}
+```
+
+### OUTPUT: PENCIL_BATCH_DESIGN
+
+```text
+CALL 1:
+root=G()
+screen=I(root,{{type:"frame",name:"Screen"}})
+U(screen,{{width:390,height:844,x:0,y:0}})
+
+CALL 2:
+cmpBg=I(screen,{{type:"rect",name:"{title}/Background"}})
+U(cmpBg,{{x:24,y:24,width:342,height:112,fillColor:"#ffffff",strokeColor:"#e5e7eb",strokeThickness:1,cornerRadius:12,opacity:1}})
+cmpText=I(screen,{{type:"text",name:"{title}/Error",content:"Error: Something went wrong…"}})
+U(cmpText,{{x:40,y:60,width:310,height:20,textColor:"#6b7280",fontFamily:"Inter",fontSize:14,fontWeight:400}})
+```
+
+## Component Summary Row (for page aggregation)
+
+```text
+| id | name | top | left | width | height | z | keyProps | state | hotkeys |
+{summary_row}
+```
+"""
+
+
+def main() -> int:
+    data = json.loads(SOURCES_INDEX.read_text(encoding="utf-8"))
+    components: List[Dict[str, Any]] = data["components"]
+
+    for c in components:
+        skill = c["skill"]
+        slug = c["slug"]
+        tag = c["tag"]
+
+        if skill in DO_NOT_OVERWRITE:
+            continue
+
+        skill_dir = TUI_SKILLS_DIR / skill
+        skill_dir.mkdir(parents=True, exist_ok=True)
+        skill_md = skill_dir / "SKILL.md"
+        skill_md.write_text(render_skill_md(skill, slug, tag), encoding="utf-8")
+
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 53 - 0
tools/lint_tui_no_uviewpro.py

@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+from pathlib import Path
+
+
+ROOT = Path(__file__).resolve().parents[1]
+SKILLS_DIR = ROOT / "skills"
+# tui-skills 已迁移至 t2ui-skills 仓库;若工作区存在同级 t2ui-skills 则对其 skills 目录做检查
+TUI_SKILLS_DIR = ROOT.parent / "t2ui-skills" / "skills"
+
+
+def iter_target_files() -> list[Path]:
+    targets: list[Path] = []
+    if not TUI_SKILLS_DIR.exists():
+        return targets
+    for p in TUI_SKILLS_DIR.iterdir():
+        if not p.is_dir():
+            continue
+        if p.name.startswith("tui-"):
+            for f in p.rglob("*"):
+                if f.is_file():
+                    targets.append(f)
+    return targets
+
+
+def main() -> int:
+    needle = "uviewpro"
+    offenders: list[tuple[Path, int, str]] = []
+
+    for f in iter_target_files():
+        try:
+            text = f.read_text(encoding="utf-8", errors="ignore")
+        except Exception:
+            continue
+        if needle not in text:
+            continue
+        for i, line in enumerate(text.splitlines(), start=1):
+            if needle in line:
+                offenders.append((f, i, line.strip()))
+
+    if offenders:
+        print(f"FAIL: found '{needle}' in {len(offenders)} location(s):")
+        for f, i, line in offenders[:200]:
+            print(f"- {f}:{i}: {line}")
+        return 1
+
+    print(f"OK: no '{needle}' found in TUI skills")
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

Некоторые файлы не были показаны из-за большого количества измененных файлов