tools-cc 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  本项目的所有重要变更都将记录在此文件中。
4
4
 
5
+ ## [1.0.5] - 2026-02-28
6
+
7
+ ### Added
8
+ - 新增部分导入功能:支持路径语法选择特定的 skills/commands/agents
9
+ - `tools-cc use source:skills/xxx` 只导入指定 skill
10
+ - `tools-cc use source:commands/` 导入所有 commands
11
+ - 新增 `--ls` 模式:`tools-cc use --ls` 列出源内容而不创建链接
12
+ - 新增 `tools-cc export` 命令:导出项目或全局配置到 JSON 文件
13
+ - `tools-cc export` 导出项目配置
14
+ - `tools-cc export -g` 导出全局配置
15
+ - 新增 `codex` 工具支持,创建 `.codex -> .toolscc` 符号链接
16
+
17
+ ### Changed
18
+ - 重构 `use` 命令,支持路径语法和 `--ls` 模式
19
+ - 重构 `useSource` 核心逻辑,支持部分导入
20
+
21
+ ### Removed
22
+ - 删除临时设计和实现文档 (docs/plans 目录)
23
+
5
24
  ## [1.0.4] - 2026-02-28
6
25
 
7
26
  ### Added
@@ -61,6 +80,7 @@
61
80
  | claude | `.claude` |
62
81
  | codebuddy | `.codebuddy` |
63
82
  | opencode | `.opencode` |
83
+ | codex | `.codex` |
64
84
 
65
85
  ---
66
86
 
package/CHANGELOG_en.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.0.5] - 2026-02-28
6
+
7
+ ### Added
8
+ - Added partial import feature: support path syntax to select specific skills/commands/agents
9
+ - `tools-cc use source:skills/xxx` import only specified skill
10
+ - `tools-cc use source:commands/` import all commands
11
+ - Added `-ls` mode: `tools-cc use -ls` list source content without creating links
12
+ - Added `tools-cc export` command: export project or global config to JSON file
13
+ - `tools-cc export` export project config
14
+ - `tools-cc export -g` export global config
15
+
16
+ ### Changed
17
+ - Refactored `use` command to support path syntax and `-ls` mode
18
+ - Refactored `useSource` core logic to support partial import
19
+
20
+ ### Removed
21
+ - Removed temporary design and implementation docs (docs/plans directory)
22
+
5
23
  ## [1.0.4] - 2026-02-28
6
24
 
7
25
  ### Added
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # tools-cc
2
2
 
3
- 一个用于统一管理多个 AI 编程工具(iflow、claude、codebuddy、opencode 等)的 skills/commands/agents 配置的 CLI 工具。通过符号链接机制,避免在多个工具间重复配置。
3
+ 一个用于统一管理多个 AI 编程工具(iflow、claude、codebuddy、opencode、codex 等)的 skills/commands/agents 配置的 CLI 工具。通过符号链接机制,避免在多个工具间重复配置。
4
4
 
5
5
  ## 安装
6
6
 
@@ -34,11 +34,11 @@ tools-cc -s list
34
34
 
35
35
  # 4. 在项目中启用配置源并创建链接
36
36
  cd my-project
37
- tools-cc use my-skills -p iflow claude
37
+ tools-cc use my-skills -p iflow claude codex
38
38
 
39
39
  # 4a. 或使用部分引入(只引入需要的 skills/commands/agents)
40
40
  tools-cc use my-skills/skills/a-skill
41
- tools-cc use my-skills -ls # 交互式选择
41
+ tools-cc use my-skills --ls # 交互式选择
42
42
 
43
43
  # 4b. 或从配置文件快速导入
44
44
  tools-cc use -c project-config.json
