Token导航 LogoToken导航

Agent Skill · 开发

spec-add(规格添加)

spec-add 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

spec-add 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为只读;许可证信息还不明确,第三方扫描已通过,按安装量在开发类的 21,746 个 Skill 里排第 17,643。

总安装 392周安装 16GitHub Stars 1,917下载 127核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:spec-add(规格添加)
来源仓库:https://github.com/catlog22/claude-code-workflow
仓库路径:skills/spec-add
安装命令:
npx skills add https://github.com/catlog22/claude-code-workflow --skill spec-add
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/catlog22/claude-code-workflow --skill spec-add

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

spec-add 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息。适合在 Codex、Claude、Cursor、Gemini CLI 中围绕仓库状态或代码变更进行整理。通过 npx skills add 命令从指定仓库安装并使用。

使用前需确认权限范围、维护状态及是否触发联网或文件操作。spec-add 属于开发类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/spec-add

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/catlog22/claude-code-workflow --skill spec-add;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它标注为只读,先用只读任务试一次,确认行为符合预期再扩大使用范围。

常见问题

6 条

spec-add 怎么安装?

在终端执行 npx skills add https://github.com/catlog22/claude-code-workflow --skill spec-add。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

spec-add 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

spec-add 需要什么权限?

权限级别是只读。该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

spec-add 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

spec-add 用的人多吗?

公开数据是累计安装 392 次,近一周安装 16 次,下载 127 次,GitHub 1,917 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

spec-add 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。
  • 来源仓库有 1,917 星,维护活跃度相对可查。
  • 标注为只读权限,试用阶段不容易误改本地文件。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。
  • 只想先试试效果、不希望它改动本地文件的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
spec-add

规格添加 · 本页

3921,917只读未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Spec Add Command

Overview

Unified command for adding specs one at a time. Supports both interactive wizard mode and direct CLI mode.

Key Features:

  • Supports both project specs and personal specs
  • Scope selection (global vs project) for personal specs
  • Category-based organization for workflow stages
  • Interactive wizard mode with smart defaults
  • Direct CLI mode with auto-detection of type and category
  • Auto-confirm mode (-y/--yes) for scripted usage

Use Cases

  1. During Session: Capture important decisions as they're made
  2. After Session: Reflect on lessons learned before archiving
  3. Proactive: Add team conventions or architectural rules
  4. Interactive: Guided wizard for adding rules with full control over dimension, scope, and category

Usage

$spec-add                                                     # Interactive wizard (all prompts)
$spec-add --interactive                                       # Explicit interactive wizard
$spec-add "Use async/await instead of callbacks"              # Direct mode (auto-detect type)
$spec-add -y "No direct DB access" --type constraint          # Auto-confirm, skip confirmation
$spec-add --scope global --dimension personal                 # Create global personal spec (interactive)
$spec-add --dimension specs --category exploration            # Project spec in exploration category (interactive)
$spec-add "Cache invalidation requires event sourcing" --type learning --category architecture

Parameters

ParameterTypeRequiredDefaultDescription
rulestringYes (unless --interactive)-The rule, convention, or insight to add
--typeenumNoauto-detectType: convention, constraint, learning
--categorystringNoauto-detect / generalCategory for organization (see categories below)
--dimensionenumNoInteractivespecs (project) or personal
--scopeenumNoprojectglobal or project (only for personal dimension)
--interactiveflagNo-Launch full guided wizard for adding rules
-y / --yesflagNo-Auto-categorize and add without confirmation

Type Categories

convention - Coding style preferences (goes to conventions section)

  • Subcategories: coding_style, naming_patterns, file_structure, documentation

constraint - Hard rules that must not be violated (goes to constraints section)

  • Subcategories: architecture, tech_stack, performance, security

learning - Session-specific insights (goes to learnings array)

  • Subcategories: architecture, performance, security, testing, process, other

Workflow Stage Categories (for --category)

CategoryUse CaseExample Rules
generalApplies to all stages"Use TypeScript strict mode"
explorationCode exploration, debugging"Always trace the call stack before modifying"
planningTask planning, requirements"Break down tasks into 2-hour chunks"
executionImplementation, testing"Run tests after each file modification"

Execution Process

