tools-cc 1.0.6 → 1.0.7

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,24 @@
2
2
 
3
3
  本项目的所有重要变更都将记录在此文件中。
4
4
 
5
+ ## [1.0.7] - 2026-03-02
6
+
7
+ ### Fixed
8
+ - 修复 `tools-cc update` 命令无法正确识别旧版数组格式配置的问题(sources 为数组时会被错误解析为索引)
9
+
10
+ ### Changed
11
+ - 更新帮助文档,完善命令说明和示例
12
+
13
+ ## [1.0.6] - 2026-03-02
14
+
15
+ ### Added
16
+ - 新增无参数交互式源选择:`tools-cc use` 直接运行显示源列表供选择
17
+ - 新增配置文件导入功能:`tools-cc use -c config.json` 从导出的配置文件快速恢复项目配置
18
+
19
+ ### Changed
20
+ - 重构 `use` 命令,统一支持多种模式(配置导入、交互选择、路径语法、整体导入、点模式)
21
+ - 优化交互选择模式,支持分组展示 skills/commands/agents
22
+
5
23
  ## [1.0.5] - 2026-02-28
6
24
 
7
25
  ### Added
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.7] - 2026-03-02
6
+
7
+ ### Fixed
8
+ - Fixed `tools-cc update` command failing to recognize legacy array format config (sources array was incorrectly parsed as indices)
9
+
10
+ ### Changed
11
+ - Updated help documentation with improved command descriptions and examples
12
+
13
+ ## [1.0.6] - 2026-03-02
14
+
15
+ ### Added
16
+ - Added interactive source selection: `tools-cc use` without arguments shows source list for selection
17
+ - Added config import feature: `tools-cc use -c config.json` to quickly restore project config from exported file
18
+
19
+ ### Changed
20
+ - Refactored `use` command to support multiple modes (config import, interactive selection, path syntax, full import, dot mode)
21
+ - Improved interactive selection mode with grouped display of skills/commands/agents
22
+
5
23
  ## [1.0.5] - 2026-02-28
6
24
 
7
25
  ### Added
package/README.md CHANGED
@@ -36,11 +36,14 @@ tools-cc -s list
36
36
  cd my-project
37
37
  tools-cc use my-skills -p iflow claude codex
38
38
 
39
- # 4a. 或使用部分引入(只引入需要的 skills/commands/agents)
39
+ # 4a. 无参数运行,交互式选择源
40
+ tools-cc use # 显示源列表供选择
41
+
42
+ # 4b. 或使用部分引入(只引入需要的 skills/commands/agents)
40
43
  tools-cc use my-skills/skills/a-skill
41
- tools-cc use my-skills --ls # 交互式选择
44
+ tools-cc use my-skills --ls # 交互式选择内容
42
45
 
43
- # 4b. 或从配置文件快速导入
46
+ # 4c. 或从配置文件快速导入
44
47
  tools-cc use -c project-config.json
45
48
 
46
49
  # 5. 查看项目状态
@@ -117,6 +120,9 @@ tools-cc export [options] # 导出项目或全局配置
117
120
  #### `use` 命令详解
118
121
 
119
122
  ```bash
123
+ # 无参数运行:交互式选择源
124
+ tools-cc use # 显示可用源列表供选择
125
+
120
126
  # 整源引入(全部 skills/commands/agents)
121
127
  tools-cc use my-skills
122
128
  tools-cc use my-skills -p iflow claude codex # 指定工具链接
@@ -127,7 +133,7 @@ tools-cc use my-skills/commands/test # 引入单个 command
127
133
  tools-cc use my-skills/agents/reviewer # 引入单个 agent
128
134
  tools-cc use my-skills/skills/a my-skills/commands/test # 引入多项
129
135
 
130
- # 交互式选择(--ls 参数)
136
+ # 交互式选择内容(--ls 参数)
131
137
  tools-cc use my-skills --ls # 分组展示,勾选引入
132
138
 
133
139
  # 从配置文件导入
package/README_en.md CHANGED
@@ -34,7 +34,8 @@ tools-cc -s list
34
34
 
35
35
  # 4. Enable configuration sources in a project and create links
36
36
  cd my-project
37
- tools-cc use my-skills -p iflow claude
37
+ tools-cc use # Interactive source selection
38
+ tools-cc use my-skills -p iflow claude codex
38
39
 
39
40
  # 5. View project status
40
41
  tools-cc status
@@ -99,11 +100,50 @@ tools-cc sources scan # Scan sourcesDir to auto-discover and
99
100
  ### Project Configuration
100
101
 
101
102
  ```bash