@@ -119,7 +119,7 @@ tools-cc export [options] # 导出项目或全局配置
119
119
  ```bash
120
120
  # 整源引入(全部 skills/commands/agents)
121
121
  tools-cc use my-skills
122
- tools-cc use my-skills -p iflow claude # 指定工具链接
122
+ tools-cc use my-skills -p iflow claude codex # 指定工具链接
123
123
 
124
124
  # 部分引入(路径语法)
125
125
  tools-cc use my-skills/skills/a-skill # 引入单个 skill
@@ -127,14 +127,14 @@ tools-cc use my-skills/commands/test # 引入单个 command
127
127
  tools-cc use my-skills/agents/reviewer # 引入单个 agent
128
128
  tools-cc use my-skills/skills/a my-skills/commands/test # 引入多项
129
129
 
130
- # 交互式选择(-ls 参数)
131
- tools-cc use my-skills -ls # 分组展示,勾选引入
130
+ # 交互式选择(--ls 参数)
131
+ tools-cc use my-skills --ls # 分组展示,勾选引入
132
132
 
133
133
  # 从配置文件导入
134
134
  tools-cc use -c project-config.json # 快速恢复项目配置
135
135
 
136
136
  # 使用 "." 表示当前项目已配置的源(只创建链接,不复制内容)
137
- tools-cc use . -p iflow claude
137
+ tools-cc use . -p iflow claude codex
138
138
  ```
139
139
 
140
140
  #### `export` 命令详解
@@ -178,6 +178,7 @@ tools-cc --version # 显示版本号
178
178
  | claude | `.claude` |
179
179
  | codebuddy | `.codebuddy` |
180
180
  | opencode | `.opencode` |
181
+ | codex | `.codex` |
181
182
 
182
183
  ## 配置源结构
183
184
 
@@ -224,7 +225,8 @@ my-project/
224
225
  │ └── agents/
225
226
  │ └── my-skills/
226
227
  ├── .iflow -> .toolscc # 符号链接
227
- └── .claude -> .toolscc
228
+ ├── .claude -> .toolscc
229
+ └── .codex -> .toolscc
228
230
  ```
229
231
 
230
232
  ## 配置文件
@@ -258,7 +260,7 @@ my-project/
258
260
  "agents": ["*"]
259
261
  }
260
262
  },
261
- "links": ["iflow", "claude"]
263
+ "links": ["iflow", "claude", "codex"]
262
264
  }
263
265
  ```
264
266
 
@@ -14,7 +14,7 @@ ${chalk_1.default.bold.cyan('═════════════════
14
14
 
15
15
  ${chalk_1.default.bold('DESCRIPTION / 描述')}
16
16
  A CLI tool for managing skills/commands/agents configurations across multiple
17
- AI coding tools (iflow, claude, codebuddy, opencode, etc.) via symlinks.
17
+ AI coding tools (iflow, claude, codebuddy, opencode, codex, etc.) via symlinks.
18
18
 
19
19
  一个用于统一管理多个 AI 编程工具配置的命令行工具,通过符号链接机制避免重复配置。
20
20
 
@@ -55,6 +55,7 @@ ${chalk_1.default.bold('SUPPORTED TOOLS / 支持的工具')}
55
55
  claude → .claude
56
56
  codebuddy → .codebuddy
57
57
  opencode → .opencode
58
+ codex → .codex
58
59
 
59
60
  ${chalk_1.default.bold('EXAMPLES / 示例')}
60
61
  ${chalk_1.default.gray('# Add a git source / 添加 Git 配置源')}
@@ -67,7 +68,7 @@ ${chalk_1.default.bold('EXAMPLES / 示例')}
67
68
  tools-cc sources list
68
69
 
69
70
  ${chalk_1.default.gray('# Use sources in project / 在项目中启用配置源')}
70
- tools-cc use my-skills -p iflow claude
71
+ tools-cc use my-skills -p iflow claude codex
71
72
 
72
73
  ${chalk_1.default.gray('# Check project status / 检查项目状态')}
73
74
  tools-cc status
@@ -9,12 +9,12 @@ export interface UseOptions {
9
9
  /**
10
10
  * 处理 use 命令
11
11
  *
12
- * 支持多种模式:
12
+ * 支持多种模式�?
13
13
  * 1. 配置导入模式: tools-cc use -c config.json
14
- * 2. 交互选择模式: tools-cc use my-source -ls
14
+ * 2. 交互选择模式: tools-cc use my-source --ls
15
15
  * 3. 路径语法模式: tools-cc use my-source/skills/a-skill
16
16
  * 4. 整体导入模式: tools-cc use my-source
17
- * 5. 点模式: tools-cc use . (使用已配置源)
17
+ * 5. 点模�? tools-cc use . (使用已配置源)
18
18
  */
19
19
  export declare function handleUse(sourceSpecs: string[], options: UseOptions): Promise<void>;
20
20
  export declare function handleList(): Promise<void>;
@@ -22,25 +22,18 @@ const SUPPORTED_TOOLS = {
22
22
  iflow: '.iflow',
23
23
  claude: '.claude',
24
24
  codebuddy: '.codebuddy',
25
- opencode: '.opencode'
26
- };
27
- /**
28
- * 默认选择配置 - 导入所有内容
29
- */
30
- const DEFAULT_SELECTION = {
31
- skills: ['*'],
32
- commands: ['*'],
33
- agents: ['*']
25
+ opencode: '.opencode',
26
+ codex: '.codex'
34
27
  };
35
28
  /**
36
29
  * 处理 use 命令
37
30
  *
38
- * 支持多种模式:
31
+ * 支持多种模式�?
39
32
  * 1. 配置导入模式: tools-cc use -c config.json
40
- * 2. 交互选择模式: tools-cc use my-source -ls
33
+ * 2. 交互选择模式: tools-cc use my-source --ls
41
34
  * 3. 路径语法模式: tools-cc use my-source/skills/a-skill
42
35
  * 4. 整体导入模式: tools-cc use my-source
43
- * 5. 点模式: tools-cc use . (使用已配置源)
36
+ * 5. 点模�? tools-cc use . (使用已配置源)
44
37
  */
45
38
  async function handleUse(sourceSpecs, options) {
46
39
  const projectDir = process.cwd();
@@ -51,15 +44,15 @@ async function handleUse(sourceSpecs, options) {
51
44
  await handleConfigImportMode(options.config, projectDir, options.projects);
52
45
  return;
53
46
  }
54
- // 2. 点模式:使用当前项目已配置的源
47
+ // 2. 点模式:使用当前项目已配置的�?
55
48
  if (sourceSpecs.length === 1 && sourceSpecs[0] === '.') {
56
49
  await handleDotMode(projectDir, toolsccDir, configFile, options.projects);
57
50
  return;
58
51
  }
59
- // 3. 交互选择模式:单个源 + -ls 选项
52
+ // 3. 交互选择模式:单个源 + --ls 选项
60
53
  if (options.ls && sourceSpecs.length === 1) {
61
54
  const parsed = (0, parsePath_1.parseSourcePath)(sourceSpecs[0]);
62
- // 只有源名称时才进入交互模式
55
+ // 只有源名称时才进入交互模�?
63
56
  if (!parsed.type && parsed.sourceName) {
64
57
  await handleInteractiveMode(parsed.sourceName, projectDir, options.projects);
65
58
  return;
@@ -75,17 +68,17 @@ async function handleUse(sourceSpecs, options) {
75
68
  }
76
69
  // 5. 解析路径语法并构建选择配置
77
70
  const selectionMap = (0, parsePath_1.buildSelectionFromPaths)(sourceSpecs);
78
- // 初始化项目
71
+ // 初始化项�?
79
72
  await (0, project_1.initProject)(projectDir);
80
73
  // 应用每个源的选择配置
81
74
  for (const [sourceName, selection] of Object.entries(selectionMap)) {
82
75
  try {
83
76
  const sourcePath = await (0, source_1.getSourcePath)(sourceName, path_1.GLOBAL_CONFIG_DIR);
84
77
  await (0, project_1.useSource)(sourceName, sourcePath, projectDir, selection);
85
- console.log(chalk_1.default.green(`✓ Using source: ${sourceName}`));
78
+ console.log(chalk_1.default.green(`�?Using source: ${sourceName}`));
86
79
  }
87
80
  catch (error) {
88
- console.log(chalk_1.default.red(`✗ Failed to use ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
81
+ console.log(chalk_1.default.red(`�?Failed to use ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
89
82
  }
90
83
  }
91
84
  // 创建符号链接
@@ -100,18 +93,18 @@ async function handleConfigImportMode(configPath, projectDir, projects) {
100
93
  const configFile = (0, path_1.getProjectConfigPath)(projectDir);
101
94
  // 解析配置文件路径
102
95
  const resolvedPath = path_2.default.resolve(configPath);
103
- // 定义源路径解析函数
96
+ // 定义源路径解析函�?
104
97
  const resolveSourcePath = async (sourceName) => {
105
98
  return await (0, source_1.getSourcePath)(sourceName, path_1.GLOBAL_CONFIG_DIR);
106
99
  };
107
100
  // 导入配置
108
101
  await (0, project_1.importProjectConfig)(resolvedPath, projectDir, resolveSourcePath);
109
- console.log(chalk_1.default.green(`✓ Imported config from: ${resolvedPath}`));
102
+ console.log(chalk_1.default.green(`�?Imported config from: ${resolvedPath}`));
110
103
  // 创建符号链接
111
104
  await createToolLinks(projectDir, toolsccDir, configFile, projects);
112
105
  }
113
106
  catch (error) {
114
- console.log(chalk_1.default.red(`✗ Failed to import config: ${error instanceof Error ? error.message : 'Unknown error'}`));
107
+ console.log(chalk_1.default.red(`�?Failed to import config: ${error instanceof Error ? error.message : 'Unknown error'}`));
115
108
  }
116
109
  }
117
110
  /**
@@ -132,7 +125,7 @@ async function handleDotMode(projectDir, toolsccDir, configFile, projects) {
132
125
  await createToolLinks(projectDir, toolsccDir, configFile, projects);
133
126
  }
134
127
  /**
135
- * 交互选择模式:显示技能/命令/代理选择列表
128
+ * 交互选择模式:显示技�?命令/代理选择列表
136
129
  */
137
130
  async function handleInteractiveMode(sourceName, projectDir, projects) {
138
131
  try {
@@ -141,21 +134,21 @@ async function handleInteractiveMode(sourceName, projectDir, projects) {
141
134
  // 构建选项列表
142
135
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
143
136
  const choices = [];
144
- // Skills
137
+ // Skills �?
145
138
  if (manifest.skills && manifest.skills.length > 0) {
146
139
  choices.push(new inquirer_1.default.Separator(`--- Skills (${manifest.skills.length}) ---`));
147
140
  for (const skill of manifest.skills) {
148
141
  choices.push({ name: skill, value: `skills/${skill}` });
149
142
  }
150
143
  }
151
- // Commands
144
+ // Commands �?
152
145
  if (manifest.commands && manifest.commands.length > 0) {
153
146
  choices.push(new inquirer_1.default.Separator(`--- Commands (${manifest.commands.length}) ---`));
154
147
  for (const cmd of manifest.commands) {
155
148
  choices.push({ name: cmd, value: `commands/${cmd}` });
156
149
  }
157
150
  }
158
- // Agents
151
+ // Agents �?
159
152
  if (manifest.agents && manifest.agents.length > 0) {
160
153
  choices.push(new inquirer_1.default.Separator(`--- Agents (${manifest.agents.length}) ---`));
161
154
  for (const agent of manifest.agents) {
@@ -180,7 +173,7 @@ async function handleInteractiveMode(sourceName, projectDir, projects) {
180
173
  console.log(chalk_1.default.gray('No items selected.'));
181
174
  return;
182
175
  }
183
- // 将选择转换为 SourceSelection
176
+ // 将选择转换�?SourceSelection
184
177
  const selection = {
185
178
  skills: [],
186
179
  commands: [],
@@ -198,14 +191,14 @@ async function handleInteractiveMode(sourceName, projectDir, projects) {
198
191
  // 初始化项目并应用选择
199
192
  await (0, project_1.initProject)(projectDir);
200
193
  await (0, project_1.useSource)(sourceName, sourcePath, projectDir, selection);
201
- console.log(chalk_1.default.green(`✓ Using source: ${sourceName}`));
194
+ console.log(chalk_1.default.green(`�?Using source: ${sourceName}`));
202
195
  // 创建符号链接
203
196
  const toolsccDir = (0, path_1.getToolsccDir)(projectDir);
204
197
  const configFile = (0, path_1.getProjectConfigPath)(projectDir);
205
198
  await createToolLinks(projectDir, toolsccDir, configFile, projects);
206
199
  }
207
200
  catch (error) {
208
- console.log(chalk_1.default.red(`✗ Failed to use ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
201
+ console.log(chalk_1.default.red(`�?Failed to use ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
209
202
  }
210
203
  }
211
204
  /**
@@ -242,10 +235,10 @@ async function createToolLinks(projectDir, toolsccDir, configFile, projects) {
242
235
  const linkPath = path_2.default.join(projectDir, linkName);
243
236
  try {
244
237
  await (0, symlink_1.createSymlink)(toolsccDir, linkPath, true);
245
- console.log(chalk_1.default.green(`✓ Linked: ${linkName} -> .toolscc`));
238
+ console.log(chalk_1.default.green(`�?Linked: ${linkName} -> .toolscc`));
246
239
  }
247
240
  catch (error) {
248
- console.log(chalk_1.default.red(`✗ Failed to link ${linkName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
241
+ console.log(chalk_1.default.red(`�?Failed to link ${linkName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
249
242
  }
250
243
  }
251
244
  // 更新项目配置
@@ -270,10 +263,10 @@ async function handleRemove(sourceName) {
270
263
  const projectDir = process.cwd();
271
264
  try {
272
265
  await (0, project_1.unuseSource)(sourceName, projectDir);
273
- console.log(chalk_1.default.green(`✓ Removed source: ${sourceName}`));
266
+ console.log(chalk_1.default.green(`�?Removed source: ${sourceName}`));
274
267
  }
275
268
  catch (error) {
276
- console.log(chalk_1.default.red(`✗ ${error instanceof Error ? error.message : 'Unknown error'}`));
269
+ console.log(chalk_1.default.red(`�?${error instanceof Error ? error.message : 'Unknown error'}`));
277
270
  }
278
271
  }
279
272
  async function handleStatus() {
@@ -281,12 +274,12 @@ async function handleStatus() {
281
274
  const sources = await (0, project_1.listUsedSources)(projectDir);
282
275
  console.log(chalk_1.default.bold('\nProject Status:'));
283
276
  console.log(chalk_1.default.gray(` Directory: ${projectDir}`));
284
- // 检查 .toolscc
277
+ // 检�?.toolscc
285
278
  const toolsccDir = (0, path_1.getToolsccDir)(projectDir);
286
279
  console.log(` .toolscc: ${await fs_extra_1.default.pathExists(toolsccDir) ? chalk_1.default.green('exists') : chalk_1.default.red('not found')}`);
287
- // 检查 sources
280
+ // 检�?sources
288
281
  console.log(` Sources: ${sources.length > 0 ? sources.map(s => chalk_1.default.cyan(s)).join(', ') : chalk_1.default.gray('none')}`);
289
- // 检查 links
282
+ // 检�?links
290
283
  const configFile = (0, path_1.getProjectConfigPath)(projectDir);
291
284
  if (await fs_extra_1.default.pathExists(configFile)) {
292
285
  const config = await fs_extra_1.default.readJson(configFile);
@@ -305,7 +298,7 @@ async function handleStatus() {
305
298
  async function handleProjectUpdate(sourceNames) {
306
299
  const projectDir = process.cwd();
307
300
  const configFile = (0, path_1.getProjectConfigPath)(projectDir);
308
- // 检查项目是否已初始化
301
+ // 检查项目是否已初始�?
309
302
  if (!(await fs_extra_1.default.pathExists(configFile))) {
310
303
  console.log(chalk_1.default.yellow('Project not initialized. Run `tools-cc use <source>` first.'));
311
304
  return;
@@ -327,18 +320,18 @@ async function handleProjectUpdate(sourceNames) {
327
320
  }
328
321
  sourcesToUpdate = sourcesToUpdate.filter((s) => configuredSources.includes(s));
329
322
  }
330
- // 更新每个配置源
323
+ // 更新每个配置�?
331
324
  for (const sourceName of sourcesToUpdate) {
332
325
  try {
333
326
  const sourcePath = await (0, source_1.getSourcePath)(sourceName, path_1.GLOBAL_CONFIG_DIR);
334
327
  // 使用保存的选择配置进行更新
335
328
  const selection = config.sources[sourceName];
336
329
  await (0, project_1.useSource)(sourceName, sourcePath, projectDir, selection);
337
- console.log(chalk_1.default.green(`✓ Updated source: ${sourceName}`));
330
+ console.log(chalk_1.default.green(`�?Updated source: ${sourceName}`));
338
331
  }
339
332
  catch (error) {
340
- console.log(chalk_1.default.red(`✗ Failed to update ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
333
+ console.log(chalk_1.default.red(`�?Failed to update ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
341
334
  }
342
335
  }
343
- console.log(chalk_1.default.green(`\nProject update complete`));
336
+ console.log(chalk_1.default.green(`\n�?Project update complete`));
344
337
  }
package/dist/index.js CHANGED
@@ -80,8 +80,8 @@ configCmd
80
80
  program
81
81
  .command('use [sources...]')
82
82
  .description('Use sources in current project')
83
- .option('-p, --projects <tools...>', 'Tools to link (iflow, claude, codebuddy, opencode)')
84
- .option('-ls', 'Interactive selection mode for single source')
83
+ .option('-p, --projects <tools...>', 'Tools to link (iflow, claude, codebuddy, opencode, codex)')
84
+ .option('-l, --ls', 'Interactive selection mode for single source')
85
85
  .option('-c, --config <file>', 'Import from config file')
86
86
  .action(async (sources, options) => {
87
87
  await (0, use_1.handleUse)(sources, options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tools-cc",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "tools-cc [options] <command> [args]",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -9,7 +9,7 @@ ${chalk.bold.cyan('════════════════════
9
9
 
10
10
  ${chalk.bold('DESCRIPTION / 描述')}
11
11
  A CLI tool for managing skills/commands/agents configurations across multiple
12
- AI coding tools (iflow, claude, codebuddy, opencode, etc.) via symlinks.
12
+ AI coding tools (iflow, claude, codebuddy, opencode, codex, etc.) via symlinks.
13
13
 
14
14
  一个用于统一管理多个 AI 编程工具配置的命令行工具,通过符号链接机制避免重复配置。
15
15
 
@@ -50,6 +50,7 @@ ${chalk.bold('SUPPORTED TOOLS / 支持的工具')}
50
50
  claude → .claude
51
51
  codebuddy → .codebuddy
52
52
  opencode → .opencode
53
+ codex → .codex
53
54
 
54
55
  ${chalk.bold('EXAMPLES / 示例')}
55
56
  ${chalk.gray('# Add a git source / 添加 Git 配置源')}
@@ -62,7 +63,7 @@ ${chalk.bold('EXAMPLES / 示例')}
62
63
  tools-cc sources list
63
64
 
64
65
  ${chalk.gray('# Use sources in project / 在项目中启用配置源')}
65
- tools-cc use my-skills -p iflow claude
66
+ tools-cc use my-skills -p iflow claude codex
66
67
 
67
68
  ${chalk.gray('# Check project status / 检查项目状态')}
68
69
  tools-cc status