Input Parsing:
   |- Parse: rule text (positional argument, optional if --interactive)
   |- Parse: --type (convention|constraint|learning)
   |- Parse: --category (subcategory)
   |- Parse: --dimension (specs|personal)
   |- Parse: --scope (global|project)
   |- Parse: --interactive (flag)
   +- Parse: -y / --yes (flag)

Step 1: Parse Input

Step 2: Determine Mode
   |- If --interactive OR no rule text -> Full Interactive Wizard (Path A)
   +- If rule text provided -> Direct Mode (Path B)

Path A: Interactive Wizard
   |- Step A1: Ask dimension (if not specified)
   |- Step A2: Ask scope (if personal + scope not specified)
   |- Step A3: Ask category (if not specified)
   |- Step A4: Ask type (convention|constraint|learning)
   |- Step A5: Ask content (rule text)
   +- Continue to Step 3

Path B: Direct Mode
   |- Step B1: Auto-detect type (if not specified) using detectType()
   |- Step B2: Auto-detect category (if not specified) using detectCategory()
   |- Step B3: Default dimension to 'specs' if not specified
   +- Continue to Step 3

Step 3: Determine Target File
   |- specs dimension -> .ccw/specs/coding-conventions.md or architecture-constraints.md
   +- personal dimension -> ~/.ccw/personal/ or .ccw/personal/

Step 4: Validate and Write Spec
   |- Ensure target directory and file exist
   |- Check for duplicates
   |- Append rule to appropriate section
   +- Run ccw spec rebuild

Step 5: Display Confirmation
   +- If -y/--yes: Minimal output
   +- Otherwise: Full confirmation with location details

Implementation

Step 1: Parse Input

// Parse arguments
const args = "$ARGUMENTS"
const argsLower = args.toLowerCase()

// Extract flags
const AUTO_YES = argsLower.includes('--yes') || argsLower.includes('-y')
const isInteractive = argsLower.includes('--interactive')

// Extract named parameters
const hasType = argsLower.includes('--type')
const hasCategory = argsLower.includes('--category')
const hasDimension = argsLower.includes('--dimension')
const hasScope = argsLower.includes('--scope')

let type = hasType ? args.match(/--type\s+(\w+)/i)?.[1]?.toLowerCase() : null
let category = hasCategory ? args.match(/--category\s+(\w+)/i)?.[1]?.toLowerCase() : null
let dimension = hasDimension ? args.match(/--dimension\s+(\w+)/i)?.[1]?.toLowerCase() : null
let scope = hasScope ? args.match(/--scope\s+(\w+)/i)?.[1]?.toLowerCase() : null