102
- tools-cc use [sources...] [-p tools...] # Enable configuration sources and create symbolic links
103
+ tools-cc use [sources...] [options] # Enable configuration sources and create symbolic links
103
104
  tools-cc update [sources...] # Sync configuration source content to project .toolscc directory
104
105
  tools-cc list # List enabled configuration sources
105
106
  tools-cc rm <source> # Disable configuration source
106
107
  tools-cc status # View project status
108
+ tools-cc export [options] # Export project or global config
109
+ ```
110
+
111
+ #### `use` Command Details
112
+
113
+ ```bash
114
+ # No arguments: interactive source selection
115
+ tools-cc use # Show available sources for selection
116
+
117
+ # Full source import (all skills/commands/agents)
118
+ tools-cc use my-skills
119
+ tools-cc use my-skills -p iflow claude codex # Specify tool links
120
+
121
+ # Partial import (path syntax)
122
+ tools-cc use my-skills/skills/a-skill # Import single skill
123
+ tools-cc use my-skills/commands/test # Import single command
124
+ tools-cc use my-skills/agents/reviewer # Import single agent
125
+ tools-cc use my-skills/skills/a my-skills/commands/test # Import multiple
126
+
127
+ # Interactive content selection (--ls flag)
128
+ tools-cc use my-skills --ls # Grouped display, checkbox selection
129
+
130
+ # Import from config file
131
+ tools-cc use -c project-config.json # Quick restore project config
132
+
133
+ # Use "." for existing project sources (only create links, no copy)
134
+ tools-cc use . -p iflow claude codex
135
+ ```
136
+
137
+ #### `export` Command Details
138
+
139
+ ```bash
140
+ # Export project config
141
+ tools-cc export # Export to .toolscc-export.json
142
+ tools-cc export -o my-config.json # Specify output path
143
+
144
+ # Export global config
145
+ tools-cc export --global # Export to .toolscc-global-export.json
146
+ tools-cc export --global -o global.json # Specify output path
107
147
  ```
108
148
 
109
149
  ### Config Management
@@ -135,6 +175,7 @@ tools-cc --version # Display version number
135
175
  | claude | `.claude` |
136
176
  | codebuddy | `.codebuddy` |
137
177
  | opencode | `.opencode` |
178
+ | codex | `.codex` |
138
179
 
139
180
  ## Configuration Source Structure
140
181
 
@@ -208,11 +249,22 @@ my-project/
208
249
 
209
250
  ```json
210
251
  {
211
- "sources": ["my-skills"],
212
- "links": ["iflow", "claude"]
252
+ "sources": {
253
+ "my-skills": {
254
+ "skills": ["a-skill", "b-skill"],
255
+ "commands": ["test"],
256
+ "agents": ["*"]
257
+ }
258
+ },
259
+ "links": ["iflow", "claude", "codex"]
213
260
  }
