1- import type { AgenticTemplateFormat } from '../commands'
2- import type { CreateNewProjectOptions } from '../commands/create'
1+ import type { AgenticTemplateFormat , GenerateAgenticTemplateOptions } from '../commands/ai'
32import type { CleanCommandConfig , CliOpts } from '../types'
43import process from 'node:process'
54import input from '@inquirer/input'
65import select from '@inquirer/select'
76import { program } from 'commander'
8- import { cleanProjects , createNewProject , createTimestampFolderName , defaultAgenticBaseDir , generateAgenticTemplate , generateAgenticTemplates , getCreateChoices , init , loadAgenticTasks , setVscodeBinaryMirror , syncNpmMirror , upgradeMonorepo } from '../commands'
7+ import { cleanProjects , createNewProject , createTimestampFolderName , defaultAgenticBaseDir , generateAgenticTemplate , generateAgenticTemplates , getCreateChoices , init , loadAgenticTasks , setVscodeBinaryMirror , skillTargets , syncNpmMirror , syncSkills , upgradeMonorepo } from '../commands'
98import { defaultTemplate } from '../commands/create'
10- import { name , version } from '../constants'
9+ import { name as cliName , version } from '../constants'
1110import { resolveCommandConfig } from '../core/config'
1211import { logger } from '../core/logger'
1312
13+ type SkillTarget = typeof skillTargets [ number ]
14+ type CreateNewProjectOptions = NonNullable < Parameters < typeof createNewProject > [ 0 ] >
15+
1416interface AiTemplateCommandOptions {
1517 output ?: string
1618 force ?: boolean
@@ -26,9 +28,15 @@ interface CleanCommandOptions {
2628 pinnedVersion ?: string
2729}
2830
31+ interface SkillsSyncCommandOptions {
32+ codex ?: boolean
33+ claude ?: boolean
34+ all ?: boolean
35+ }
36+
2937const cwd = process . cwd ( )
3038
31- program . name ( name ) . version ( version )
39+ program . name ( cliName ) . version ( version )
3240
3341/**
3442 * 升级子命令:同步 assets 模板到当前仓库。
@@ -86,6 +94,41 @@ program.command('mirror').description('设置 VscodeBinaryMirror').action(async
8694 logger . success ( 'set vscode binary mirror finished!' )
8795} )
8896
97+ const skillsCommand = program . command ( 'skills' ) . description ( '技能工具集' )
98+
99+ skillsCommand . command ( 'sync' )
100+ . description ( '同步 resources/skills/icebreakers-monorepo-cli 到全局目录' )
101+ . option ( '--codex' , '同步到 ~/.codex/skills' )
102+ . option ( '--claude' , '同步到 ~/.claude/skills' )
103+ . option ( '--all' , '同步全部目标' )
104+ . action ( async ( opts : SkillsSyncCommandOptions ) => {
105+ const selected = new Set < SkillTarget > ( )
106+ if ( opts . all ) {
107+ for ( const target of skillTargets ) {
108+ selected . add ( target )
109+ }
110+ }
111+ else {
112+ if ( opts . codex ) {
113+ selected . add ( 'codex' )
114+ }
115+ if ( opts . claude ) {
116+ selected . add ( 'claude' )
117+ }
118+ }
119+
120+ const options = selected . size
121+ ? { cwd, targets : Array . from ( selected ) }
122+ : { cwd }
123+ const results = await syncSkills ( options )
124+ if ( ! results . length ) {
125+ logger . info ( '未选择任何目标,已跳过同步。' )
126+ return
127+ }
128+ logger . info ( `[已同步的目标]:\n${ results . map ( item => `- ${ item . target } : ${ item . dest } ` ) . join ( '\n' ) } \n` )
129+ logger . success ( 'skills sync finished!' )
130+ } )
131+
89132const aiCommand = program . command ( 'ai' ) . description ( 'AI 助手工具集' )
90133
91134aiCommand . command ( 'create' )
@@ -104,7 +147,7 @@ aiCommand.command('create')
104147 const output = opts . output ?? aiConfig ?. output
105148 const baseDir = opts . dir ?? aiConfig ?. baseDir ?? defaultAgenticBaseDir
106149 const tasksFile = opts . tasks ?? aiConfig ?. tasksFile
107- const name = opts . name
150+ const templateName = opts . name
108151
109152 const shouldUseTasks = Boolean ( tasksFile && ! opts . output && ! opts . name )
110153
@@ -123,7 +166,7 @@ aiCommand.command('create')
123166 }
124167
125168 let folderName : string | undefined
126- if ( ! output && ! name ) {
169+ if ( ! output && ! templateName ) {
127170 const generated = createTimestampFolderName ( )
128171 const answer = await input ( {
129172 message : '提示词将写入哪个文件夹?(可回车确认或自定义)' ,
@@ -132,25 +175,34 @@ aiCommand.command('create')
132175 folderName = ( answer ?. trim ?.( ) ?? generated ) || generated
133176 }
134177
135- await generateAgenticTemplate ( {
178+ const templateOptions : GenerateAgenticTemplateOptions = {
136179 cwd,
137- output,
138180 force,
139181 format,
140182 baseDir,
141- name,
142- folderName,
143- } )
183+ }
184+ if ( output !== undefined ) {
185+ templateOptions . output = output
186+ }
187+ if ( templateName !== undefined ) {
188+ templateOptions . name = templateName
189+ }
190+ if ( folderName !== undefined ) {
191+ templateOptions . folderName = folderName
192+ }
193+
194+ await generateAgenticTemplate ( templateOptions )
144195 } )
145196
146197program . command ( 'new' )
147198 . description ( '创建一个新的子包' )
148199 . alias ( 'create' )
149200 . argument ( '[name]' )
150- . action ( async ( name : string ) => {
201+ . action ( async ( inputName : string ) => {
151202 const createConfig = await resolveCommandConfig ( 'create' , cwd )
152- if ( ! name ) {
153- name = await input ( {
203+ let packageName = inputName
204+ if ( ! packageName ) {
205+ packageName = await input ( {
154206 message : '请输入包名' ,
155207 default : createConfig ?. name ?? 'my-package' ,
156208 } )
@@ -162,7 +214,7 @@ program.command('new')
162214 } )
163215
164216 await createNewProject ( {
165- name,
217+ name : packageName ,
166218 cwd,
167219 type,
168220 } )
0 commit comments