bcoder 0.0.1

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.
@@ -0,0 +1,217 @@
1
+ ---
2
+ name: bc-use-git-worktrees
3
+ description: 当开始需要与当前工作空间隔离的功能工作或在执行实施计划之前使用 - 创建具有智能目录选择和安全验证的隔离 git worktrees
4
+ ---
5
+
6
+ # 使用 Git Worktrees
7
+
8
+ ## 概述
9
+
10
+ Git worktrees 创建共享同一存储库的隔离工作空间,允许同时在多个分支上工作而无需切换。
11
+
12
+ **核心原则:** 系统性目录选择 + 安全验证 = 可靠隔离。
13
+
14
+ **开始时声明:** "我正在使用 使用 Git Worktrees (bc-use-git-worktrees ) 技能来设置隔离的工作空间。"
15
+
16
+ ## 目录选择流程
17
+
18
+ 遵循此优先顺序:
19
+
20
+ ### 1. 检查现有目录
21
+
22
+ ```bash
23
+ # 按优先顺序检查
24
+ ls -d .worktrees 2>/dev/null # 首选(隐藏)
25
+ ls -d worktrees 2>/dev/null # 替代
26
+ ```
27
+
28
+ **如果找到:** 使用该目录。如果两者都存在,`.worktrees` 获胜。
29
+
30
+ ### 2. 检查 CLAUDE.md
31
+
32
+ ```bash
33
+ grep -i "worktree.*director" CLAUDE.md 2>/dev/null
34
+ ```
35
+
36
+ **如果指定了首选项:** 使用它而不询问。
37
+
38
+ ### 3. 询问用户
39
+
40
+ 如果不存在目录且没有 CLAUDE.md 首选项:
41
+
42
+ ```
43
+ 未找到 worktree 目录。我应该在哪里创建 worktrees?
44
+
45
+ 1. .worktrees/(项目本地,隐藏)
46
+ 2. ~/.config/bcoder/worktrees/<project-name>/(全局位置)
47
+
48
+ 你更喜欢哪个?
49
+ ```
50
+
51
+ ## 安全验证
52
+
53
+ ### 对于项目本地目录(.worktrees 或 worktrees)
54
+
55
+ **必须在创建 worktree 之前验证目录被忽略:**
56
+
57
+ ```bash
58
+ # 检查目录是否被忽略(尊重本地、全局和系统 gitignore)
59
+ git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null
60
+ ```
61
+
62
+ **如果未被忽略:**
63
+
64
+ 根据 Jesse 的规则"立即修复损坏的东西":
65
+ 1. 将适当的行添加到 .gitignore
66
+ 2. 提交更改
67
+ 3. 继续 worktree 创建
68
+
69
+ **为什么关键:** 防止意外将 worktree 内容提交到存储库。
70
+
71
+ ### 对于全局目录(~/.config/bcoder/worktrees)
72
+
73
+ 无需 .gitignore 验证 - 完全在项目之外。
74
+
75
+ ## 创建步骤
76
+
77
+ ### 1. 检测项目名称
78
+
79
+ ```bash
80
+ project=$(basename "$(git rev-parse --show-toplevel)")
81
+ ```
82
+
83
+ ### 2. 创建 Worktree
84
+
85
+ ```bash
86
+ # 确定完整路径
87
+ case $LOCATION in
88
+ .worktrees|worktrees)
89
+ path="$LOCATION/$BRANCH_NAME"
90
+ ;;
91
+ ~/.config/bcoder/worktrees/*)
92
+ path="~/.config/bcoder/worktrees/$project/$BRANCH_NAME"
93
+ ;;
94
+ esac
95
+
96
+ # 使用新分支创建 worktree
97
+ git worktree add "$path" -b "$BRANCH_NAME"
98
+ cd "$path"
99
+ ```
100
+
101
+ ### 3. 运行项目设置
102
+
103
+ 自动检测并运行适当的设置:
104
+
105
+ ```bash
106
+ # Node.js
107
+ if [ -f package.json ]; then npm install; fi
108
+
109
+ # Rust
110
+ if [ -f Cargo.toml ]; then cargo build; fi
111
+
112
+ # Python
113
+ if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
114
+ if [ -f pyproject.toml ]; then poetry install; fi
115
+
116
+ # Go
117
+ if [ -f go.mod ]; then go mod download; fi
118
+ ```
119
+
120
+ ### 4. 验证干净基线
121
+
122
+ 运行测试以确保 worktree 以干净状态开始:
123
+
124
+ ```bash
125
+ # 示例 - 使用项目适当的命令
126
+ npm test
127
+ cargo test
128
+ pytest
129
+ go test ./...
130
+ ```
131
+
132
+ **如果测试失败:** 报告失败,询问是否继续或调查。
133
+
134
+ **如果测试通过:** 报告就绪。
135
+
136
+ ### 5. 报告位置
137
+
138
+ ```
139
+ Worktree 准备就绪在 <full-path>
140
+ 测试通过(<N> 个测试,0 个失败)
141
+ 准备实现 <feature-name>
142
+ ```
143
+
144
+ ## 快速参考
145
+
146
+ | 情况 | 操作 |
147
+ |-----------|--------|
148
+ | `.worktrees/` 存在 | 使用它(验证被忽略) |
149
+ | `worktrees/` 存在 | 使用它(验证被忽略) |
150
+ | 两者都存在 | 使用 `.worktrees/` |
151
+ | 都不存在 | 检查 CLAUDE.md → 询问用户 |
152
+ | 目录未被忽略 | 添加到 .gitignore + 提交 |
153
+ | 基线期间测试失败 | 报告失败 + 询问 |
154
+ | 无 package.json/Cargo.toml | 跳过依赖安装 |
155
+
156
+ ## 常见错误
157
+
158
+ ### 跳过忽略验证
159
+
160
+ - **问题:** Worktree 内容被跟踪,污染 git 状态
161
+ - **修复:** 在创建项目本地 worktree 之前始终使用 `git check-ignore`
162
+
163
+ ### 假设目录位置
164
+
165
+ - **问题:** 创建不一致,违反项目约定
166
+ - **修复:** 遵循优先级:现有 > CLAUDE.md > 询问
167
+
168
+ ### 在测试失败时继续
169
+
170
+ - **问题:** 无法区分新错误与预先存在的问题
171
+ - **修复:** 报告失败,获取明确许可以继续
172
+
173
+ ### 硬编码设置命令
174
+
175
+ - **问题:** 在使用不同工具的项目上中断
176
+ - **修复:** 从项目文件自动检测(package.json 等)
177
+
178
+ ## 示例工作流
179
+
180
+ ```
181
+ 你:我正在使用 bc-using-git-worktrees 技能来设置隔离的工作空间。
182
+
183
+ [检查 .worktrees/ - 存在]
184
+ [验证被忽略 - git check-ignore 确认 .worktrees/ 被忽略]
185
+ [创建 worktree: git worktree add .worktrees/auth -b feature/auth]
186
+ [运行 npm install]
187
+ [运行 npm test - 47 个通过]
188
+
189
+ Worktree 准备就绪在 /Users/jesse/myproject/.worktrees/auth
190
+ 测试通过(47 个测试,0 个失败)
191
+ 准备实现 auth 功能
192
+ ```
193
+
194
+ ## 红旗
195
+
196
+ **永远不要:**
197
+ - 创建 worktree 而不验证它被忽略(项目本地)
198
+ - 跳过基线测试验证
199
+ - 在未询问的情况下继续失败的测试
200
+ - 在模棱两可时假没目录位置
201
+ - 跳过 CLAUDE.md 检查
202
+
203
+ **始终:**
204
+ - 遵循目录优先级:现有 > CLAUDE.md > 询问
205
+ - 验证项目本地目录被忽略
206
+ - 自动检测并运行项目设置
207
+ - 验证干净的测试基线
208
+
209
+ ## 集成
210
+
211
+ **被以下技能调用:**
212
+ - **bc-requirements-analysis**(第 4 阶段)- 当设计被批准且实施遵循时必需
213
+ - **bc-execute-plans** - 在执行任何任务之前必需
214
+ - 任何需要隔离工作空间的技能
215
+
216
+ **与以下技能配合:**
217
+ - **bc-finish-a-dev** - 工作完成后清理必需
package/bin/index.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('../dist/cli/index.js');
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const commander_1 = require("commander"); // 类似于 import java.util...
40
+ const fs_1 = require("fs"); // 引入所有文件操作方法
41
+ const path = __importStar(require("path")); // 处理路径分隔符,类似 Paths.get()
42
+ const ora_1 = __importDefault(require("ora"));
43
+ const chalk_1 = __importDefault(require("chalk"));
44
+ const clear_1 = __importDefault(require("clear"));
45
+ const welcome_1 = require("./welcome");
46
+ const tools_1 = require("./tools");
47
+ const program = new commander_1.Command();
48
+ const { version } = require('../../package.json');
49
+ program
50
+ .name("bcoder")
51
+ .description("一个极轻量级的企业AICoding助手")
52
+ .version(version);
53
+ program
54
+ .command("init [path]")
55
+ .description("初始化项目")
56
+ .option('--tools <tools>', '选择工具')
57
+ .option('--force', '自动清理遗留文件,不提示')
58
+ .action(async (targetPath = '.', options) => {
59
+ let spinner = (0, ora_1.default)();
60
+ (0, clear_1.default)();
61
+ await (0, welcome_1.showWelcomeAnimation)();
62
+ spinner = (0, ora_1.default)("正在初始化…").start();
63
+ try {
64
+ const resolvedPath = path.resolve(targetPath);
65
+ try {
66
+ const stats = await fs_1.promises.stat(resolvedPath);
67
+ if (!stats.isDirectory()) {
68
+ throw new Error(`Path "${targetPath}" is not a directory`);
69
+ }
70
+ }
71
+ catch (error) {
72
+ if (error.code === 'ENOENT') {
73
+ console.log(`Directory "${targetPath}" doesn't exist, it will be created.`);
74
+ }
75
+ else if (error.message && error.message.includes('not a directory')) {
76
+ throw error;
77
+ }
78
+ else {
79
+ throw new Error(`Cannot access path "${targetPath}": ${error.message}`);
80
+ }
81
+ }
82
+ spinner.succeed(chalk_1.default.green("初始化完成,进行工具选择!")); // 绿色文字
83
+ let toolIds = [];
84
+ try {
85
+ if (options?.tools !== undefined && String(options.tools).trim() !== "") {
86
+ toolIds = (0, tools_1.parseToolsOption)(options.tools);
87
+ }
88
+ if (toolIds.length === 0) {
89
+ toolIds = await (0, tools_1.promptToolSelection)();
90
+ }
91
+ }
92
+ catch (err) {
93
+ spinner.fail(err?.message ?? "Invalid tools");
94
+ process.exit(1);
95
+ }
96
+ if (toolIds.length > 0) {
97
+ await (0, tools_1.writeToolStructure)(resolvedPath, toolIds);
98
+ await (0, tools_1.copyBcoderToToolFolders)(resolvedPath, toolIds);
99
+ }
100
+ spinner.succeed(`初始化完成:${resolvedPath}`);
101
+ }
102
+ catch (error) {
103
+ console.log();
104
+ spinner.fail(`Error: ${error.message}`);
105
+ process.exit(1);
106
+ }
107
+ });
108
+ program
109
+ .command("update [path]")
110
+ .description("将 BCoder 模板更新到已有 AI 工具目录,仅覆盖模板中有的文件,保留其他文件")
111
+ .option("--force", "强制更新,即使工具已经是最新的")
112
+ .action(async (targetPath = ".", options) => {
113
+ const spinner = (0, ora_1.default)("正在更新…").start();
114
+ try {
115
+ const resolvedPath = path.resolve(targetPath);
116
+ const stats = await fs_1.promises.stat(resolvedPath);
117
+ if (!stats.isDirectory()) {
118
+ throw new Error(`路径 "${targetPath}" 不是目录`);
119
+ }
120
+ await (0, tools_1.updateBcoderInToolFolders)(resolvedPath);
121
+ spinner.succeed(`更新完成:${resolvedPath}`);
122
+ }
123
+ catch (error) {
124
+ console.log();
125
+ spinner.fail(error.message);
126
+ process.exit(1);
127
+ }
128
+ });
129
+ // 解析命令行参数
130
+ program.parse(process.argv);
131
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export declare const VALID_TOOLS: readonly ["cursor", "claude", "trae"];
2
+ export declare const TOOL_DISPLAY_NAMES: Record<string, string>;
3
+ export declare function parseToolsOption(value: string | undefined): string[];
4
+ export declare function promptToolSelection(): Promise<string[]>;
5
+ /** 返回 CLI 包内 bcoder 模板目录路径(与 src/cli 平级的 bcoder 目录) */
6
+ export declare function getBcoderTemplatePath(): string;
7
+ /** 将 bcoder 模板目录内容复制到各 AI 工具目录(.cursor、.claude、.trae) */
8
+ export declare function copyBcoderToToolFolders(resolvedPath: string, toolIds: string[]): Promise<void>;
9
+ /** 返回目标目录下已存在的 AI 工具目录名(.cursor、.claude、.trae) */
10
+ export declare function getExistingToolDirs(resolvedPath: string): Promise<string[]>;
11
+ /** 将 bcoder 模板内容同步到已存在的 AI 工具目录:只更新/覆盖模板中有的路径,不删除工具目录里其他文件 */
12
+ export declare function updateBcoderInToolFolders(resolvedPath: string): Promise<void>;
13
+ export declare function writeToolStructure(resolvedPath: string, toolIds: string[]): Promise<void>;
14
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/cli/tools.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,uCAAwC,CAAC;AACjE,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAIrD,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAQpE;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAS7D;AAED,uDAAuD;AACvD,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AA6BD,yDAAyD;AACzD,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,kDAAkD;AAClD,wBAAsB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAiBjF;AAED,8DAA8D;AAC9D,wBAAsB,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAenF;AAGD,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/F"}
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TOOL_DISPLAY_NAMES = exports.VALID_TOOLS = void 0;
37
+ exports.parseToolsOption = parseToolsOption;
38
+ exports.promptToolSelection = promptToolSelection;
39
+ exports.getBcoderTemplatePath = getBcoderTemplatePath;
40
+ exports.copyBcoderToToolFolders = copyBcoderToToolFolders;
41
+ exports.getExistingToolDirs = getExistingToolDirs;
42
+ exports.updateBcoderInToolFolders = updateBcoderInToolFolders;
43
+ exports.writeToolStructure = writeToolStructure;
44
+ const fs_1 = require("fs");
45
+ const path = __importStar(require("path"));
46
+ const prompts_1 = require("@inquirer/prompts");
47
+ exports.VALID_TOOLS = ["cursor", "claude", "trae"];
48
+ exports.TOOL_DISPLAY_NAMES = {
49
+ cursor: "Cursor",
50
+ claude: "Claude Code",
51
+ trae: "Trae",
52
+ };
53
+ function parseToolsOption(value) {
54
+ if (value === undefined || String(value).trim() === "")
55
+ return [];
56
+ const parts = value.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
57
+ const invalid = parts.filter((p) => !exports.VALID_TOOLS.includes(p));
58
+ if (invalid.length > 0) {
59
+ throw new Error(`Invalid tool(s): ${invalid.join(", ")}. Allowed: cursor, claude, trae`);
60
+ }
61
+ return [...new Set(parts)];
62
+ }
63
+ async function promptToolSelection() {
64
+ const answers = await (0, prompts_1.checkbox)({
65
+ message: "选择 AI 编程工具(可多选)",
66
+ choices: exports.VALID_TOOLS.map((id) => ({ name: exports.TOOL_DISPLAY_NAMES[id] ?? id, value: id })),
67
+ });
68
+ if (answers.length === 0) {
69
+ throw new Error("至少选择一项");
70
+ }
71
+ return [...answers];
72
+ }
73
+ /** 返回 CLI 包内 bcoder 模板目录路径(与 src/cli 平级的 bcoder 目录) */
74
+ function getBcoderTemplatePath() {
75
+ return path.join(__dirname, "..", "..", "bcoder");
76
+ }
77
+ /** 递归复制目录内容到目标目录(不覆盖已存在文件,与 writeToolStructure 的“不覆盖”一致) */
78
+ async function copyDirContents(srcDir, destDir, options) {
79
+ await fs_1.promises.mkdir(destDir, { recursive: true });
80
+ const entries = await fs_1.promises.readdir(srcDir, { withFileTypes: true });
81
+ for (const e of entries) {
82
+ const srcPath = path.join(srcDir, e.name);
83
+ const destPath = path.join(destDir, e.name);
84
+ if (e.isDirectory()) {
85
+ await copyDirContents(srcPath, destPath, options);
86
+ }
87
+ else {
88
+ if (!options?.overwrite) {
89
+ try {
90
+ await fs_1.promises.access(destPath);
91
+ continue; // 已存在则不覆盖
92
+ }
93
+ catch {
94
+ // 文件不存在,继续写入
95
+ }
96
+ }
97
+ await fs_1.promises.copyFile(srcPath, destPath);
98
+ }
99
+ }
100
+ }
101
+ /** 将 bcoder 模板目录内容复制到各 AI 工具目录(.cursor、.claude、.trae) */
102
+ async function copyBcoderToToolFolders(resolvedPath, toolIds) {
103
+ const templatePath = getBcoderTemplatePath();
104
+ try {
105
+ await fs_1.promises.access(templatePath);
106
+ }
107
+ catch {
108
+ return; // 模板目录不存在则静默跳过(如仅发布 bin/src 时)
109
+ }
110
+ for (const id of toolIds) {
111
+ const destBase = path.join(resolvedPath, `.${id}`);
112
+ await copyDirContents(templatePath, destBase);
113
+ }
114
+ }
115
+ /** 返回目标目录下已存在的 AI 工具目录名(.cursor、.claude、.trae) */
116
+ async function getExistingToolDirs(resolvedPath) {
117
+ const names = [];
118
+ try {
119
+ const entries = await fs_1.promises.readdir(resolvedPath, { withFileTypes: true });
120
+ for (const e of entries) {
121
+ if (e.isDirectory() &&
122
+ e.name.startsWith(".") &&
123
+ exports.VALID_TOOLS.includes(e.name.slice(1))) {
124
+ names.push(e.name);
125
+ }
126
+ }
127
+ }
128
+ catch {
129
+ // 目录不可读则返回空
130
+ }
131
+ return names;
132
+ }
133
+ /** 将 bcoder 模板内容同步到已存在的 AI 工具目录:只更新/覆盖模板中有的路径,不删除工具目录里其他文件 */
134
+ async function updateBcoderInToolFolders(resolvedPath) {
135
+ const templatePath = getBcoderTemplatePath();
136
+ try {
137
+ await fs_1.promises.access(templatePath);
138
+ }
139
+ catch {
140
+ throw new Error("bcoder 模板目录不存在,无法执行 update");
141
+ }
142
+ const toolDirNames = await getExistingToolDirs(resolvedPath);
143
+ if (toolDirNames.length === 0) {
144
+ throw new Error(`未找到 AI 工具目录(.cursor / .claude / .trae),请先在此路径下执行 bcoder init`);
145
+ }
146
+ for (const dirName of toolDirNames) {
147
+ const destBase = path.join(resolvedPath, dirName);
148
+ await copyDirContents(templatePath, destBase, { overwrite: true });
149
+ }
150
+ }
151
+ async function writeToolStructure(resolvedPath, toolIds) {
152
+ for (const id of toolIds) {
153
+ const rulesDir = path.join(resolvedPath, `.${id}`, "rules");
154
+ await fs_1.promises.mkdir(rulesDir, { recursive: true });
155
+ }
156
+ }
157
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/cli/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function showWelcomeAnimation(): Promise<void>;
2
+ //# sourceMappingURL=welcome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../src/cli/welcome.ts"],"names":[],"mappings":"AAMA,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAY1D"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.showWelcomeAnimation = showWelcomeAnimation;
7
+ const figlet_1 = __importDefault(require("figlet"));
8
+ const gradient_string_1 = __importDefault(require("gradient-string"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const delay = (ms) => new Promise((r) => setTimeout(r, ms));
11
+ async function showWelcomeAnimation() {
12
+ try {
13
+ console.log(chalk_1.default.gray("Welcome to"));
14
+ const text = figlet_1.default.textSync("BCoder", { font: "Standard" });
15
+ const lines = text.split("\n").filter((line) => line.trim().length > 0);
16
+ for (const line of lines) {
17
+ console.log((0, gradient_string_1.default)("cyan", "magenta")(line));
18
+ await delay(300);
19
+ }
20
+ }
21
+ catch {
22
+ // 静默跳过,不中断 init
23
+ }
24
+ }
25
+ //# sourceMappingURL=welcome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"welcome.js","sourceRoot":"","sources":["../../src/cli/welcome.ts"],"names":[],"mappings":";;;;;AAMA,oDAYC;AAlBD,oDAA4B;AAC5B,sEAAuC;AACvC,kDAA0B;AAE1B,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAE7D,KAAK,UAAU,oBAAoB;IACxC,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,gBAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACxE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,IAAA,yBAAQ,EAAC,MAAM,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC/C,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "bcoder",
3
+ "version": "0.0.1",
4
+ "description": "极轻量级的企业 AI Coding 助手:init 初始化项目与 AI 工具目录,update 同步 bcoder 模板",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "bcoder": "bin/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc -p tsconfig.build.json",
11
+ "prepublishOnly": "npm run build",
12
+ "test": "echo \"Error: no test specified\" && exit 1"
13
+ },
14
+ "files": [
15
+ "bin",
16
+ "dist",
17
+ "bcoder",
18
+ "README.md"
19
+ ],
20
+ "keywords": [
21
+ "cli",
22
+ "ai",
23
+ "cursor",
24
+ "coding",
25
+ "init"
26
+ ],
27
+ "author": "",
28
+ "license": "ISC",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": ""
32
+ },
33
+ "engines": {
34
+ "node": ">=18"
35
+ },
36
+ "devDependencies": {
37
+ "@types/clear": "^0.1.4",
38
+ "@types/figlet": "^1.7.0",
39
+ "@types/gradient-string": "^1.1.6",
40
+ "@types/node": "^25.1.0",
41
+ "ts-node": "^10.9.2",
42
+ "typescript": "^5.9.3"
43
+ },
44
+ "dependencies": {
45
+ "@inquirer/core": "^10.2.2",
46
+ "@inquirer/prompts": "^7.8.0",
47
+ "chalk": "^5.6.2",
48
+ "clear": "^0.1.0",
49
+ "commander": "^14.0.2",
50
+ "figlet": "^1.10.0",
51
+ "gradient-string": "^3.0.0",
52
+ "ora": "^9.1.0"
53
+ }
54
+ }