214
261
  ```
215
262
 
263
+ **Notes:**
264
+ - `sources` records specific content imported from each source
265
+ - `["*"]` means import all content of that type
266
+ - `[]` means import nothing of that type
267
+
216
268
  ## License
217
269
 
218
270
  MIT
@@ -28,7 +28,8 @@ ${chalk_1.default.bold('COMMANDS / 命令')}
28
28
  tools-cc sources add <name> <path-or-url> Add a source / 添加配置源
29
29
  tools-cc sources list, ls List all sources / 列出所有配置源
30
30
  tools-cc sources remove, rm <name> Remove a source / 移除配置源
31
- tools-cc sources update, up [name] Update source(s) / 更新配置源
31
+ tools-cc sources update, up [name] git pull update / 更新源代码
32
+ tools-cc sources scan Scan dir for sources / 扫描发现新源
32
33
 
33
34
  ${chalk_1.default.gray('Shortcut: -s')} e.g., tools-cc -s add my-skills https://github.com/user/skills.git
34
35
 
@@ -40,16 +41,27 @@ ${chalk_1.default.bold('COMMANDS / 命令')}
40
41
  ${chalk_1.default.gray('Shortcut: -c')} e.g., tools-cc -c set sourcesDir D:/skills
41
42
 
42
43
  ${chalk_1.default.cyan('Project Commands / 项目命令')}
43
- tools-cc use [sources...] [-p tools...] Use sources in project / 在项目中启用配置源
44
+ tools-cc use [sources...] [options] Use sources in project / 在项目中启用配置源
45
+ tools-cc update [sources...] Sync source content to project / 同步内容到项目
44
46
  tools-cc list List used sources / 列出已启用的配置源
45
47
  tools-cc rm <source> Remove source from project / 禁用配置源
46
48
  tools-cc status Show project status / 显示项目状态
49
+ tools-cc export [options] Export config / 导出配置
47
50
 
48
51
  ${chalk_1.default.cyan('Help / 帮助')}
49
52
  tools-cc help Show this help / 显示此帮助信息
50
53
  tools-cc --help, -h Show command help / 显示命令帮助
51
54
  tools-cc --version, -V Show version / 显示版本号
52
55
 
56
+ ${chalk_1.default.bold('USE OPTIONS / use 命令选项')}
57
+ -p, --tools <tools...> Target tools (iflow, claude, etc.) / 目标工具
58
+ --ls Interactive selection / 交互式选择内容
59
+ -c, --config <file> Import from config file / 从配置文件导入
60
+
61
+ ${chalk_1.default.bold('EXPORT OPTIONS / export 命令选项')}
62
+ -o, --output <file> Output file path / 输出文件路径
63
+ --global Export global config / 导出全局配置
64
+
53
65
  ${chalk_1.default.bold('SUPPORTED TOOLS / 支持的工具')}
54
66
  iflow → .iflow
55
67
  claude → .claude
@@ -64,21 +76,36 @@ ${chalk_1.default.bold('EXAMPLES / 示例')}
64
76
  ${chalk_1.default.gray('# Add a local source / 添加本地配置源')}
65
77
  tools-cc sources add local-skills D:/path/to/local-skills
66
78
 
79
+ ${chalk_1.default.gray('# Scan for sources / 扫描发现配置源')}
80
+ tools-cc sources scan
81
+
67
82
  ${chalk_1.default.gray('# List all sources / 列出所有配置源')}
68
83
  tools-cc sources list
69
84
 
70
85
  ${chalk_1.default.gray('# Use sources in project / 在项目中启用配置源')}
71
86
  tools-cc use my-skills -p iflow claude codex
72
87
 
88
+ ${chalk_1.default.gray('# Interactive selection / 交互式选择内容')}
89
+ tools-cc use my-skills --ls
90
+
91
+ ${chalk_1.default.gray('# Import from config file / 从配置文件导入')}
92
+ tools-cc use -c project-config.json
93
+
94
+ ${chalk_1.default.gray('# Sync source content to project / 同步源内容到项目')}
95
+ tools-cc update my-skills
96
+
73
97
  ${chalk_1.default.gray('# Check project status / 检查项目状态')}
74
98
  tools-cc status
75
99
 
100
+ ${chalk_1.default.gray('# Export project config / 导出项目配置')}
101
+ tools-cc export -o my-config.json
102
+
76
103
  ${chalk_1.default.gray('# Show full configuration / 显示完整配置')}
77
104
  tools-cc config list
78
105
 
79
106
  ${chalk_1.default.bold('MORE INFO / 更多信息')}
80
- GitHub: https://github.com/user/tools-cc
81
- Docs: https://github.com/user/tools-cc#readme
107
+ GitHub: https://github.com/q759410559/tools-cc
108
+ Docs: https://github.com/q759410559/tools-cc#readme
82
109
 
83
110
  ${chalk_1.default.bold.cyan('═══════════════════════════════════════════════════════════════════════════')}
84
111
  `);
@@ -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
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>;
@@ -11,6 +11,7 @@ exports.handleProjectUpdate = handleProjectUpdate;
11
11
  const chalk_1 = __importDefault(require("chalk"));
12
12
  const inquirer_1 = __importDefault(require("inquirer"));
