tools-cc 1.0.1 → 1.0.4
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/AGENTS.md +164 -0
- package/CHANGELOG.md +71 -0
- package/CHANGELOG_en.md +71 -0
- package/{readme.md → README.md} +3 -3
- package/README_en.md +218 -0
- package/dist/commands/use.js +3 -3
- package/dist/core/project.js +2 -1
- package/dist/utils/path.d.ts +1 -1
- package/dist/utils/path.js +4 -4
- package/package.json +3 -2
- package/src/commands/use.ts +4 -4
- package/src/core/project.ts +21 -20
- package/src/utils/path.ts +4 -4
package/AGENTS.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# tools-cc 项目上下文
|
|
2
|
+
|
|
3
|
+
## 项目概述
|
|
4
|
+
|
|
5
|
+
tools-cc 是一个 CLI 工具,用于统一管理多个 AI 编程工具(iflow、claude、codebuddy、opencode 等)的 skills/commands/agents 配置。通过符号链接机制,避免在多个工具间重复配置。
|
|
6
|
+
|
|
7
|
+
## 技术栈
|
|
8
|
+
|
|
9
|
+
- **语言**: TypeScript (ES2020, strict mode)
|
|
10
|
+
- **CLI 框架**: Commander.js
|
|
11
|
+
- **文件操作**: fs-extra
|
|
12
|
+
- **终端输出**: chalk
|
|
13
|
+
- **交互式命令**: inquirer
|
|
14
|
+
- **测试框架**: vitest
|
|
15
|
+
- **运行时**: Node.js (CommonJS)
|
|
16
|
+
|
|
17
|
+
## 项目结构
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
tools-cc/
|
|
21
|
+
├── src/
|
|
22
|
+
│ ├── index.ts # CLI 入口,命令注册
|
|
23
|
+
│ ├── commands/ # CLI 命令处理器
|
|
24
|
+
│ │ ├── config.ts # 配置管理命令
|
|
25
|
+
│ │ ├── help.ts # 帮助信息
|
|
26
|
+
│ │ ├── source.ts # 源管理命令
|
|
27
|
+
│ │ └── use.ts # 项目使用命令
|
|
28
|
+
│ ├── core/ # 核心业务逻辑
|
|
29
|
+
│ │ ├── config.ts # 配置读写
|
|
30
|
+
│ │ ├── manifest.ts # manifest.json 解析
|
|
31
|
+
│ │ ├── project.ts # 项目管理
|
|
32
|
+
│ │ ├── source.ts # 源管理
|
|
33
|
+
│ │ └── symlink.ts # 符号链接创建
|
|
34
|
+
│ ├── types/ # TypeScript 类型定义
|
|
35
|
+
│ │ └── config.ts # 核心接口定义
|
|
36
|
+
│ └── utils/
|
|
37
|
+
│ └── path.ts # 路径常量和工具函数
|
|
38
|
+
├── tests/ # 测试文件
|
|
39
|
+
│ ├── core/ # 核心模块测试
|
|
40
|
+
│ └── fixtures/ # 测试固件
|
|
41
|
+
└── dist/ # 编译输出
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 构建和运行
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# 安装依赖
|
|
48
|
+
npm install
|
|
49
|
+
|
|
50
|
+
# 开发模式运行
|
|
51
|
+
npm run dev
|
|
52
|
+
|
|
53
|
+
# 编译 TypeScript
|
|
54
|
+
npm run build
|
|
55
|
+
|
|
56
|
+
# 运行编译后的代码
|
|
57
|
+
npm start
|
|
58
|
+
|
|
59
|
+
# 运行测试
|
|
60
|
+
npm test
|
|
61
|
+
|
|
62
|
+
# 运行测试(单次)
|
|
63
|
+
npm run test:run
|
|
64
|
+
|
|
65
|
+
# 全局安装(开发)
|
|
66
|
+
npm link
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 核心命令
|
|
70
|
+
|
|
71
|
+
### 全局配置源管理
|
|
72
|
+
- `tools-cc -s add <name> <path-or-url>` - 添加配置源
|
|
73
|
+
- `tools-cc -s list` - 列出所有配置源
|
|
74
|
+
- `tools-cc -s remove <name>` - 移除配置源
|
|
75
|
+
- `tools-cc -s update [name]` - git pull 更新源代码
|
|
76
|
+
- `tools-cc -s scan` - 扫描目录发现新源
|
|
77
|
+
|
|
78
|
+
### 项目配置
|
|
79
|
+
- `tools-cc use [sources...] [-p tools...]` - 启用配置源并创建符号链接
|
|
80
|
+
- `tools-cc update [sources...]` - 同步源内容到项目
|
|
81
|
+
- `tools-cc list` - 列出已启用的配置源
|
|
82
|
+
- `tools-cc rm <source>` - 禁用配置源
|
|
83
|
+
- `tools-cc status` - 查看项目状态
|
|
84
|
+
|
|
85
|
+
### 配置管理
|
|
86
|
+
- `tools-cc config set <key> <value>` - 设置配置
|
|
87
|
+
- `tools-cc config get <key>` - 获取配置
|
|
88
|
+
- `tools-cc config list` - 查看完整配置
|
|
89
|
+
|
|
90
|
+
## 支持的 AI 工具
|
|
91
|
+
|
|
92
|
+
| 工具 | 链接名称 |
|
|
93
|
+
|------|----------|
|
|
94
|
+
| iflow | `.iflow` |
|
|
95
|
+
| claude | `.claude` |
|
|
96
|
+
| codebuddy | `.codebuddy` |
|
|
97
|
+
| opencode | `.opencode` |
|
|
98
|
+
|
|
99
|
+
## 配置文件位置
|
|
100
|
+
|
|
101
|
+
- **全局配置**: `~/.tools-cc/config.json`
|
|
102
|
+
- **项目配置**: `项目/.toolscc/config.json`
|
|
103
|
+
- **源存储目录**: `~/.tools-cc/sources`(可配置)
|
|
104
|
+
|
|
105
|
+
## 核心类型
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// 源配置
|
|
109
|
+
interface SourceConfig {
|
|
110
|
+
type: 'git' | 'local';
|
|
111
|
+
url?: string;
|
|
112
|
+
path?: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 全局配置
|
|
116
|
+
interface GlobalConfig {
|
|
117
|
+
sourcesDir: string;
|
|
118
|
+
sources: Record<string, SourceConfig>;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 项目配置
|
|
122
|
+
interface ProjectConfig {
|
|
123
|
+
sources: string[];
|
|
124
|
+
links: string[];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Manifest 文件
|
|
128
|
+
interface Manifest {
|
|
129
|
+
name: string;
|
|
130
|
+
version: string;
|
|
131
|
+
skills?: string[];
|
|
132
|
+
commands?: string[];
|
|
133
|
+
agents?: string[];
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 开发约定
|
|
138
|
+
|
|
139
|
+
### 代码风格
|
|
140
|
+
- 使用 TypeScript strict 模式
|
|
141
|
+
- 异步函数使用 async/await
|
|
142
|
+
- 文件操作使用 fs-extra
|
|
143
|
+
- 命令处理函数命名:`handle*`
|
|
144
|
+
|
|
145
|
+
### 测试
|
|
146
|
+
- 测试文件放在 `tests/` 目录,镜像 `src/` 结构
|
|
147
|
+
- 使用 vitest 框架
|
|
148
|
+
- 测试固件放在 `tests/fixtures/`
|
|
149
|
+
|
|
150
|
+
### 命令添加
|
|
151
|
+
1. 在 `src/commands/` 创建或修改命令处理文件
|
|
152
|
+
2. 在 `src/index.ts` 注册新命令
|
|
153
|
+
3. 添加相应的测试
|
|
154
|
+
|
|
155
|
+
### 文档更新 [CHANGELOG.md](CHANGELOG.md)[README.md](README.md)
|
|
156
|
+
- 更新文档时,请确保命令描述清晰、准确,并使用一致的格式
|
|
157
|
+
- 添加新命令时,请更新命令列表和描述
|
|
158
|
+
- 修改现有命令时,请更新相关命令的描述
|
|
159
|
+
|
|
160
|
+
## 注意事项
|
|
161
|
+
|
|
162
|
+
- 此项目运行在 Windows 系统,注意路径分隔符兼容性
|
|
163
|
+
- 符号链接在 Windows 上可能需要管理员权限
|
|
164
|
+
- 全局配置目录位于用户主目录下的 `.tools-cc`
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# 变更日志
|
|
2
|
+
|
|
3
|
+
本项目的所有重要变更都将记录在此文件中。
|
|
4
|
+
|
|
5
|
+
## [1.0.4] - 2026-02-28
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- 新增英文版项目说明文档 README_en.md
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- 优化项目初始化与源码同步逻辑
|
|
12
|
+
|
|
13
|
+
## [1.0.3] - 2026-02-26
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- 项目配置文件位置从 `tools-cc.json` 改为 `.toolscc/config.json`
|
|
17
|
+
- 优化文档命令描述,明确区分全局和项目命令
|
|
18
|
+
|
|
19
|
+
## [1.0.2] - 2026-02-26
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- 新增 `tools-cc -s scan` 命令:扫描 sourcesDir 目录,自动发现并添加配置源
|
|
23
|
+
- 新增 `tools-cc -s upgrade [name]` 命令别名:执行 git pull 更新配置源代码
|
|
24
|
+
- 新增 `tools-cc update [sources...]` 命令:同步配置源内容到项目 .toolscc 目录
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- 优化帮助文档,添加工作流说明和命令对比表
|
|
28
|
+
|
|
29
|
+
## [1.0.1] - 2026-02-25
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
- 补充 package.json 仓库相关元数据(repository、bugs、homepage)
|
|
33
|
+
|
|
34
|
+
## [1.0.0] - 2026-02-25
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
- 项目初始化,基于 TypeScript + Commander 构建 CLI 框架
|
|
38
|
+
- 全局配置管理模块
|
|
39
|
+
- `tools-cc -c set <key> <value>` 设置配置
|
|
40
|
+
- `tools-cc -c get <key>` 查看配置
|
|
41
|
+
- `tools-cc config list` 查看完整配置
|
|
42
|
+
- 配置源管理模块
|
|
43
|
+
- `tools-cc -s add <name> <path-or-url>` 添加配置源(支持 Git URL 和本地路径)
|
|
44
|
+
- `tools-cc -s list` 列出所有配置源
|
|
45
|
+
- `tools-cc -s remove <name>` 移除配置源
|
|
46
|
+
- `tools-cc -s update [name]` 更新配置源(git pull)
|
|
47
|
+
- 项目管理模块
|
|
48
|
+
- `tools-cc use [sources...]` 启用配置源并创建符号链接
|
|
49
|
+
- `tools-cc list` 列出已启用的配置源
|
|
50
|
+
- `tools-cc rm <source>` 禁用配置源
|
|
51
|
+
- `tools-cc status` 查看项目状态
|
|
52
|
+
- 符号链接管理模块(支持 Windows Junction)
|
|
53
|
+
- Manifest 加载和扫描模块
|
|
54
|
+
- 中英双语帮助信息 (`tools-cc help`)
|
|
55
|
+
- 单元测试覆盖(vitest)
|
|
56
|
+
|
|
57
|
+
### Supported Tools
|
|
58
|
+
| 工具 | 链接名称 |
|
|
59
|
+
|------|----------|
|
|
60
|
+
| iflow | `.iflow` |
|
|
61
|
+
| claude | `.claude` |
|
|
62
|
+
| codebuddy | `.codebuddy` |
|
|
63
|
+
| opencode | `.opencode` |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 版本说明
|
|
68
|
+
|
|
69
|
+
- **主版本号**: 不兼容的 API 变更
|
|
70
|
+
- **次版本号**: 向后兼容的功能新增
|
|
71
|
+
- **修订号**: 向后兼容的问题修复
|
package/CHANGELOG_en.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [1.0.4] - 2026-02-28
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Added English version of project documentation README_en.md
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Optimized project initialization and source synchronization logic
|
|
12
|
+
|
|
13
|
+
## [1.0.3] - 2026-02-26
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Changed project configuration file location from `tools-cc.json` to `.toolscc/config.json`
|
|
17
|
+
- Improved documentation command descriptions, clearly distinguishing global and project commands
|
|
18
|
+
|
|
19
|
+
## [1.0.2] - 2026-02-26
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- Added `tools-cc -s scan` command: scan sourcesDir directory to auto-discover and add configuration sources
|
|
23
|
+
- Added `tools-cc -s upgrade [name]` command alias: execute git pull to update configuration source code
|
|
24
|
+
- Added `tools-cc update [sources...]` command: sync configuration source content to project .toolscc directory
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Improved help documentation, added workflow guide and command comparison table
|
|
28
|
+
|
|
29
|
+
## [1.0.1] - 2026-02-25
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
- Added package.json repository metadata (repository, bugs, homepage)
|
|
33
|
+
|
|
34
|
+
## [1.0.0] - 2026-02-25
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
- Project initialization, built CLI framework based on TypeScript + Commander
|
|
38
|
+
- Global configuration management module
|
|
39
|
+
- `tools-cc -c set <key> <value>` set configuration
|
|
40
|
+
- `tools-cc -c get <key>` get configuration
|
|
41
|
+
- `tools-cc config list` view complete configuration
|
|
42
|
+
- Configuration source management module
|
|
43
|
+
- `tools-cc -s add <name> <path-or-url>` add configuration source (supports Git URL and local path)
|
|
44
|
+
- `tools-cc -s list` list all configuration sources
|
|
45
|
+
- `tools-cc -s remove <name>` remove configuration source
|
|
46
|
+
- `tools-cc -s update [name]` update configuration source (git pull)
|
|
47
|
+
- Project management module
|
|
48
|
+
- `tools-cc use [sources...]` enable configuration sources and create symbolic links
|
|
49
|
+
- `tools-cc list` list enabled configuration sources
|
|
50
|
+
- `tools-cc rm <source>` disable configuration source
|
|
51
|
+
- `tools-cc status` view project status
|
|
52
|
+
- Symbolic link management module (supports Windows Junction)
|
|
53
|
+
- Manifest loading and scanning module
|
|
54
|
+
- Bilingual help information (Chinese/English) (`tools-cc help`)
|
|
55
|
+
- Unit test coverage (vitest)
|
|
56
|
+
|
|
57
|
+
### Supported Tools
|
|
58
|
+
| Tool | Link Name |
|
|
59
|
+
|------|-----------|
|
|
60
|
+
| iflow | `.iflow` |
|
|
61
|
+
| claude | `.claude` |
|
|
62
|
+
| codebuddy | `.codebuddy` |
|
|
63
|
+
| opencode | `.opencode` |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Versioning
|
|
68
|
+
|
|
69
|
+
- **Major version**: Incompatible API changes
|
|
70
|
+
- **Minor version**: Backwards-compatible functionality additions
|
|
71
|
+
- **Patch version**: Backwards-compatible bug fixes
|
package/{readme.md → README.md}
RENAMED
|
@@ -173,6 +173,7 @@ my-skills/
|
|
|
173
173
|
```
|
|
174
174
|
my-project/
|
|
175
175
|
├── .toolscc/ # 实际内容目录
|
|
176
|
+
│ ├── config.json # 项目配置
|
|
176
177
|
│ ├── skills/ # 扁平化,带来源前缀
|
|
177
178
|
│ │ └── my-skills-my-skill/
|
|
178
179
|
│ ├── commands/
|
|
@@ -180,8 +181,7 @@ my-project/
|
|
|
180
181
|
│ └── agents/
|
|
181
182
|
│ └── my-skills/
|
|
182
183
|
├── .iflow -> .toolscc # 符号链接
|
|
183
|
-
|
|
184
|
-
└── tools-cc.json # 项目配置
|
|
184
|
+
└── .claude -> .toolscc
|
|
185
185
|
```
|
|
186
186
|
|
|
187
187
|
## 配置文件
|
|
@@ -204,7 +204,7 @@ my-project/
|
|
|
204
204
|
}
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
-
### 项目配置
|
|
207
|
+
### 项目配置 `项目/.toolscc/config.json`
|
|
208
208
|
|
|
209
209
|
```json
|
|
210
210
|
{
|
package/README_en.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# tools-cc
|
|
2
|
+
|
|
3
|
+
A CLI tool for unified management of skills/commands/agents configurations across multiple AI programming tools (iflow, claude, codebuddy, opencode, etc.). Uses symbolic links to avoid duplicate configurations across tools.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install from npm
|
|
9
|
+
npm install -g tools-cc
|
|
10
|
+
|
|
11
|
+
# Or build from source
|
|
12
|
+
git clone https://github.com/q759410559/tools-cc.git
|
|
13
|
+
cd tools-cc
|
|
14
|
+
npm install
|
|
15
|
+
npm run build
|
|
16
|
+
npm link
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# 1. Set configuration source storage location (optional, default is ~/.tools-cc/sources)
|
|
23
|
+
tools-cc -c set sourcesDir D:/skills-hub-sources
|
|
24
|
+
|
|
25
|
+
# 2. Add configuration sources (supports Git URL or local path)
|
|
26
|
+
tools-cc -s add my-skills https://github.com/user/my-skills.git
|
|
27
|
+
tools-cc -s add local-skills D:/path/to/local-skills
|
|
28
|
+
|
|
29
|
+
# Or scan source directory to auto-discover and add configurations
|
|
30
|
+
tools-cc -s scan
|
|
31
|
+
|
|
32
|
+
# 3. View added configuration sources
|
|
33
|
+
tools-cc -s list
|
|
34
|
+
|
|
35
|
+
# 4. Enable configuration sources in a project and create links
|
|
36
|
+
cd my-project
|
|
37
|
+
tools-cc use my-skills -p iflow claude
|
|
38
|
+
|
|
39
|
+
# 5. View project status
|
|
40
|
+
tools-cc status
|
|
41
|
+
|
|
42
|
+
# 6. View enabled configuration sources
|
|
43
|
+
tools-cc list
|
|
44
|
+
|
|
45
|
+
# 7. Update configuration sources (sync latest content from source directory to project)
|
|
46
|
+
tools-cc update my-skills
|
|
47
|
+
tools-cc update # Update all
|
|
48
|
+
|
|
49
|
+
# 8. Remove configuration source
|
|
50
|
+
tools-cc rm my-skills
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Workflow Guide
|
|
54
|
+
|
|
55
|
+
### Global Source Management vs Project Configuration
|
|
56
|
+
|
|
57
|
+
| Command | Scope | Description |
|
|
58
|
+
|---------|-------|-------------|
|
|
59
|
+
| `tools-cc -s add/remove/list` | Global | Manage global configuration sources |
|
|
60
|
+
| `tools-cc -s update/upgrade` | Global | git pull to update source code |
|
|
61
|
+
| `tools-cc -s scan` | Global | Scan directory to discover new sources |
|
|
62
|
+
| `tools-cc use/rm` | Project | Enable/disable sources in project |
|
|
63
|
+
| `tools-cc update` | Project | Sync source content to project |
|
|
64
|
+
|
|
65
|
+
### Typical Workflow
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Scenario 1: Configuration source has updates, need to sync to project
|
|
69
|
+
tools-cc -s upgrade my-skills # 1. git pull to update source code
|
|
70
|
+
cd my-project
|
|
71
|
+
tools-cc update my-skills # 2. Sync to project .toolscc directory
|
|
72
|
+
|
|
73
|
+
# Scenario 2: Batch update all sources
|
|
74
|
+
tools-cc -s upgrade # 1. Update all git sources
|
|
75
|
+
cd my-project
|
|
76
|
+
tools-cc update # 2. Sync all sources to project
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Command Reference
|
|
80
|
+
|
|
81
|
+
### Source Management
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Shortcuts (-s)
|
|
85
|
+
tools-cc -s add <name> <path-or-url> # Add configuration source (Git URL or local path)
|
|
86
|
+
tools-cc -s list # List all configuration sources (alias: -s ls)
|
|
87
|
+
tools-cc -s remove <name> # Remove configuration source (alias: -s rm)
|
|
88
|
+
tools-cc -s update [name] # git pull to update source code (alias: -s up, -s upgrade)
|
|
89
|
+
tools-cc -s scan # Scan sourcesDir to auto-discover and add configuration sources
|
|
90
|
+
|
|
91
|
+
# Full commands (sources)
|
|
92
|
+
tools-cc sources add <name> <path-or-url> # Add configuration source
|
|
93
|
+
tools-cc sources list # List all configuration sources (alias: sources ls)
|
|
94
|
+
tools-cc sources remove <name> # Remove configuration source (alias: sources rm)
|
|
95
|
+
tools-cc sources update [name] # git pull to update source code (alias: sources up, sources upgrade)
|
|
96
|
+
tools-cc sources scan # Scan sourcesDir to auto-discover and add configuration sources
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Project Configuration
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
tools-cc use [sources...] [-p tools...] # Enable configuration sources and create symbolic links
|
|
103
|
+
tools-cc update [sources...] # Sync configuration source content to project .toolscc directory
|
|
104
|
+
tools-cc list # List enabled configuration sources
|
|
105
|
+
tools-cc rm <source> # Disable configuration source
|
|
106
|
+
tools-cc status # View project status
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Config Management
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Shortcuts (-c)
|
|
113
|
+
tools-cc -c set <key> <value> # Set configuration
|
|
114
|
+
tools-cc -c get <key> # Get configuration
|
|
115
|
+
|
|
116
|
+
# Full commands (config)
|
|
117
|
+
tools-cc config set <key> <value> # Set configuration
|
|
118
|
+
tools-cc config get <key> # Get configuration
|
|
119
|
+
tools-cc config list # View complete global configuration
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Help
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
tools-cc help # Display bilingual help (Chinese/English)
|
|
126
|
+
tools-cc --help # Display command line help
|
|
127
|
+
tools-cc --version # Display version number
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Supported Tools
|
|
131
|
+
|
|
132
|
+
| Tool | Link Name |
|
|
133
|
+
|------|-----------|
|
|
134
|
+
| iflow | `.iflow` |
|
|
135
|
+
| claude | `.claude` |
|
|
136
|
+
| codebuddy | `.codebuddy` |
|
|
137
|
+
| opencode | `.opencode` |
|
|
138
|
+
|
|
139
|
+
## Configuration Source Structure
|
|
140
|
+
|
|
141
|
+
A configuration source directory should contain the following structure:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
my-skills/
|
|
145
|
+
├── manifest.json # Optional, describes component information
|
|
146
|
+
├── skills/
|
|
147
|
+
│ └── my-skill/
|
|
148
|
+
│ └── SKILL.md
|
|
149
|
+
├── commands/
|
|
150
|
+
│ └── my-command.md
|
|
151
|
+
└── agents/
|
|
152
|
+
└── my-agent.md
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### manifest.json Format
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"name": "my-skills",
|
|
160
|
+
"version": "1.0.0",
|
|
161
|
+
"skills": ["my-skill"],
|
|
162
|
+
"commands": ["my-command"],
|
|
163
|
+
"agents": ["my-agent"]
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
If `manifest.json` is not present, the CLI will automatically scan the directory structure to generate one.
|
|
168
|
+
|
|
169
|
+
## Project Structure
|
|
170
|
+
|
|
171
|
+
After using `tools-cc use`, the project directory structure:
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
my-project/
|
|
175
|
+
├── .toolscc/ # Actual content directory
|
|
176
|
+
│ ├── config.json # Project configuration
|
|
177
|
+
│ ├── skills/ # Flattened, with source prefix
|
|
178
|
+
│ │ └── my-skills-my-skill/
|
|
179
|
+
│ ├── commands/
|
|
180
|
+
│ │ └── my-skills/
|
|
181
|
+
│ └── agents/
|
|
182
|
+
│ └── my-skills/
|
|
183
|
+
├── .iflow -> .toolscc # Symbolic link
|
|
184
|
+
└── .claude -> .toolscc
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Configuration Files
|
|
188
|
+
|
|
189
|
+
### Global Configuration `~/.tools-cc/config.json`
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"sourcesDir": "D:/skills-hub-sources",
|
|
194
|
+
"sources": {
|
|
195
|
+
"my-skills": {
|
|
196
|
+
"type": "git",
|
|
197
|
+
"url": "https://github.com/user/my-skills.git"
|
|
198
|
+
},
|
|
199
|
+
"local-skills": {
|
|
200
|
+
"type": "local",
|
|
201
|
+
"path": "D:/local-skills"
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Project Configuration `project/.toolscc/config.json`
|
|
208
|
+
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"sources": ["my-skills"],
|
|
212
|
+
"links": ["iflow", "claude"]
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
MIT
|
package/dist/commands/use.js
CHANGED
|
@@ -78,7 +78,7 @@ async function handleUse(sourceNames, options) {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
// 更新项目配置
|
|
81
|
-
const configFile =
|
|
81
|
+
const configFile = (0, path_1.getProjectConfigPath)(projectDir);
|
|
82
82
|
const config = await fs_extra_1.default.readJson(configFile);
|
|
83
83
|
const existingLinks = config.links || [];
|
|
84
84
|
config.links = [...new Set([...existingLinks, ...tools])];
|
|
@@ -117,7 +117,7 @@ async function handleStatus() {
|
|
|
117
117
|
// 检查 sources
|
|
118
118
|
console.log(` Sources: ${sources.length > 0 ? sources.map(s => chalk_1.default.cyan(s)).join(', ') : chalk_1.default.gray('none')}`);
|
|
119
119
|
// 检查 links
|
|
120
|
-
const configFile =
|
|
120
|
+
const configFile = (0, path_1.getProjectConfigPath)(projectDir);
|
|
121
121
|
if (await fs_extra_1.default.pathExists(configFile)) {
|
|
122
122
|
const config = await fs_extra_1.default.readJson(configFile);
|
|
123
123
|
console.log(` Links:`);
|
|
@@ -134,7 +134,7 @@ async function handleStatus() {
|
|
|
134
134
|
}
|
|
135
135
|
async function handleProjectUpdate(sourceNames) {
|
|
136
136
|
const projectDir = process.cwd();
|
|
137
|
-
const configFile =
|
|
137
|
+
const configFile = (0, path_1.getProjectConfigPath)(projectDir);
|
|
138
138
|
// 检查项目是否已初始化
|
|
139
139
|
if (!(await fs_extra_1.default.pathExists(configFile))) {
|
|
140
140
|
console.log(chalk_1.default.yellow('Project not initialized. Run `tools-cc use <source>` first.'));
|
package/dist/core/project.js
CHANGED
|
@@ -46,7 +46,8 @@ async function useSource(sourceName, sourceDir, projectDir) {
|
|
|
46
46
|
const skills = await fs_extra_1.default.readdir(sourceSkillsDir);
|
|
47
47
|
for (const skill of skills) {
|
|
48
48
|
const srcPath = path_1.default.join(sourceSkillsDir, skill);
|
|
49
|
-
const
|
|
49
|
+
const name = `${sourceName}` == `${skill}` ? skill : `${sourceName}-${skill}`;
|
|
50
|
+
const destPath = path_1.default.join(toolsccDir, 'skills', name);
|
|
50
51
|
// Remove existing if exists
|
|
51
52
|
await fs_extra_1.default.remove(destPath);
|
|
52
53
|
// Copy directory
|
package/dist/utils/path.d.ts
CHANGED
|
@@ -4,5 +4,5 @@ export declare const DEFAULT_CONFIG: {
|
|
|
4
4
|
sourcesDir: string;
|
|
5
5
|
sources: {};
|
|
6
6
|
};
|
|
7
|
-
export declare function getProjectConfigPath(projectDir: string): string;
|
|
8
7
|
export declare function getToolsccDir(projectDir: string): string;
|
|
8
|
+
export declare function getProjectConfigPath(projectDir: string): string;
|
package/dist/utils/path.js
CHANGED
|
@@ -4,8 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.DEFAULT_CONFIG = exports.GLOBAL_CONFIG_FILE = exports.GLOBAL_CONFIG_DIR = void 0;
|
|
7
|
-
exports.getProjectConfigPath = getProjectConfigPath;
|
|
8
7
|
exports.getToolsccDir = getToolsccDir;
|
|
8
|
+
exports.getProjectConfigPath = getProjectConfigPath;
|
|
9
9
|
const os_1 = __importDefault(require("os"));
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
exports.GLOBAL_CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.tools-cc');
|
|
@@ -14,9 +14,9 @@ exports.DEFAULT_CONFIG = {
|
|
|
14
14
|
sourcesDir: path_1.default.join(exports.GLOBAL_CONFIG_DIR, 'sources'),
|
|
15
15
|
sources: {}
|
|
16
16
|
};
|
|
17
|
-
function getProjectConfigPath(projectDir) {
|
|
18
|
-
return path_1.default.join(projectDir, 'tools-cc.json');
|
|
19
|
-
}
|
|
20
17
|
function getToolsccDir(projectDir) {
|
|
21
18
|
return path_1.default.join(projectDir, '.toolscc');
|
|
22
19
|
}
|
|
20
|
+
function getProjectConfigPath(projectDir) {
|
|
21
|
+
return path_1.default.join(getToolsccDir(projectDir), 'config.json');
|
|
22
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tools-cc",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "tools-cc [options] <command> [args]",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"dev": "ts-node src/index.ts",
|
|
12
12
|
"start": "node dist/index.js",
|
|
13
13
|
"test": "vitest",
|
|
14
|
-
"test:run": "vitest run"
|
|
14
|
+
"test:run": "vitest run",
|
|
15
|
+
"release": "npm publish && git tag v%npm_package_version% && git push origin v%npm_package_version% && gh release create v%npm_package_version% --title v%npm_package_version% --generate-notes"
|
|
15
16
|
},
|
|
16
17
|
"bin": {
|
|
17
18
|
"tools-cc": "./dist/index.js"
|
package/src/commands/use.ts
CHANGED
|
@@ -3,7 +3,7 @@ import inquirer from 'inquirer';
|
|
|
3
3
|
import { useSource, unuseSource, listUsedSources, initProject } from '../core/project';
|
|
4
4
|
import { getSourcePath, listSources } from '../core/source';
|
|
5
5
|
import { createSymlink, isSymlink } from '../core/symlink';
|
|
6
|
-
import { GLOBAL_CONFIG_DIR, getToolsccDir } from '../utils/path';
|
|
6
|
+
import { GLOBAL_CONFIG_DIR, getToolsccDir, getProjectConfigPath } from '../utils/path';
|
|
7
7
|
import fs from 'fs-extra';
|
|
8
8
|
import path from 'path';
|
|
9
9
|
|
|
@@ -83,7 +83,7 @@ export async function handleUse(
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// 更新项目配置
|
|
86
|
-
const configFile =
|
|
86
|
+
const configFile = getProjectConfigPath(projectDir);
|
|
87
87
|
const config = await fs.readJson(configFile);
|
|
88
88
|
const existingLinks = config.links || [];
|
|
89
89
|
config.links = [...new Set([...existingLinks, ...tools])];
|
|
@@ -131,7 +131,7 @@ export async function handleStatus(): Promise<void> {
|
|
|
131
131
|
console.log(` Sources: ${sources.length > 0 ? sources.map(s => chalk.cyan(s)).join(', ') : chalk.gray('none')}`);
|
|
132
132
|
|
|
133
133
|
// 检查 links
|
|
134
|
-
const configFile =
|
|
134
|
+
const configFile = getProjectConfigPath(projectDir);
|
|
135
135
|
if (await fs.pathExists(configFile)) {
|
|
136
136
|
const config = await fs.readJson(configFile);
|
|
137
137
|
console.log(` Links:`);
|
|
@@ -148,7 +148,7 @@ export async function handleStatus(): Promise<void> {
|
|
|
148
148
|
|
|
149
149
|
export async function handleProjectUpdate(sourceNames?: string[]): Promise<void> {
|
|
150
150
|
const projectDir = process.cwd();
|
|
151
|
-
const configFile =
|
|
151
|
+
const configFile = getProjectConfigPath(projectDir);
|
|
152
152
|
|
|
153
153
|
// 检查项目是否已初始化
|
|
154
154
|
if (!(await fs.pathExists(configFile))) {
|
package/src/core/project.ts
CHANGED
|
@@ -7,12 +7,12 @@ import { getToolsccDir, getProjectConfigPath } from '../utils/path';
|
|
|
7
7
|
export async function initProject(projectDir: string): Promise<void> {
|
|
8
8
|
const toolsccDir = getToolsccDir(projectDir);
|
|
9
9
|
const configFile = getProjectConfigPath(projectDir);
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
// Create .toolscc directory structure
|
|
12
12
|
await fs.ensureDir(path.join(toolsccDir, 'skills'));
|
|
13
13
|
await fs.ensureDir(path.join(toolsccDir, 'commands'));
|
|
14
14
|
await fs.ensureDir(path.join(toolsccDir, 'agents'));
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
// Create project config if not exists
|
|
17
17
|
if (!(await fs.pathExists(configFile))) {
|
|
18
18
|
const config: ProjectConfig = {
|
|
@@ -32,34 +32,35 @@ export async function useSource(
|
|
|
32
32
|
if (!sourceName || !sourceName.trim()) {
|
|
33
33
|
throw new Error('Source name is required');
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
// Check source directory existence
|
|
37
37
|
if (!(await fs.pathExists(sourceDir))) {
|
|
38
38
|
throw new Error(`Source directory does not exist: ${sourceDir}`);
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
const toolsccDir = getToolsccDir(projectDir);
|
|
42
42
|
const manifest = await loadManifest(sourceDir);
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
// Ensure project is initialized
|
|
45
45
|
await initProject(projectDir);
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
// Copy/link skills (flattened with prefix)
|
|
48
48
|
const sourceSkillsDir = path.join(sourceDir, 'skills');
|
|
49
49
|
if (await fs.pathExists(sourceSkillsDir)) {
|
|
50
50
|
const skills = await fs.readdir(sourceSkillsDir);
|
|
51
51
|
for (const skill of skills) {
|
|
52
52
|
const srcPath = path.join(sourceSkillsDir, skill);
|
|
53
|
-
const
|
|
54
|
-
|
|
53
|
+
const name = `${sourceName}` == `${skill}` ? skill : `${sourceName}-${skill}`;
|
|
54
|
+
const destPath = path.join(toolsccDir, 'skills', name);
|
|
55
|
+
|
|
55
56
|
// Remove existing if exists
|
|
56
57
|
await fs.remove(destPath);
|
|
57
|
-
|
|
58
|
+
|
|
58
59
|
// Copy directory
|
|
59
60
|
await fs.copy(srcPath, destPath);
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
|
-
|
|
63
|
+
|
|
63
64
|
// Copy commands (in subdirectory by source name)
|
|
64
65
|
const sourceCommandsDir = path.join(sourceDir, 'commands');
|
|
65
66
|
if (await fs.pathExists(sourceCommandsDir)) {
|
|
@@ -67,7 +68,7 @@ export async function useSource(
|
|
|
67
68
|
await fs.remove(destDir);
|
|
68
69
|
await fs.copy(sourceCommandsDir, destDir);
|
|
69
70
|
}
|
|
70
|
-
|
|
71
|
+
|
|
71
72
|
// Copy agents (in subdirectory by source name)
|
|
72
73
|
const sourceAgentsDir = path.join(sourceDir, 'agents');
|
|
73
74
|
if (await fs.pathExists(sourceAgentsDir)) {
|
|
@@ -75,7 +76,7 @@ export async function useSource(
|
|
|
75
76
|
await fs.remove(destDir);
|
|
76
77
|
await fs.copy(sourceAgentsDir, destDir);
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
+
|
|
79
80
|
// Update project config
|
|
80
81
|
const configFile = getProjectConfigPath(projectDir);
|
|
81
82
|
const config: ProjectConfig = await fs.readJson(configFile);
|
|
@@ -90,10 +91,10 @@ export async function unuseSource(sourceName: string, projectDir: string): Promi
|
|
|
90
91
|
if (!sourceName || !sourceName.trim()) {
|
|
91
92
|
throw new Error('Source name is required');
|
|
92
93
|
}
|
|
93
|
-
|
|
94
|
+
|
|
94
95
|
const toolsccDir = getToolsccDir(projectDir);
|
|
95
96
|
const configFile = getProjectConfigPath(projectDir);
|
|
96
|
-
|
|
97
|
+
|
|
97
98
|
// Remove skills with prefix
|
|
98
99
|
const skillsDir = path.join(toolsccDir, 'skills');
|
|
99
100
|
if (await fs.pathExists(skillsDir)) {
|
|
@@ -104,13 +105,13 @@ export async function unuseSource(sourceName: string, projectDir: string): Promi
|
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
|
-
|
|
108
|
+
|
|
108
109
|
// Remove commands subdirectory
|
|
109
110
|
await fs.remove(path.join(toolsccDir, 'commands', sourceName));
|
|
110
|
-
|
|
111
|
+
|
|
111
112
|
// Remove agents subdirectory
|
|
112
113
|
await fs.remove(path.join(toolsccDir, 'agents', sourceName));
|
|
113
|
-
|
|
114
|
+
|
|
114
115
|
// Update project config with error handling
|
|
115
116
|
let config: ProjectConfig;
|
|
116
117
|
try {
|
|
@@ -119,18 +120,18 @@ export async function unuseSource(sourceName: string, projectDir: string): Promi
|
|
|
119
120
|
// If config file doesn't exist or is invalid, nothing to update
|
|
120
121
|
return;
|
|
121
122
|
}
|
|
122
|
-
|
|
123
|
+
|
|
123
124
|
config.sources = config.sources.filter(s => s !== sourceName);
|
|
124
125
|
await fs.writeJson(configFile, config, { spaces: 2 });
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
export async function listUsedSources(projectDir: string): Promise<string[]> {
|
|
128
129
|
const configFile = getProjectConfigPath(projectDir);
|
|
129
|
-
|
|
130
|
+
|
|
130
131
|
if (!(await fs.pathExists(configFile))) {
|
|
131
132
|
return [];
|
|
132
133
|
}
|
|
133
|
-
|
|
134
|
+
|
|
134
135
|
const config: ProjectConfig = await fs.readJson(configFile);
|
|
135
136
|
return config.sources;
|
|
136
137
|
}
|
package/src/utils/path.ts
CHANGED
|
@@ -9,10 +9,10 @@ export const DEFAULT_CONFIG = {
|
|
|
9
9
|
sources: {}
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
export function getProjectConfigPath(projectDir: string): string {
|
|
13
|
-
return path.join(projectDir, 'tools-cc.json');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
12
|
export function getToolsccDir(projectDir: string): string {
|
|
17
13
|
return path.join(projectDir, '.toolscc');
|
|
18
14
|
}
|
|
15
|
+
|
|
16
|
+
export function getProjectConfigPath(projectDir: string): string {
|
|
17
|
+
return path.join(getToolsccDir(projectDir), 'config.json');
|
|
18
|
+
}
|