Skip to content

Commit 89b355a

Browse files
committed
chore: 新增 monorepo skills sync 命令
1 parent 4fc6d58 commit 89b355a

File tree

13 files changed

+315
-18
lines changed

13 files changed

+315
-18
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@icebreakers/monorepo": minor
3+
---
4+
5+
新增 `monorepo skills sync` 命令,并将内置技能模板移动至 `resources/skills` 以便随包发布与同步。

packages/monorepo/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,17 @@ npx monorepo -h
1515
npx monorepo ai create -o agentic-task.md -f
1616
# 或使用别名
1717
npx monorepo ai new --name checkout
18+
# 同步技能到全局目录
19+
npx monorepo skills sync
20+
# 仅同步指定目标
21+
npx monorepo skills sync --codex
22+
npx monorepo skills sync --claude
1823
```
1924

2025
`monorepo ai create`(别名 `ai new`)默认会把模板写入 `agentic/prompts/<timestamp>/prompt.md`,每次都会建一个以时间命名的目录,并在命令行提示可修改该目录名称,方便追加截图等素材;也可以通过参数自定义路径。
2126

27+
`monorepo skills sync` 会将包内 `resources/skills/icebreakers-monorepo-cli` 同步到 `~/.codex/skills/icebreakers-monorepo-cli``~/.claude/skills/icebreakers-monorepo-cli`;未指定目标时会交互选择。
28+
2229
`monorepo ai create` 支持批量生成:
2330

2431
```bash

packages/monorepo/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"assets",
5353
"bin",
5454
"dist",
55+
"resources",
5556
"templates"
5657
],
5758
"engines": {

skills/icebreakers-monorepo-cli/SKILL.md renamed to packages/monorepo/resources/skills/icebreakers-monorepo-cli/SKILL.md

File renamed without changes.

skills/icebreakers-monorepo-cli/references/commands.md renamed to packages/monorepo/resources/skills/icebreakers-monorepo-cli/references/commands.md

File renamed without changes.

skills/icebreakers-monorepo-cli/references/config.md renamed to packages/monorepo/resources/skills/icebreakers-monorepo-cli/references/config.md

File renamed without changes.

skills/icebreakers-monorepo-cli/references/templates.md renamed to packages/monorepo/resources/skills/icebreakers-monorepo-cli/references/templates.md

File renamed without changes.

packages/monorepo/src/cli/program.ts

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import type { AgenticTemplateFormat } from '../commands'
2-
import type { CreateNewProjectOptions } from '../commands/create'
1+
import type { AgenticTemplateFormat, GenerateAgenticTemplateOptions } from '../commands/ai'
32
import type { CleanCommandConfig, CliOpts } from '../types'
43
import process from 'node:process'
54
import input from '@inquirer/input'
65
import select from '@inquirer/select'
76
import { 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'
98
import { defaultTemplate } from '../commands/create'
10-
import { name, version } from '../constants'
9+
import { name as cliName, version } from '../constants'
1110
import { resolveCommandConfig } from '../core/config'
1211
import { logger } from '../core/logger'
1312

13+
type SkillTarget = typeof skillTargets[number]
14+
type CreateNewProjectOptions = NonNullable<Parameters<typeof createNewProject>[0]>
15+
1416
interface 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+
2937
const 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+
89132
const aiCommand = program.command('ai').description('AI 助手工具集')
90133

91134
aiCommand.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

146197
program.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
})

packages/monorepo/src/commands/clean.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import path from 'pathe'
55
import set from 'set-value'
66
import { resolveCommandConfig } from '../core/config'
77
import { getWorkspaceData } from '../core/workspace'
8+
import { getSkillTargetPaths } from './skills'
89

910
function mergeCleanConfig(base?: CleanCommandConfig, overrides?: Partial<CleanCommandConfig>): CleanCommandConfig {
1011
const normalizedBase = base ?? {}
@@ -65,10 +66,12 @@ export async function cleanProjects(cwd: string, overrides?: Partial<CleanComman
6566

6667
const readmeZh = path.resolve(workspaceDir, 'README.zh-CN.md')
6768
const qoderDir = path.resolve(workspaceDir, '.qoder')
69+
const skillTargets = Object.values(getSkillTargetPaths())
6870
const candidates = Array.from(new Set([
6971
...cleanDirs.filter(Boolean),
7072
readmeZh,
7173
qoderDir,
74+
...skillTargets,
7275
]))
7376
await Promise.all(candidates.map(async (dir) => {
7477
if (await fs.pathExists(dir)) {

packages/monorepo/src/commands/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import type { GetWorkspacePackagesOptions } from '../types'
22
import type { AgenticTemplateFormat, AgenticTemplateTask, GenerateAgenticTemplateOptions } from './ai'
33
import type { CreateNewProjectOptions } from './create'
4+
import type { SkillTarget, SyncSkillsOptions } from './skills'
45
import { GitClient } from '../core/git'
56
import { getWorkspaceData, getWorkspacePackages } from '../core/workspace'
67
import { createTimestampFolderName, defaultAgenticBaseDir, generateAgenticTemplate, generateAgenticTemplates, loadAgenticTasks } from './ai'
78
import { cleanProjects } from './clean'
89
import { createNewProject, getCreateChoices, getTemplateMap, templateMap } from './create'
910
import { init } from './init'
1011
import { setVscodeBinaryMirror } from './mirror'
12+
import { getSkillTargetPaths, skillTargets, syncSkills } from './skills'
1113
import { syncNpmMirror } from './sync'
1214
import { upgradeMonorepo } from './upgrade'
1315

@@ -17,6 +19,8 @@ export type {
1719
CreateNewProjectOptions,
1820
GenerateAgenticTemplateOptions,
1921
GetWorkspacePackagesOptions,
22+
SkillTarget,
23+
SyncSkillsOptions,
2024
}
2125

2226
export {
@@ -27,14 +31,17 @@ export {
2731
generateAgenticTemplate,
2832
generateAgenticTemplates,
2933
getCreateChoices,
34+
getSkillTargetPaths,
3035
getTemplateMap,
3136
getWorkspaceData,
3237
getWorkspacePackages,
3338
GitClient,
3439
init,
3540
loadAgenticTasks,
3641
setVscodeBinaryMirror,
42+
skillTargets,
3743
syncNpmMirror,
44+
syncSkills,
3845
templateMap,
3946
upgradeMonorepo,
4047
}

0 commit comments

Comments
 (0)