ai-workflow-init 1.3.0 → 1.3.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.
Files changed (3) hide show
  1. package/README.md +27 -7
  2. package/cli.js +162 -19
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -7,24 +7,44 @@ Initialize standardized AI workflow docs and command templates into ANY reposito
7
7
  > Requires: [Node.js](https://nodejs.org/) (>= 14)
8
8
 
9
9
  Run in the root of your target project:
10
+
10
11
  ```bash
11
12
  npx ai-workflow-init
12
13
  ```
13
- This will automatically fetch and place:
14
+
15
+ The installer will prompt you to select which AI tool(s) to configure:
16
+
17
+ - **1. Cursor** → installs `.cursor/commands` and `.cursor/prompts`
18
+ - **2. GitHub Copilot** → installs `.github/prompts`
19
+ - **3. Both** → installs both command sets and prompts
20
+
21
+ All installations include:
22
+
14
23
  - `docs/ai` (planning, implementation, testing, project standards)
15
- - `.cursor/commands` (AI agent commands)
16
- - `AGENTS.md`
24
+ - `AGENTS.md` with rules and workflow overview
25
+
26
+ ## Smart Installation Features
27
+
28
+ - **Protected Files**: Core documentation files (`CODE_CONVENTIONS.md`, `PROJECT_STRUCTURE.md`) are never overwritten if they already exist
29
+ - **Selective Updates**: Only `template-feature.md` and `README.md` files are updated in each documentation subfolder
30
+ - **Safe Cloning**: Uses temporary directories to ensure no data loss
17
31
 
18
32
  ## Notes
33
+
19
34
  - Works on Windows (PowerShell/CMD/Git Bash), macOS, and Linux.
20
- - If the destination folders already exist, the installer will overwrite files as needed.
21
35
  - After installation, commit the new files to your repository so your team can use them.
22
36
 
23
37
  ## What gets installed
24
- - Documentation templates and guides under `docs/ai/`
25
- - AI agent commands under `.cursor/commands/`
26
- - `AGENTS.md` with rules and workflow overview
38
+
39
+ - **Always installed**:
40
+ - Documentation templates and guides under `docs/ai/`
41
+ - `AGENTS.md` with rules and workflow overview
42
+ - **Based on your choice**:
43
+ - `.cursor/commands/` and `.cursor/prompts/` (if Cursor is selected)
44
+ - `.github/prompts/` (if GitHub Copilot is selected)
27
45
 
28
46
  ## Troubleshooting
47
+
29
48
  - Ensure Node.js is installed and accessible in your PATH.
30
49
  - If your network blocks npm registry calls, try again on a different network or with a VPN.
50
+ - Ensure you have write permissions in your project directory.
package/cli.js CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const { execSync } = require("child_process");
4
- const { existsSync, mkdirSync } = require("fs");
4
+ const { existsSync, mkdirSync, rmSync, cpSync, readdirSync } = require("fs");
5
5
  const readline = require("readline");
6
+ const path = require("path");
6
7
 
7
8
  // Repo workflow gốc của bạn
8
9
  const REPO = "phananhtuan09/ai-agent-workflow";
@@ -23,13 +24,149 @@ function run(cmd) {
23
24
  }
24
25
  }
25
26
 