// Extract rule text (everything before flags, or quoted string)
let ruleText = args
  .replace(/--type\s+\w+/gi, '')
  .replace(/--category\s+\w+/gi, '')
  .replace(/--dimension\s+\w+/gi, '')
  .replace(/--scope\s+\w+/gi, '')
  .replace(/--interactive/gi, '')
  .replace(/--yes/gi, '')
  .replace(/-y\b/gi, '')
  .replace(/^["']|["']$/g, '')
  .trim()

// Validate values
if (scope && !['global', 'project'].includes(scope)) {
  console.log("Invalid scope. Use 'global' or 'project'.")
  return
}
if (dimension && !['specs', 'personal'].includes(dimension)) {
  console.log("Invalid dimension. Use 'specs' or 'personal'.")
  return
}
if (type && !['convention', 'constraint', 'learning'].includes(type)) {
  console.log("Invalid type. Use 'convention', 'constraint', or 'learning'.")
  return
}
if (category) {
  const validCategories = [
    'general', 'exploration', 'planning', 'execution',
    'coding_style', 'naming_patterns', 'file_structure', 'documentation',
    'architecture', 'tech_stack', 'performance', 'security',
    'testing', 'process', 'other'
  ]
  if (!validCategories.includes(category)) {
    console.log(`Invalid category. Valid categories: ${validCategories.join(', ')}`)
    return
  }
}

Step 2: Determine Mode

const useInteractiveWizard = isInteractive || !ruleText

Path A: Interactive Wizard

if (useInteractiveWizard) {

  // --- Step A1: Ask dimension (if not specified) ---
  if (!dimension) {
    if (AUTO_YES) {
      dimension = 'specs'  // Default to project specs in auto mode
    } else {
      const dimensionAnswer = functions.request_user_input({
        questions: [{
          header: "Dimension",
          id: "dimension",
          question: "What type of spec do you want to create?",
          options: [
            { label: "Project Spec(Recommended)", description: "Coding conventions, constraints, quality rules for this project (stored in .ccw/specs/)" },
            { label: "Personal Spec", description: "Personal preferences and constraints that follow you across projects (stored in ~/.ccw/specs/personal/ or .ccw/specs/personal/)" }
          ]
        }]
      })  // BLOCKS (wait for user response)
      dimension = dimensionAnswer.answers.dimension.answers[0] === "Project Spec(Recommended)" ? "specs" : "personal"
    }
  }

  // --- Step A2: Ask scope (if personal + scope not specified) ---
  if (dimension === 'personal' && !scope) {
    if (AUTO_YES) {
      scope = 'project'  // Default to project scope in auto mode
    } else {
      const scopeAnswer = functions.request_user_input({
        questions: [{
          header: "Scope",
          id: "scope",
          question: "Where should this personal spec be stored?",
          options: [
            { label: "Global(Recommended)", description: "Apply to ALL projects (~/.ccw/specs/personal/)" },
            { label: "Project-only", description: "Apply only to this project (.ccw/specs/personal/)" }
          ]
        }]
      })  // BLOCKS (wait for user response)
      scope = scopeAnswer.answers.scope.answers[0] === "Global(Recommended)" ? "global" : "project"
    }
  }

  // --- Step A3: Ask category (if not specified) ---
  if (!category) {
    if (AUTO_YES) {
      category = 'general'  // Default to general in auto mode
    } else {
      const categoryAnswer = functions.request_user_input({
        questions: [{
          header: "Category",
          id: "category",
          question: "Which workflow stage does this spec apply to?",
          options: [
            { label: "General(Recommended)", description: "Applies to all stages (default)" },
            { label: "Exploration", description: "Code exploration, analysis, debugging" },
            { label: "Planning", description: "Task planning, requirements gathering" }
          ]
        }]
      })  // BLOCKS (wait for user response)
      const categoryLabel = categoryAnswer.answers.category.answers[0]
      category = categoryLabel.includes("General") ? "general"
        : categoryLabel.includes("Exploration") ? "exploration"
        : categoryLabel.includes("Planning") ? "planning"
        : "execution"
    }
  }

  // --- Step A4: Ask type (if not specified) ---
  if (!type) {
    if (AUTO_YES) {
      type = 'convention'  // Default to convention in auto mode
    } else {
      const typeAnswer = functions.request_user_input({
        questions: [{
          header: "Rule Type",
          id: "rule_type",
          question: "What type of rule is this?",
          options: [
            { label: "Convention", description: "Coding style preference (e.g., use functional components)" },
            { label: "Constraint", description: "Hard rule that must not be violated (e.g., no direct DB access)" },
            { label: "Learning", description: "Insight or lesson learned (e.g., cache invalidation needs events)" }
          ]
        }]
      })  // BLOCKS (wait for user response)
      const typeLabel = typeAnswer.answers.rule_type.answers[0]
      type = typeLabel.includes("Convention") ? "convention"
        : typeLabel.includes("Constraint") ? "constraint"
        : "learning"
    }
  }

  // --- Step A5: Ask content (rule text) ---
  if (!ruleText) {
    if (AUTO_YES) {
      console.log("Error: Rule text is required in auto mode. Provide rule text as argument.")
      return
    }
    const contentAnswer = functions.request_user_input({
      questions: [{
        header: "Content",
        id: "content",
        question: "Enter the rule or guideline text:",
        options: [
          { label: "Type in Other", description: "Enter your rule text via the Other input field" }
        ]
      }]
    })  // BLOCKS (wait for user response)
    ruleText = contentAnswer.answers.content.answers[0]
  }

}

Path B: Direct Mode

Auto-detect type if not specified:

function detectType(ruleText) {
  const text = ruleText.toLowerCase();

  // Constraint indicators
  if (/\b(no|never|must not|forbidden|prohibited|always must)\b/.test(text)) {
    return 'constraint';
  }

  // Learning indicators
  if (/\b(learned|discovered|realized|found that|turns out)\b/.test(text)) {
    return 'learning';
  }

  // Default to convention
  return 'convention';
}

function detectCategory(ruleText, type) {
  const text = ruleText.toLowerCase();

  if (type === 'constraint' || type === 'learning') {
    if (/\b(architecture|layer|module|dependency|circular)\b/.test(text)) return 'architecture';
    if (/\b(security|auth|permission|sanitize|xss|sql)\b/.test(text)) return 'security';
    if (/\b(performance|cache|lazy|async|sync|slow)\b/.test(text)) return 'performance';
    if (/\b(test|coverage|mock|stub)\b/.test(text)) return 'testing';
  }

  if (type === 'convention') {
    if (/\b(name|naming|prefix|suffix|camel|pascal)\b/.test(text)) return 'naming_patterns';
    if (/\b(file|folder|directory|structure|organize)\b/.test(text)) return 'file_structure';
    if (/\b(doc|comment|jsdoc|readme)\b/.test(text)) return 'documentation';
    return 'coding_style';
  }

  return type === 'constraint' ? 'tech_stack' : 'other';
}

if (!useInteractiveWizard) {
  if (!type) {
    type = detectType(ruleText)
  }
  if (!category) {
    category = detectCategory(ruleText, type)
  }
  if (!dimension) {
    dimension = 'specs'  // Default to project specs in direct mode
  }
}

Step 3: Ensure Guidelines File Exists

Uses.ccw/specs/ directory (same as frontend/backend spec-index-builder)

bash(test -f .ccw/specs/coding-conventions.md && echo "EXISTS" || echo "NOT_FOUND")

If NOT_FOUND, initialize spec system:

Bash('ccw spec init')
Bash('ccw spec rebuild')

Step 4: Determine Target File

const path = require('path')
const os = require('os')

const isConvention = type === 'convention'
const isConstraint = type === 'constraint'
const isLearning = type === 'learning'

let targetFile
let targetDir

if (dimension === 'specs') {
  // Project specs - use .ccw/specs/ (same as frontend/backend spec-index-builder)
  targetDir = '.ccw/specs'
  if (isConstraint) {
    targetFile = path.join(targetDir, 'architecture-constraints.md')
  } else {
    targetFile = path.join(targetDir, 'coding-conventions.md')
  }
} else {
  // Personal specs - use .ccw/personal/ (same as backend spec-index-builder)
  if (scope === 'global') {
    targetDir = path.join(os.homedir(), '.ccw', 'personal')
  } else {
    targetDir = path.join('.ccw', 'personal')
  }

  // Create type-based filename
  const typePrefix = isConstraint ? 'constraints' : isLearning ? 'learnings' : 'conventions'
  targetFile = path.join(targetDir, `${typePrefix}.md`)
}

Step 5: Build Entry

function buildEntry(rule, type, category, sessionId) {
  if (type === 'learning') {
    return {
      date: new Date().toISOString().split('T')[0],
      session_id: sessionId || null,
      insight: rule,
      category: category,
      context: null
    };
  }

  // For conventions and constraints, just return the rule string
  return rule;
}

Step 6: Write Spec

const fs = require('fs')

// Ensure directory exists
if (!fs.existsSync(targetDir)) {
  fs.mkdirSync(targetDir, { recursive: true })
}

// Check if file exists
const fileExists = fs.existsSync(targetFile)

if (!fileExists) {
  // Create new file with frontmatter
  const frontmatter = `---
title: ${dimension === 'specs' ? 'Project' : 'Personal'} ${isConstraint ? 'Constraints' : isLearning ? 'Learnings' : 'Conventions'}
readMode: optional
priority: medium
category: ${category}
scope: ${dimension === 'personal' ? scope : 'project'}
dimension: ${dimension}
keywords: [${category}, ${isConstraint ? 'constraint' : isLearning ? 'learning' : 'convention'}]
---

# ${dimension === 'specs' ? 'Project' : 'Personal'} ${isConstraint ? 'Constraints' : isLearning ? 'Learnings' : 'Conventions'}

`
  fs.writeFileSync(targetFile, frontmatter, 'utf8')
}

// Read existing content
let content = fs.readFileSync(targetFile, 'utf8')

// Deduplicate: skip if rule text already exists in the file
if (content.includes(ruleText)) {
  console.log(`
Rule already exists in ${targetFile}
Text: "${ruleText}"
`)
  return
}

// Format the new rule based on type
let newRule
if (isLearning) {
  const entry = buildEntry(ruleText, type, category)
  newRule = `- [learning/${category}] ${entry.insight} (${entry.date})`
} else {
  newRule = `- [${category}] ${ruleText}`
}

// Append the rule
content = content.trimEnd() + '\n' + newRule + '\n'
fs.writeFileSync(targetFile, content, 'utf8')

// Rebuild spec index
Bash('ccw spec rebuild')

Step 7: Display Confirmation

If -y/--yes (auto mode):

Spec added: [${type}/${category}] "${ruleText}" -> ${targetFile}

Otherwise (full confirmation):

Spec created successfully

Dimension: ${dimension}
Scope: ${dimension === 'personal' ? scope : 'project'}
Category: ${category}
Type: ${type}
Rule: "${ruleText}"

Location: ${targetFile}

Use 'ccw spec list' to view all specs
Use 'ccw spec load --category ${category}' to load specs by category

Target File Resolution

Project Specs (dimension: specs)

.ccw/specs/
|- coding-conventions.md       <- conventions, learnings
|- architecture-constraints.md <- constraints
+- quality-rules.md            <- quality rules

Personal Specs (dimension: personal)

# Global (~/.ccw/personal/)
~/.ccw/personal/
|- conventions.md              <- personal conventions (all projects)
|- constraints.md              <- personal constraints (all projects)
+- learnings.md                <- personal learnings (all projects)

# Project-local (.ccw/personal/)
.ccw/personal/
|- conventions.md              <- personal conventions (this project only)
|- constraints.md              <- personal constraints (this project only)
+- learnings.md                <- personal learnings (this project only)

Examples

Interactive Wizard

$spec-add --interactive
# Prompts for: dimension -> scope (if personal) -> category -> type -> content

Add a Convention (Direct)

$spec-add "Use async/await instead of callbacks" --type convention --category coding_style

Result in .ccw/specs/coding-conventions.md:

- [coding_style] Use async/await instead of callbacks

Add an Architectural Constraint (Direct)

$spec-add "No direct DB access from controllers" --type constraint --category architecture

Result in .ccw/specs/architecture-constraints.md:

- [architecture] No direct DB access from controllers

Capture a Learning (Direct, Auto-detect)

$spec-add "Cache invalidation requires event sourcing for consistency" --type learning

Result in .ccw/specs/coding-conventions.md:

- [learning/architecture] Cache invalidation requires event sourcing for consistency (2026-03-06)

Auto-confirm Mode

$spec-add -y "No direct DB access from controllers" --type constraint
# Auto-detects category as 'architecture', writes without confirmation prompt

Personal Spec (Global)

$spec-add --scope global --dimension personal --type convention "Prefer descriptive variable names"

Result in ~/.ccw/personal/conventions.md:

- [general] Prefer descriptive variable names

Personal Spec (Project)

$spec-add --scope project --dimension personal --type constraint "No ORM in this project"

Result in .ccw/personal/constraints.md:

- [general] No ORM in this project

Error Handling

  • Duplicate Rule: Warn and skip if exact rule text already exists in target file
  • Invalid Category: Suggest valid categories for the type
  • Invalid Scope: Exit with error - must be 'global' or 'project'
  • Invalid Dimension: Exit with error - must be 'specs' or 'personal'
  • Invalid Type: Exit with error - must be 'convention', 'constraint', or 'learning'
  • File not writable: Check permissions, suggest manual creation
  • Invalid path: Exit with error message
  • File Corruption: Backup existing file before modification

Related Commands

  • $spec-setup - Initialize project with specs scaffold
  • $session-sync - Quick-sync session work to specs and project-tech
  • $workflow-session-start - Start a session
  • $workflow-session-complete - Complete session (prompts for learnings)
  • ccw spec list - View all specs
  • ccw spec load --category <cat> - Load filtered specs
  • ccw spec rebuild - Rebuild spec index

平台分布

Codex

37.54%
按下载量换算48

Claude

26.5%
按下载量换算34

Cursor

19.12%
按下载量换算24

Gemini CLI

8.27%
按下载量换算11

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills