返回技能列表

build-cli-plugin

pjt222
更新于 6 days ago
18 次查看
17
2
17
在 GitHub 上查看
design

关于

This skill provides a template for building CLI plugins or adapters using the abstract base class pattern in TypeScript. It guides developers through defining the plugin contract, implementing idempotent install/uninstall operations, and choosing an installation strategy. Use it when adding framework support to a CLI tool or extending an existing plugin architecture.

快速安装

Claude Code

推荐
主要方式
npx skills add pjt222/agent-almanac -a claude-code
插件命令备选方式
/plugin add https://github.com/pjt222/agent-almanac
Git 克隆备选方式
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/build-cli-plugin

在 Claude Code 中复制并粘贴此命令以安装该技能

技能文档

建命工插件

以抽象基類模→加新插件/配器於命工之可插構。

  • 加新標框支於命裝器
  • 為多標命工建插系
  • 擴現配器構以新策變
  • 移內容發至用異檔布之框

  • :插所支之框或標(名、配徑、規)
  • :基類或插契之徑
  • :裝策:symlinkcopyfile-per-itemappend-to-file
  • :插處之內容類(如唯技、技+將、全支)
  • :範支(案級、全域、兩)

一:定契

基類立諸插當施之介。

export class FrameworkAdapter {
  static id = 'base';            // Unique identifier
  static displayName = 'Base';   // Human-readable name
  static strategy = 'symlink';   // Installation strategy
  static contentTypes = ['skill']; // What this adapter handles

  async detect(projectDir) { return false; }
  getTargetPath(projectDir, scope) { throw new Error('Not implemented'); }
  async install(item, projectDir, scope, options) { throw new Error('Not implemented'); }
  async uninstall(item, projectDir, scope, options) { throw new Error('Not implemented'); }
  async listInstalled(projectDir, scope) { return []; }
  async audit(projectDir, scope) { return { framework: this.constructor.displayName, ok: [], warnings: [], errors: [] }; }
  supports(contentType) { return this.constructor.contentTypes.includes(contentType); }
}

靜欄 定插之身與能:

  • id:用於 --framework <id> 選項與結報
  • displayName:顯於人讀出
  • strategy:定內容達標之方
  • contentTypes:濾此配器受之項

基類未存→先造之。模可縮至任數插件。

得: 基類附靜身欄與抽方。

敗: 基類有不適諸插之方(如非諸框支 audit)→供默施返妥空操。

二:擇裝策

用時
symlink標直讀源檔。最廉、同步Claude Code 讀 .claude/skills/<name>/ 符連
copy標需檔於己目。改不傳某 IDE 唯索其目
file-per-item標每項一檔,有專格Cursor .mdc 律檔
append-to-file標讀單指檔Aider CONVENTIONS.md、Codex AGENTS.md

策定施形:

  • SymlinksymlinkSync(source, target)—處相對對絕對徑
  • CopycpSync(source, target, { recursive: true })—處覆
  • File-per-itemwriteFileSync(target, transform(content))—或需格轉
  • Append-to-file:包內容以標冪等插/替/除

得: 策已擇附基於標框如何發現內容之清由。

敗: 不確→察框文如何發現配或指檔。框讀任意目→默為 symlink。

三:施偵

偵告命工案中何框存。

// In detector.js — each rule checks for a filesystem marker
const RULES = [
  {
    id: 'my-framework',
    displayName: 'My Framework',
    check: (dir) => existsSync(resolve(dir, '.myframework/')),
    marker: '.myframework/',
    scope: 'project',
  },
];

偵策:

  • 目存.claude/.cursor/.gemini/
  • 配檔opencode.json.aider.conf.yml
  • 指檔AGENTS.mdCONVENTIONS.md
  • 全域標~/.openclaw/~/.hermes/

偵結必返標以令用者解框何以被偵。

得: 偵律穩識框而無偽陽。

敗: 框無唯標(泛目名)→用多標組或需顯 --framework

四:冪等施裝

async install(item, projectDir, scope, options) {
  const targetDir = this.getTargetPath(projectDir, scope);
  const targetPath = resolve(targetDir, item.id);

  // Idempotency: skip if already installed (unless force)
  if (existsSync(targetPath) && !options.force) {
    return { action: 'skipped', path: targetPath };
  }

  if (options.dryRun) {
    return { action: 'created', path: targetPath, details: 'dry-run' };
  }

  // Ensure parent directory exists
  mkdirSync(targetDir, { recursive: true });

  // Strategy-specific installation
  if (this.constructor.strategy === 'symlink') {
    const relPath = relative(targetDir, item.sourceDir);
    symlinkSync(relPath, targetPath);
  } else if (this.constructor.strategy === 'copy') {
    cpSync(item.sourceDir, targetPath, { recursive: true });
  }

  return { action: 'created', path: targetPath };
}

冪等律:

  • 標存且未 --force
  • --force 設→(先除,後裝)
  • 乾行 必成於 action: 'created'
  • 返值 必為 { action, path, details? }

得: 裝於標徑造內容,若已存則略,循 --force--dry-run

敗: symlink 於 Windows/NTFS 敗→退為目連或拷。記退。

五:施卸與清

async uninstall(item, projectDir, scope, options) {
  const targetDir = this.getTargetPath(projectDir, scope);
  const targetPath = resolve(targetDir, item.id);

  if (!existsSync(targetPath)) {
    return { action: 'skipped', path: targetPath };
  }

  if (options.dryRun) {
    return { action: 'removed', path: targetPath };
  }

  // Remove the installed content
  rmSync(targetPath, { recursive: true });

  return { action: 'removed', path: targetPath };
}

清慮:

  • 唯除插所裝—絕不刪用者造檔
  • append-to-file:除標段,非全檔
  • 留父目(他插或用之)

得: 卸唯除插內容。

敗: 除敗(權、鎖檔)→返誤結非拋。

六:施列與審

async listInstalled(projectDir, scope) {
  const targetDir = this.getTargetPath(projectDir, scope);
  if (!existsSync(targetDir)) return [];

  const entries = readdirSync(targetDir);
  return entries.map(name => {
    const fullPath = resolve(targetDir, name);
    const broken = lstatSync(fullPath).isSymbolicLink()
      && !existsSync(fullPath);
    return { id: name, type: 'skill', broken };
  });
}

async audit(projectDir, scope) {
  const items = await this.listInstalled(projectDir, scope);
  const ok = items.filter(i => !i.broken);
  const broken = items.filter(i => i.broken);
  return {
    framework: this.constructor.displayName,
    ok: [`${ok.length} skills installed`],
    warnings: [],
    errors: broken.map(i => `Broken: ${i.id}`),
  };
}

得: 列返諸裝項附破連偵。審概健。

敗: 標目不存→返空結(非誤—框但無所裝)。

七:註插件

// In adapters/index.js
import { MyFrameworkAdapter } from './my-framework.js';
register(MyFrameworkAdapter);

註令配器得於:

  • 自偵(detectFrameworks()getAdaptersForDetections()
  • 顯擇(--framework my-framework
  • 列(listAdapters()

得: 配器現於 tool detect 出且可以 --framework 標。

敗: 配器不現→驗 static id 合偵律之 idregister() 已呼。

八:書試

describe('adapter: my-framework (dry-run)', () => {
  it('targets the correct path', () => {
    const out = run('install create-skill --framework my-framework --dry-run');
    assert.match(out, /\.myframework/i);
  });
});

最少試:乾行徑、偵存、內容類支。

得: 配器專試證裝徑與行。

敗: CI 不偵(無標目)→試中顯用 --framework

  • 插件正擴基類
  • 靜欄(iddisplayNamestrategycontentTypes)已設
  • 偵律識框而無偽陽
  • install() 冪等(存則略,循 --force
  • uninstall() 唯除插所造
  • listInstalled() 偵破符連
  • audit() 準報健
  • 插件已註且現於 tool detect
  • 乾行試通

  • 忘相對對絕對 symlink:案範 symlink 當相對(可攜)。全域範 symlink 當絕對(非依 cwd)。
  • 不處缺父目:造內容前必 mkdirSync(dir, { recursive: true })
  • append-to-file 無標:無冪等標(<!-- start:id --> / <!-- end:id -->)→重裝複內容。必包所附內容。
  • 偵偽陽:泛目名(如 .config/)或合多框。用目中專檔標。
  • supports():裝器呼 supports(item.type) 前派。contentTypes 誤→配器默略項。

  • scaffold-cli-command — 建用此插之命
  • test-cli-application — 命工試模含配器試
  • design-cli-output — 裝/卸結之端出

GitHub 仓库

pjt222/agent-almanac
路径: i18n/wenyan-ultra/skills/build-cli-plugin
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

相关推荐技能

content-collections

Content Collections 是一个 TypeScript 优先的构建工具,可将本地 Markdown/MDX 文件转换为类型安全的数据集合。它专为构建博客、文档站和内容密集型 Vite+React 应用而设计,提供基于 Zod 的自动模式验证。该工具涵盖从 Vite 插件配置、MDX 编译到生产环境部署的完整工作流。

查看技能

polymarket

这个Claude Skill为开发者提供完整的Polymarket预测市场开发支持,涵盖API调用、交易执行和市场数据分析。关键特性包括实时WebSocket数据流,可监控实时交易、订单和市场动态。开发者可用它构建预测市场应用、实施交易策略并集成实时市场预测功能。

查看技能

creating-opencode-plugins

该Skill帮助开发者创建OpenCode插件,用于接入命令、文件、LSP等25+种事件。它提供了插件结构、事件API规范和JavaScript/TypeScript实现模式,适合需要拦截操作、扩展功能或自定义事件处理的场景。开发者可通过它快速构建响应式模块来增强OpenCode AI助手的能力。

查看技能

sglang

SGLang是一个专为LLM设计的高性能推理框架,特别适用于需要结构化输出的场景。它通过RadixAttention前缀缓存技术,在处理JSON、正则表达式、工具调用等具有重复前缀的复杂工作流时,能实现极速生成。如果你正在构建智能体或多轮对话系统,并追求远超vLLM的推理性能,SGLang是理想选择。

查看技能