13
13
  const project_1 = require("../core/project");
14
+ const config_1 = require("../types/config");
14
15
  const source_1 = require("../core/source");
15
16
  const manifest_1 = require("../core/manifest");
16
17
  const symlink_1 = require("../core/symlink");
@@ -28,12 +29,12 @@ const SUPPORTED_TOOLS = {
28
29
  /**
29
30
  * 处理 use 命令
30
31
  *
31
- * 支持多种模式�?
32
+ * 支持多种模式:
32
33
  * 1. 配置导入模式: tools-cc use -c config.json
33
34
  * 2. 交互选择模式: tools-cc use my-source --ls
34
35
  * 3. 路径语法模式: tools-cc use my-source/skills/a-skill
35
36
  * 4. 整体导入模式: tools-cc use my-source
36
- * 5. 点模�? tools-cc use . (使用已配置源)
37
+ * 5. 点模式: tools-cc use . (使用已配置源)
37
38
  */
38
39
  async function handleUse(sourceSpecs, options) {
39
40
  const projectDir = process.cwd();
@@ -44,7 +45,7 @@ async function handleUse(sourceSpecs, options) {
44
45
  await handleConfigImportMode(options.config, projectDir, options.projects);
45
46
  return;
46
47
  }
47
- // 2. 点模式:使用当前项目已配置的�?
48
+ // 2. 点模式:使用当前项目已配置的源
48
49
  if (sourceSpecs.length === 1 && sourceSpecs[0] === '.') {
49
50
  await handleDotMode(projectDir, toolsccDir, configFile, options.projects);
50
51
  return;
@@ -52,7 +53,7 @@ async function handleUse(sourceSpecs, options) {
52
53
  // 3. 交互选择模式:单个源 + --ls 选项
53
54
  if (options.ls && sourceSpecs.length === 1) {
54
55
  const parsed = (0, parsePath_1.parseSourcePath)(sourceSpecs[0]);
55
- // 只有源名称时才进入交互模�?
56
+ // 只有源名称时才进入交互模式
56
57
  if (!parsed.type && parsed.sourceName) {
57
58
  await handleInteractiveMode(parsed.sourceName, projectDir, options.projects);
58
59
  return;
@@ -68,17 +69,17 @@ async function handleUse(sourceSpecs, options) {
68
69
  }
69
70
  // 5. 解析路径语法并构建选择配置
70
71
  const selectionMap = (0, parsePath_1.buildSelectionFromPaths)(sourceSpecs);
71
- // 初始化项�?
72
+ // 初始化项目
72
73
  await (0, project_1.initProject)(projectDir);
73
74
  // 应用每个源的选择配置
74
75
  for (const [sourceName, selection] of Object.entries(selectionMap)) {
75
76
  try {
76
77
  const sourcePath = await (0, source_1.getSourcePath)(sourceName, path_1.GLOBAL_CONFIG_DIR);
77
78
  await (0, project_1.useSource)(sourceName, sourcePath, projectDir, selection);
78
- console.log(chalk_1.default.green(`�?Using source: ${sourceName}`));
79
+ console.log(chalk_1.default.green(`✓ Using source: ${sourceName}`));
79
80
  }
80
81
  catch (error) {
81
- console.log(chalk_1.default.red(`�?Failed to use ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
82
+ console.log(chalk_1.default.red(`✗ Failed to use ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
82
83
  }
83
84
  }
84
85
  // 创建符号链接
@@ -93,18 +94,18 @@ async function handleConfigImportMode(configPath, projectDir, projects) {
93
94
  const configFile = (0, path_1.getProjectConfigPath)(projectDir);
94
95
  // 解析配置文件路径
95
96
  const resolvedPath = path_2.default.resolve(configPath);
96
- // 定义源路径解析函�?
97
+ // 定义源路径解析函数
97
98
  const resolveSourcePath = async (sourceName) => {
98
99
  return await (0, source_1.getSourcePath)(sourceName, path_1.GLOBAL_CONFIG_DIR);
99
100
  };
100
101
  // 导入配置
101
102
  await (0, project_1.importProjectConfig)(resolvedPath, projectDir, resolveSourcePath);
102
- console.log(chalk_1.default.green(`�?Imported config from: ${resolvedPath}`));
103
+ console.log(chalk_1.default.green(`✓ Imported config from: ${resolvedPath}`));
103
104
  // 创建符号链接
104
105
  await createToolLinks(projectDir, toolsccDir, configFile, projects);
105
106
  }
106
107
  catch (error) {
107
- console.log(chalk_1.default.red(`�?Failed to import config: ${error instanceof Error ? error.message : 'Unknown error'}`));
108
+ console.log(chalk_1.default.red(`✗ Failed to import config: ${error instanceof Error ? error.message : 'Unknown error'}`));
108
109
  }
109
110
  }
110
111
  /**
@@ -125,7 +126,7 @@ async function handleDotMode(projectDir, toolsccDir, configFile, projects) {
125
126
  await createToolLinks(projectDir, toolsccDir, configFile, projects);
126
127
  }
127
128
  /**
128
- * 交互选择模式:显示技�?命令/代理选择列表
129
+ * 交互选择模式:显示技能/命令/代理选择列表
129
130
  */
130
131
  async function handleInteractiveMode(sourceName, projectDir, projects) {
131
132
  try {
@@ -134,21 +135,21 @@ async function handleInteractiveMode(sourceName, projectDir, projects) {
134
135
  // 构建选项列表
135
136
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
136
137
  const choices = [];
137
- // Skills �?
138
+ // Skills
138
139
  if (manifest.skills && manifest.skills.length > 0) {
139
140
  choices.push(new inquirer_1.default.Separator(`--- Skills (${manifest.skills.length}) ---`));
140
141
  for (const skill of manifest.skills) {
141
142
  choices.push({ name: skill, value: `skills/${skill}` });
142
143
  }
143
144
  }
144
- // Commands �?
145
+ // Commands
145
146
  if (manifest.commands && manifest.commands.length > 0) {
146
147
  choices.push(new inquirer_1.default.Separator(`--- Commands (${manifest.commands.length}) ---`));
147
148
  for (const cmd of manifest.commands) {
148
149
  choices.push({ name: cmd, value: `commands/${cmd}` });
149
150
  }
150
151
  }
151
- // Agents �?
152
+ // Agents
152
153
  if (manifest.agents && manifest.agents.length > 0) {
153
154
  choices.push(new inquirer_1.default.Separator(`--- Agents (${manifest.agents.length}) ---`));
154
155
  for (const agent of manifest.agents) {
@@ -173,7 +174,7 @@ async function handleInteractiveMode(sourceName, projectDir, projects) {
173
174
  console.log(chalk_1.default.gray('No items selected.'));
174
175
  return;
175
176
  }
176
- // 将选择转换�?SourceSelection
177
+ // 将选择转换为 SourceSelection
177
178
  const selection = {
178
179
  skills: [],
179
180
  commands: [],
@@ -191,14 +192,14 @@ async function handleInteractiveMode(sourceName, projectDir, projects) {
191
192
  // 初始化项目并应用选择
192
193
  await (0, project_1.initProject)(projectDir);
193
194
  await (0, project_1.useSource)(sourceName, sourcePath, projectDir, selection);
194
- console.log(chalk_1.default.green(`�?Using source: ${sourceName}`));
195
+ console.log(chalk_1.default.green(`✓ Using source: ${sourceName}`));
195
196
  // 创建符号链接
196
197
  const toolsccDir = (0, path_1.getToolsccDir)(projectDir);
197
198
  const configFile = (0, path_1.getProjectConfigPath)(projectDir);
198
199
  await createToolLinks(projectDir, toolsccDir, configFile, projects);
199
200
  }
200
201
  catch (error) {
201
- console.log(chalk_1.default.red(`�?Failed to use ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
202
+ console.log(chalk_1.default.red(`✗ Failed to use ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
202
203
  }
203
204
  }
204
205
  /**
@@ -235,10 +236,10 @@ async function createToolLinks(projectDir, toolsccDir, configFile, projects) {
235
236
  const linkPath = path_2.default.join(projectDir, linkName);
236
237
  try {
237
238
  await (0, symlink_1.createSymlink)(toolsccDir, linkPath, true);
238
- console.log(chalk_1.default.green(`�?Linked: ${linkName} -> .toolscc`));
239
+ console.log(chalk_1.default.green(`✓ Linked: ${linkName} -> .toolscc`));
239
240
  }
240
241
  catch (error) {
241
- console.log(chalk_1.default.red(`�?Failed to link ${linkName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
242
+ console.log(chalk_1.default.red(`✗ Failed to link ${linkName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
242
243
  }
243
244
  }
244
245
  // 更新项目配置
@@ -263,10 +264,10 @@ async function handleRemove(sourceName) {
263
264
  const projectDir = process.cwd();
264
265
  try {
265
266
  await (0, project_1.unuseSource)(sourceName, projectDir);
266
- console.log(chalk_1.default.green(`�?Removed source: ${sourceName}`));
267
+ console.log(chalk_1.default.green(`✓ Removed source: ${sourceName}`));
267
268
  }
268
269
  catch (error) {
269
- console.log(chalk_1.default.red(`�?${error instanceof Error ? error.message : 'Unknown error'}`));
270
+ console.log(chalk_1.default.red(`✗ ${error instanceof Error ? error.message : 'Unknown error'}`));
270
271
  }
271
272
  }
272
273
  async function handleStatus() {
@@ -274,12 +275,12 @@ async function handleStatus() {
274
275
  const sources = await (0, project_1.listUsedSources)(projectDir);
275
276
  console.log(chalk_1.default.bold('\nProject Status:'));
276
277
  console.log(chalk_1.default.gray(` Directory: ${projectDir}`));
277
- // 检�?.toolscc
278
+ // 检查 .toolscc
278
279
  const toolsccDir = (0, path_1.getToolsccDir)(projectDir);
279
280
  console.log(` .toolscc: ${await fs_extra_1.default.pathExists(toolsccDir) ? chalk_1.default.green('exists') : chalk_1.default.red('not found')}`);
280
- // 检�?sources
281
+ // 检查 sources
281
282
  console.log(` Sources: ${sources.length > 0 ? sources.map(s => chalk_1.default.cyan(s)).join(', ') : chalk_1.default.gray('none')}`);
282
- // 检�?links
283
+ // 检查 links
283
284
  const configFile = (0, path_1.getProjectConfigPath)(projectDir);
284
285
  if (await fs_extra_1.default.pathExists(configFile)) {
285
286
  const config = await fs_extra_1.default.readJson(configFile);
@@ -298,40 +299,44 @@ async function handleStatus() {
298
299
  async function handleProjectUpdate(sourceNames) {
299
300
  const projectDir = process.cwd();
300
301
  const configFile = (0, path_1.getProjectConfigPath)(projectDir);
301
- // 检查项目是否已初始�?
302
+ // 检查项目是否已初始化
302
303
  if (!(await fs_extra_1.default.pathExists(configFile))) {
303
304
  console.log(chalk_1.default.yellow('Project not initialized. Run `tools-cc use <source>` first.'));
304
305
  return;
305
306
  }
306
- const config = await fs_extra_1.default.readJson(configFile);
307
+ const rawConfig = await fs_extra_1.default.readJson(configFile);
308
+ // 使用 normalizeProjectConfig 处理旧版(数组)和新版(对象)格式
309
+ const config = (0, config_1.normalizeProjectConfig)(rawConfig);
307
310
  const configuredSources = Object.keys(config.sources || {});
308
- let sourcesToUpdate = sourceNames && sourceNames.length > 0
309
- ? sourceNames
311
+ // 过滤掉无效的源名称(如数字字符串),这些可能是 Commander.js 解析错误产生的
312
+ const validSourceNames = sourceNames?.filter(s => isNaN(Number(s))) || [];
313
+ let sourcesToUpdate = validSourceNames.length > 0
314
+ ? validSourceNames
310
315
  : configuredSources;
311
316
  if (sourcesToUpdate.length === 0) {
312
317
  console.log(chalk_1.default.gray('No sources to update.'));
313
318
  return;
314
319
  }
315
- // 验证指定的源是否存在于项目配置中
316
- if (sourceNames && sourceNames.length > 0) {
317
- const invalidSources = sourceNames.filter((s) => !configuredSources.includes(s));
320
+ // 验证指定的源是否存在于项目配置中(仅当用户明确指定了有效源名称时)
321
+ if (validSourceNames.length > 0) {
322
+ const invalidSources = validSourceNames.filter((s) => !configuredSources.includes(s));
318
323
  if (invalidSources.length > 0) {
319
324
  console.log(chalk_1.default.yellow(`Sources not in project: ${invalidSources.join(', ')}`));
320
325
  }
321
326
  sourcesToUpdate = sourcesToUpdate.filter((s) => configuredSources.includes(s));
322
327
  }
323
- // 更新每个配置�?
328
+ // 更新每个配置源
324
329
  for (const sourceName of sourcesToUpdate) {
325
330
  try {
326
331
  const sourcePath = await (0, source_1.getSourcePath)(sourceName, path_1.GLOBAL_CONFIG_DIR);
327
332
  // 使用保存的选择配置进行更新
328
333
  const selection = config.sources[sourceName];
329
334
  await (0, project_1.useSource)(sourceName, sourcePath, projectDir, selection);
330
- console.log(chalk_1.default.green(`�?Updated source: ${sourceName}`));
335
+ console.log(chalk_1.default.green(`✓ Updated source: ${sourceName}`));
331
336
  }
332
337
  catch (error) {
333
- console.log(chalk_1.default.red(`�?Failed to update ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
338
+ console.log(chalk_1.default.red(`✗ Failed to update ${sourceName}: ${error instanceof Error ? error.message : 'Unknown error'}`));
334
339
  }
335
340
  }
336
- console.log(chalk_1.default.green(`\n�?Project update complete`));
341
+ console.log(chalk_1.default.green(`\nProject update complete`));
337
342
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tools-cc",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "tools-cc [options] <command> [args]",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -23,7 +23,8 @@ ${chalk.bold('COMMANDS / 命令')}
23
23
  tools-cc sources add <name> <path-or-url> Add a source / 添加配置源
24
24
  tools-cc sources list, ls List all sources / 列出所有配置源
25
25
  tools-cc sources remove, rm <name> Remove a source / 移除配置源
26
- tools-cc sources update, up [name] Update source(s) / 更新配置源
26
+ tools-cc sources update, up [name] git pull update / 更新源代码
27
+ tools-cc sources scan Scan dir for sources / 扫描发现新源
27
28
 
28
29
  ${chalk.gray('Shortcut: -s')} e.g., tools-cc -s add my-skills https://github.com/user/skills.git
29
30
 
@@ -35,16 +36,27 @@ ${chalk.bold('COMMANDS / 命令')}
35
36
  ${chalk.gray('Shortcut: -c')} e.g., tools-cc -c set sourcesDir D:/skills
36
37
 
37
38
  ${chalk.cyan('Project Commands / 项目命令')}
38
- tools-cc use [sources...] [-p tools...] Use sources in project / 在项目中启用配置源
39
+ tools-cc use [sources...] [options] Use sources in project / 在项目中启用配置源
40
+ tools-cc update [sources...] Sync source content to project / 同步内容到项目
39
41
  tools-cc list List used sources / 列出已启用的配置源
40
42
  tools-cc rm <source> Remove source from project / 禁用配置源
41
43
  tools-cc status Show project status / 显示项目状态
44
+ tools-cc export [options] Export config / 导出配置
42
45
 
43
46
  ${chalk.cyan('Help / 帮助')}
44
47
  tools-cc help Show this help / 显示此帮助信息
45
48
  tools-cc --help, -h Show command help / 显示命令帮助
46
49
  tools-cc --version, -V Show version / 显示版本号
47
50
 
51
+ ${chalk.bold('USE OPTIONS / use 命令选项')}
52
+ -p, --tools <tools...> Target tools (iflow, claude, etc.) / 目标工具
53
+ --ls Interactive selection / 交互式选择内容
54
+ -c, --config <file> Import from config file / 从配置文件导入
55
+
56
+ ${chalk.bold('EXPORT OPTIONS / export 命令选项')}
57
+ -o, --output <file> Output file path / 输出文件路径
58
+ --global Export global config / 导出全局配置
59
+
48
60
  ${chalk.bold('SUPPORTED TOOLS / 支持的工具')}
49
61
  iflow → .iflow
50
62
  claude → .claude
@@ -59,21 +71,36 @@ ${chalk.bold('EXAMPLES / 示例')}
59
71
  ${chalk.gray('# Add a local source / 添加本地配置源')}
60
72
  tools-cc sources add local-skills D:/path/to/local-skills
61
73
 
74
+ ${chalk.gray('# Scan for sources / 扫描发现配置源')}
75
+ tools-cc sources scan
76
+
62
77
  ${chalk.gray('# List all sources / 列出所有配置源')}
63
78
  tools-cc sources list
64
79
 
65
80
  ${chalk.gray('# Use sources in project / 在项目中启用配置源')}
66
81
  tools-cc use my-skills -p iflow claude codex
67
82
 
83
+ ${chalk.gray('# Interactive selection / 交互式选择内容')}
84
+ tools-cc use my-skills --ls
85
+
86
+ ${chalk.gray('# Import from config file / 从配置文件导入')}
87
+ tools-cc use -c project-config.json
88
+
89
+ ${chalk.gray('# Sync source content to project / 同步源内容到项目')}
90
+ tools-cc update my-skills
91
+
68
92
  ${chalk.gray('# Check project status / 检查项目状态')}
69
93
  tools-cc status
70
94
 
95
+ ${chalk.gray('# Export project config / 导出项目配置')}
96
+ tools-cc export -o my-config.json
97
+
71
98
  ${chalk.gray('# Show full configuration / 显示完整配置')}
72
99
  tools-cc config list
73
100
 
74
101
  ${chalk.bold('MORE INFO / 更多信息')}
75
- GitHub: https://github.com/user/tools-cc
76
- Docs: https://github.com/user/tools-cc#readme
102
+ GitHub: https://github.com/q759410559/tools-cc
103
+ Docs: https://github.com/q759410559/tools-cc#readme
77
104
 
78
105
  ${chalk.bold.cyan('═══════════════════════════════════════════════════════════════════════════')}
79
106
  `);
@@ -1,6 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import inquirer from 'inquirer';
3
3
  import { useSource, unuseSource, listUsedSources, initProject, importProjectConfig } from '../core/project';
4
+ import { normalizeProjectConfig } from '../types/config';
4
5
  import { getSourcePath, listSources } from '../core/source';
5
6
  import { scanSource } from '../core/manifest';
6
7
  import { createSymlink, isSymlink } from '../core/symlink';
@@ -368,11 +369,16 @@ export async function handleProjectUpdate(sourceNames?: string[]): Promise<void>
368
369
  return;
369
370
  }
370
371
 
371
- const config = await fs.readJson(configFile);
372
+ const rawConfig = await fs.readJson(configFile);
373
+ // 使用 normalizeProjectConfig 处理旧版(数组)和新版(对象)格式
374
+ const config = normalizeProjectConfig(rawConfig);
372
375
  const configuredSources = Object.keys(config.sources || {});
373
376
 
374
- let sourcesToUpdate = sourceNames && sourceNames.length > 0
375
- ? sourceNames
377
+ // 过滤掉无效的源名称(如数字字符串),这些可能是 Commander.js 解析错误产生的
378
+ const validSourceNames = sourceNames?.filter(s => isNaN(Number(s))) || [];
379
+
380
+ let sourcesToUpdate = validSourceNames.length > 0
381
+ ? validSourceNames
376
382
  : configuredSources;
377
383
 
378
384
  if (sourcesToUpdate.length === 0) {
@@ -380,9 +386,9 @@ export async function handleProjectUpdate(sourceNames?: string[]): Promise<void>
380
386
  return;
381
387
  }
382
388
 
383
- // 验证指定的源是否存在于项目配置中
384
- if (sourceNames && sourceNames.length > 0) {
385
- const invalidSources = sourceNames.filter((s: string) => !configuredSources.includes(s));
389
+ // 验证指定的源是否存在于项目配置中(仅当用户明确指定了有效源名称时)
390
+ if (validSourceNames.length > 0) {
391
+ const invalidSources = validSourceNames.filter((s: string) => !configuredSources.includes(s));
386
392
  if (invalidSources.length > 0) {
387
393
  console.log(chalk.yellow(`Sources not in project: ${invalidSources.join(', ')}`));
388
394
  }