26
- // Hỏi user chọn IDE
27
- const rl = readline.createInterface({
28
- input: process.stdin,
29
- output: process.stdout,
30
- });
27
+ // Clone folder luôn ghi đè
28
+ function cloneFolderForce(source, dest) {
29
+ mkdirSync(path.dirname(dest), { recursive: true });
30
+ const tempDir = path.join(dest, ".temp-clone");
31
+
32
+ // Xóa temp folder nếu tồn tại
33
+ if (existsSync(tempDir)) {
34
+ rmSync(tempDir, { recursive: true, force: true });
35
+ }
36
+
37
+ run(`npx degit ${source} ${tempDir} --force`);
38
+
39
+ // Tạo dest folder nếu chưa có
40
+ if (!existsSync(dest)) {
41
+ mkdirSync(dest, { recursive: true });
42
+ }
43
+
44
+ // Copy tất cả files từ temp vào dest (ghi đè toàn bộ)
45
+ const filesToCopy = execSync(`find ${tempDir} -type f`, { encoding: "utf8" })
46
+ .trim()
47
+ .split("\n")
48
+ .filter(Boolean);
49
+
50
+ for (const file of filesToCopy) {
51
+ const relativePath = path.relative(tempDir, file);
52
+ const destFile = path.join(dest, relativePath);
53
+
54
+ // Tạo folder nếu cần
55
+ mkdirSync(path.dirname(destFile), { recursive: true });
56
+
57
+ // Copy file với ghi đè
58
+ cpSync(file, destFile, { force: true });
59
+ }
60
+
61
+ // Xóa temp folder
62
+ rmSync(tempDir, { recursive: true, force: true });
63
+ }
64
+
65
+ // Clone folder docs/ai một cách an toàn
66
+ function cloneDocsAI(source, dest) {
67
+ mkdirSync(dest, { recursive: true });
68
+ const tempDir = path.join(dest, ".temp-clone");
69
+
70
+ // Xóa temp folder nếu tồn tại
71
+ if (existsSync(tempDir)) {
72
+ rmSync(tempDir, { recursive: true, force: true });
73
+ }
74
+
75
+ run(`npx degit ${source} ${tempDir} --force`);
76
+
77
+ // Xử lý từng subfolder
78
+ const subfolders = ["implementation", "planning", "testing"];
79
+
80
+ // Xử lý folders: implementation, planning, testing
81
+ for (const subfolder of subfolders) {
82
+ const tempSubfolder = path.join(tempDir, subfolder);
83
+ const destSubfolder = path.join(dest, subfolder);
84
+
85
+ if (existsSync(tempSubfolder)) {
86
+ mkdirSync(destSubfolder, { recursive: true });
87
+
88
+ // Chỉ copy file template và README.md
89
+ const filesToCopy = ["README.md", "feature-template.md"];
31
90
 
91
+ for (const file of filesToCopy) {
92
+ const srcFile = path.join(tempSubfolder, file);
93
+ const destFile = path.join(destSubfolder, file);
94
+
95
+ if (existsSync(srcFile)) {
96
+ cpSync(srcFile, destFile, { force: true });
97
+ }
98
+ }
99
+ }
100
+ }
101
+
102
+ // Xử lý folder: project
103
+ const tempProject = path.join(tempDir, "project");
104
+ const destProject = path.join(dest, "project");
105
+
106
+ if (existsSync(tempProject)) {
107
+ mkdirSync(destProject, { recursive: true });
108
+
109
+ // 1. Chỉ tạo CODE_CONVENTIONS.md và PROJECT_STRUCTURE.md nếu chưa có
110
+ const protectedFiles = [
111
+ "CODE_CONVENTIONS.md",
112
+ "PROJECT_STRUCTURE.md",
113
+ "README.md",
114
+ ];
115
+
116
+ for (const file of protectedFiles) {
117
+ const srcFile = path.join(tempProject, file);
118
+ const destFile = path.join(destProject, file);
119
+
120
+ if (existsSync(srcFile)) {
121
+ // Nếu là CODE_CONVENTIONS.md hoặc PROJECT_STRUCTURE.md, chỉ tạo nếu chưa có
122
+ if (
123
+ (file === "CODE_CONVENTIONS.md" || file === "PROJECT_STRUCTURE.md") &&
124
+ existsSync(destFile)
125
+ ) {
126
+ console.log(`⏭️ Skipping (already exists): docs/ai/project/${file}`);
127
+ continue;
128
+ }
129
+
130
+ // Các file khác luôn ghi đè
131
+ cpSync(srcFile, destFile, { force: true });
132
+ }
133
+ }
134
+
135
+ // 2. Ghi đè folder template-convention
136
+ const tempTemplateConvention = path.join(
137
+ tempProject,
138
+ "template-convention"
139
+ );
140
+ const destTemplateConvention = path.join(
141
+ destProject,
142
+ "template-convention"
143
+ );
144
+
145
+ if (existsSync(tempTemplateConvention)) {
146
+ // Xóa folder cũ nếu tồn tại
147
+ if (existsSync(destTemplateConvention)) {
148
+ rmSync(destTemplateConvention, { recursive: true, force: true });
149
+ }
150
+
151
+ // Copy folder mới
152
+ cpSync(tempTemplateConvention, destTemplateConvention, {
153
+ recursive: true,
154
+ force: true,
155
+ });
156
+ }
157
+ }
158
+
159
+ // Xóa temp folder
160
+ rmSync(tempDir, { recursive: true, force: true });
161
+ }
162
+
163
+ // Hỏi user chọn IDE
32
164
  function askIDE() {
165
+ const rl = readline.createInterface({
166
+ input: process.stdin,
167
+ output: process.stdout,
168
+ });
169
+
33
170
  return new Promise((resolve) => {
34
171
  console.log("\n🤖 Which AI tool(s) do you want to setup?");
35
172
  console.log("1. Cursor");
@@ -53,15 +190,11 @@ async function main() {
53
190
  process.exit(1);
54
191
  }
55
192
 
56
- // Kiểm tra tạo folder nếu chưa
57
- if (!existsSync("docs/ai")) {
58
- mkdirSync("docs/ai", { recursive: true });
59
- }
60
-
193
+ // Clone docs/ai một cách an toàn, bảo vệ các file quan trọng
61
194
  step("🚚 Downloading workflow template (docs/ai)...");
62
- run(`npx degit ${REPO}/docs/ai docs/ai --force`);
195
+ cloneDocsAI(`${REPO}/docs/ai`, "docs/ai");
63
196
 
64
- // Clone Cursor commands
197
+ // Clone Cursor commands (luôn ghi đè)
65
198
  if (installCursor) {
66
199
  if (!existsSync(".cursor/commands")) {
67
200
  mkdirSync(".cursor/commands", { recursive: true });
@@ -70,16 +203,26 @@ async function main() {
70
203
  run(`npx degit ${REPO}/.cursor/commands .cursor/commands --force`);
71
204
  }
72
205
 
73
- // Clone GitHub Copilot commands (nếu folder khác)
206
+ // Clone GitHub Copilot prompts (luôn ghi đè)
74
207
  if (installCopilot) {
75
- if (!existsSync(".copilot/commands")) {
76
- mkdirSync(".copilot/commands", { recursive: true });
208
+ if (!existsSync(".github/prompts")) {
209
+ mkdirSync(".github/prompts", { recursive: true });
210
+ }
211
+ step("🚚 Downloading GitHub Copilot prompts (.github/prompts)...");
212
+ run(`npx degit ${REPO}/.github/prompts .github/prompts --force`);
213
+ }
214
+
215
+ // Clone Cursor prompts (luôn ghi đè)
216
+ if (installCursor) {
217
+ if (!existsSync(".cursor/prompts")) {
218
+ mkdirSync(".cursor/prompts", { recursive: true });
77
219
  }
78
- step("🚚 Downloading GitHub Copilot agent commands (.copilot/commands)...");
79
- run(`npx degit ${REPO}/.copilot/commands .copilot/commands --force`);
220
+ step("🚚 Downloading Cursor prompts (.cursor/prompts)...");
221
+ run(`npx degit ${REPO}/.cursor/prompts .cursor/prompts --force`);
80
222
  }
81
223
 
82
- step("🚚 Downloading AGENTS.md ...");
224
+ // Download AGENTS.md (luôn ghi đè)
225
+ step("🚚 Downloading AGENTS.md...");
83
226
  try {
84
227
  run(`curl -fsSL ${RAW_BASE}/AGENTS.md -o AGENTS.md`);
85
228
  } catch (_) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-workflow-init",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Initialize AI workflow docs & commands into any repo with one command",
5
5
  "bin": {
6
6
  "ai-workflow-init": "./cli.js"