superpower_setup 1.0.0

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/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # superpower_setup
2
+
3
+ CLI tool để cài đặt [obra/superpowers](https://github.com/obra/superpowers) vào project Google Antigravity.
4
+
5
+ ## Cài đặt & Sử dụng
6
+
7
+ ### Cài đặt superpowers vào project
8
+
9
+ ```bash
10
+ npx superpower_setup init
11
+ ```
12
+
13
+ ### Cập nhật superpowers lên phiên bản mới nhất
14
+
15
+ ```bash
16
+ npx superpower_setup update
17
+ ```
18
+
19
+ ### Options
20
+
21
+ | Option | Mô tả | Mặc định |
22
+ |--------|--------|----------|
23
+ | `--target <path>` | Thư mục đích | Thư mục hiện tại |
24
+ | `--branch <name>` | Branch của repo superpowers | `main` |
25
+ | `--force` | Ghi đè files đã tồn tại | `false` |
26
+
27
+ ### Ví dụ
28
+
29
+ ```bash
30
+ # Cài đặt vào project hiện tại
31
+ npx superpower_setup init
32
+
33
+ # Cài đặt vào thư mục khác
34
+ npx superpower_setup init --target /path/to/project
35
+
36
+ # Ghi đè files đã có
37
+ npx superpower_setup init --force
38
+
39
+ # Cài đặt từ branch khác
40
+ npx superpower_setup init --branch develop
41
+ ```
42
+
43
+ ## Cấu trúc sau khi cài đặt
44
+
45
+ ```
46
+ project-root/
47
+ ├── .agents/
48
+ │ ├── skills/superpowers/ # 14 skills
49
+ │ ├── agents/superpowers/ # Agent definitions
50
+ │ ├── commands/superpowers/ # Custom commands
51
+ │ └── hooks/superpowers/ # Session hooks
52
+ ├── GEMINI.md # Context file (tham chiếu skills)
53
+ └── gemini-extension.json # Extension config
54
+ ```
55
+
56
+ ## Skills đi kèm
57
+
58
+ | Skill | Mô tả |
59
+ |-------|--------|
60
+ | **brainstorming** | Socratic design refinement |
61
+ | **test-driven-development** | RED-GREEN-REFACTOR cycle |
62
+ | **systematic-debugging** | 4-phase root cause process |
63
+ | **writing-plans** | Detailed implementation plans |
64
+ | **executing-plans** | Batch execution with checkpoints |
65
+ | **subagent-driven-development** | Fast iteration with two-stage review |
66
+ | **using-git-worktrees** | Parallel development branches |
67
+ | **requesting-code-review** | Pre-review checklist |
68
+ | **receiving-code-review** | Responding to feedback |
69
+ | **finishing-a-development-branch** | Merge/PR decision workflow |
70
+ | **verification-before-completion** | Ensure it's actually fixed |
71
+ | **dispatching-parallel-agents** | Concurrent subagent workflows |
72
+ | **writing-skills** | Create new skills |
73
+ | **using-superpowers** | Introduction to the skills system |
74
+
75
+ ## License
76
+
77
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { parseArgs } from "node:util";
4
+ import { runInit } from "../src/index.js";
5
+ import { logInfo, logError, LOG_COLORS } from "../src/utils.js";
6
+
7
+ const PACKAGE_VERSION = "1.0.0";
8
+
9
+ const HELP_TEXT = `
10
+ ${LOG_COLORS.cyan}superpower_setup${LOG_COLORS.reset} - Cài đặt obra/superpowers vào Google Antigravity project
11
+
12
+ ${LOG_COLORS.yellow}Usage:${LOG_COLORS.reset}
13
+ npx superpower_setup init [options] Tải và cài đặt superpowers skills
14
+ npx superpower_setup update [options] Cập nhật superpowers lên phiên bản mới nhất
15
+ npx superpower_setup --help Hiển thị help
16
+ npx superpower_setup --version Hiển thị version
17
+
18
+ ${LOG_COLORS.yellow}Options:${LOG_COLORS.reset}
19
+ --target <path> Thư mục đích (mặc định: thư mục hiện tại)
20
+ --branch <name> Branch của repo superpowers (mặc định: main)
21
+ --force Ghi đè files đã tồn tại
22
+ --help, -h Hiển thị help
23
+ --version, -v Hiển thị version
24
+ `;
25
+
26
+ function main() {
27
+ const args = process.argv.slice(2);
28
+ const command = args[0];
29
+
30
+ if (!command || command === "--help" || command === "-h") {
31
+ console.log(HELP_TEXT);
32
+ process.exit(0);
33
+ }
34
+
35
+ if (command === "--version" || command === "-v") {
36
+ console.log(`superpower_setup v${PACKAGE_VERSION}`);
37
+ process.exit(0);
38
+ }
39
+
40
+ const command_args = args.slice(1);
41
+
42
+ let parsed_options;
43
+ try {
44
+ const { values } = parseArgs({
45
+ args: command_args,
46
+ options: {
47
+ target: { type: "string", default: process.cwd() },
48
+ branch: { type: "string", default: "main" },
49
+ force: { type: "boolean", default: false },
50
+ help: { type: "boolean", short: "h", default: false },
51
+ },
52
+ allowPositionals: true,
53
+ });
54
+ parsed_options = values;
55
+ } catch (err) {
56
+ logError(`Lỗi parse arguments: ${err.message}`);
57
+ process.exit(1);
58
+ }
59
+
60
+ if (parsed_options.help) {
61
+ console.log(HELP_TEXT);
62
+ process.exit(0);
63
+ }
64
+
65
+ switch (command) {
66
+ case "init":
67
+ runInit({
68
+ target_dir: parsed_options.target,
69
+ branch: parsed_options.branch,
70
+ is_force: parsed_options.force,
71
+ is_update: false,
72
+ });
73
+ break;
74
+
75
+ case "update":
76
+ runInit({
77
+ target_dir: parsed_options.target,
78
+ branch: parsed_options.branch,
79
+ is_force: true,
80
+ is_update: true,
81
+ });
82
+ break;
83
+
84
+ default:
85
+ logError(`Lệnh không hợp lệ: "${command}"`);
86
+ logInfo('Chạy "npx superpower_setup --help" để xem hướng dẫn.');
87
+ process.exit(1);
88
+ }
89
+ }
90
+
91
+ main();
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "superpower_setup",
3
+ "version": "1.0.0",
4
+ "description": "CLI tool to install obra/superpowers skills into Google Antigravity projects",
5
+ "type": "module",
6
+ "bin": {
7
+ "superpower_setup": "./bin/cli.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "src/",
12
+ "README.md"
13
+ ],
14
+ "keywords": [
15
+ "superpowers",
16
+ "gemini",
17
+ "antigravity",
18
+ "ai",
19
+ "skills",
20
+ "coding-agent"
21
+ ],
22
+ "author": "",
23
+ "license": "MIT"
24
+ }
package/src/index.js ADDED
@@ -0,0 +1,261 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ import { tmpdir } from "node:os";
4
+ import { randomBytes } from "node:crypto";
5
+ import {
6
+ logInfo,
7
+ logSuccess,
8
+ logWarning,
9
+ logError,
10
+ logStep,
11
+ ensureDir,
12
+ copyDirRecursive,
13
+ cleanUp,
14
+ checkGitInstalled,
15
+ cloneRepo,
16
+ LOG_COLORS,
17
+ } from "./utils.js";
18
+
19
+ const REPO_URL = "https://github.com/obra/superpowers.git";
20
+ const TOTAL_STEPS = 5;
21
+
22
+ // Các thư mục/files cần copy từ repo superpowers
23
+ // Theo docs Antigravity: skills đặt trong .agents/skills/<skill-folder>/ (workspace-specific)
24
+ // Ref: https://antigravity.google/docs/skills
25
+ const COPY_MAP = [
26
+ { source: "skills", dest_sub: join(".agents", "skills", "superpowers"), type: "dir" },
27
+ { source: "agents", dest_sub: join(".agents", "agents", "superpowers"), type: "dir" },
28
+ { source: "commands", dest_sub: join(".agents", "commands", "superpowers"), type: "dir" },
29
+ { source: "hooks", dest_sub: join(".agents", "hooks", "superpowers"), type: "dir" },
30
+ ];
31
+
32
+ /**
33
+ * Tạo nội dung GEMINI.md cho project đích
34
+ * References đến tất cả skills đã cài đặt
35
+ */
36
+ function buildGeminiMdContent(skills_dir) {
37
+ const lines = [
38
+ "# Superpowers Skills",
39
+ "",
40
+ "<!-- Auto-generated by superpower_setup. Do not edit this section manually. -->",
41
+ "",
42
+ ];
43
+
44
+ // Tham chiếu đến skills theo cấu trúc Antigravity (.agents/skills/)
45
+ lines.push("@./.agents/skills/superpowers/using-superpowers/SKILL.md");
46
+ lines.push("@./.agents/skills/superpowers/using-superpowers/references/gemini-tools.md");
47
+ lines.push("");
48
+
49
+ return lines.join("\n");
50
+ }
51
+
52
+ /**
53
+ * Cập nhật hoặc tạo GEMINI.md ở root project
54
+ */
55
+ function setupGeminiMd(target_dir, is_force) {
56
+ const gemini_md_path = join(target_dir, "GEMINI.md");
57
+ const superpowers_content = buildGeminiMdContent(target_dir);
58
+ const MARKER_START = "<!-- SUPERPOWERS_START -->";
59
+ const MARKER_END = "<!-- SUPERPOWERS_END -->";
60
+ const wrapped_content = `${MARKER_START}\n${superpowers_content}\n${MARKER_END}`;
61
+
62
+ if (existsSync(gemini_md_path)) {
63
+ const existing_content = readFileSync(gemini_md_path, "utf-8");
64
+
65
+ // Kiểm tra xem đã có section superpowers chưa
66
+ if (existing_content.includes(MARKER_START)) {
67
+ if (!is_force) {
68
+ logWarning("GEMINI.md đã chứa cấu hình superpowers. Dùng --force để ghi đè.");
69
+ return false;
70
+ }
71
+ // Replace section cũ
72
+ const regex = new RegExp(
73
+ `${escapeRegex(MARKER_START)}[\\s\\S]*?${escapeRegex(MARKER_END)}`,
74
+ "g"
75
+ );
76
+ const updated_content = existing_content.replace(regex, wrapped_content);
77
+ writeFileSync(gemini_md_path, updated_content, "utf-8");
78
+ logSuccess("Đã cập nhật section superpowers trong GEMINI.md");
79
+ } else {
80
+ // Append vào cuối file
81
+ const updated_content = `${existing_content}\n\n${wrapped_content}\n`;
82
+ writeFileSync(gemini_md_path, updated_content, "utf-8");
83
+ logSuccess("Đã thêm cấu hình superpowers vào GEMINI.md");
84
+ }
85
+ } else {
86
+ writeFileSync(gemini_md_path, `${wrapped_content}\n`, "utf-8");
87
+ logSuccess("Đã tạo GEMINI.md với cấu hình superpowers");
88
+ }
89
+
90
+ return true;
91
+ }
92
+
93
+ /**
94
+ * Copy gemini-extension.json vào root project
95
+ */
96
+ function setupGeminiExtension(repo_dir, target_dir, is_force) {
97
+ const source_path = join(repo_dir, "gemini-extension.json");
98
+ const dest_path = join(target_dir, "gemini-extension.json");
99
+
100
+ if (!existsSync(source_path)) {
101
+ logWarning("Không tìm thấy gemini-extension.json trong repo.");
102
+ return;
103
+ }
104
+
105
+ if (existsSync(dest_path) && !is_force) {
106
+ logWarning("gemini-extension.json đã tồn tại. Dùng --force để ghi đè.");
107
+ return;
108
+ }
109
+
110
+ // Đọc và chỉnh sửa contextFileName path
111
+ const extension_content = JSON.parse(readFileSync(source_path, "utf-8"));
112
+ extension_content.contextFileName = "GEMINI.md";
113
+
114
+ writeFileSync(dest_path, JSON.stringify(extension_content, null, 2) + "\n", "utf-8");
115
+ logSuccess("Đã copy gemini-extension.json");
116
+ }
117
+
118
+ /**
119
+ * Thêm .agents vào .gitignore nếu chưa có
120
+ */
121
+ function setupGitignore(target_dir) {
122
+ const gitignore_path = join(target_dir, ".gitignore");
123
+ const entry = ".agents";
124
+
125
+ if (existsSync(gitignore_path)) {
126
+ const content = readFileSync(gitignore_path, "utf-8");
127
+ const lines = content.split(/\r?\n/).map((l) => l.trim());
128
+
129
+ if (lines.includes(entry) || lines.includes(entry + "/")) {
130
+ logInfo(".agents đã có trong .gitignore");
131
+ return;
132
+ }
133
+
134
+ // Append vào cuối file
135
+ const separator = content.endsWith("\n") ? "" : "\n";
136
+ writeFileSync(gitignore_path, `${content}${separator}\n# Superpowers skills\n${entry}\n`, "utf-8");
137
+ logSuccess("Đã thêm .agents vào .gitignore");
138
+ } else {
139
+ writeFileSync(gitignore_path, `# Superpowers skills\n${entry}\n`, "utf-8");
140
+ logSuccess("Đã tạo .gitignore với .agents");
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Escape regex special characters
146
+ */
147
+ function escapeRegex(str) {
148
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
149
+ }
150
+
151
+ /**
152
+ * Main init function
153
+ */
154
+ export function runInit({ target_dir, branch, is_force, is_update }) {
155
+ const resolved_target = resolve(target_dir);
156
+ const action_name = is_update ? "Cập nhật" : "Cài đặt";
157
+ const temp_dir = join(tmpdir(), `superpower_setup_${randomBytes(6).toString("hex")}`);
158
+
159
+ console.log("");
160
+ console.log(
161
+ `${LOG_COLORS.bold}${LOG_COLORS.magenta}⚡ Superpower Setup${LOG_COLORS.reset} - ${action_name} superpowers skills`
162
+ );
163
+ console.log(`${LOG_COLORS.dim} Target: ${resolved_target}${LOG_COLORS.reset}`);
164
+ console.log(`${LOG_COLORS.dim} Branch: ${branch}${LOG_COLORS.reset}`);
165
+ console.log("");
166
+
167
+ // ── Step 1: Kiểm tra git ──────────────────────────────────────────
168
+ logStep(1, TOTAL_STEPS, "Kiểm tra prerequisites...");
169
+
170
+ if (!checkGitInstalled()) {
171
+ logError("Git chưa được cài đặt. Vui lòng cài đặt git trước.");
172
+ logInfo("Tải git tại: https://git-scm.com/downloads");
173
+ process.exit(1);
174
+ }
175
+
176
+ logSuccess("Git đã sẵn sàng");
177
+
178
+ // ── Step 2: Clone repo ────────────────────────────────────────────
179
+ logStep(2, TOTAL_STEPS, "Tải superpowers từ GitHub...");
180
+
181
+ try {
182
+ logInfo(`Cloning ${REPO_URL} (branch: ${branch})...`);
183
+ cloneRepo({ repo_url: REPO_URL, target_dir: temp_dir, branch });
184
+ logSuccess("Đã tải xong repo superpowers");
185
+ } catch (err) {
186
+ logError(`Không thể clone repo: ${err.message}`);
187
+ cleanUp(temp_dir);
188
+ process.exit(1);
189
+ }
190
+
191
+ // ── Step 3: Copy files ────────────────────────────────────────────
192
+ logStep(3, TOTAL_STEPS, "Copy skills, agents, commands, hooks...");
193
+
194
+ let total_files = 0;
195
+
196
+ for (const item of COPY_MAP) {
197
+ const source_path = join(temp_dir, item.source);
198
+ const dest_path = join(resolved_target, item.dest_sub);
199
+
200
+ if (!existsSync(source_path)) {
201
+ logWarning(`Không tìm thấy thư mục: ${item.source}`);
202
+ continue;
203
+ }
204
+
205
+ if (existsSync(dest_path) && !is_force && !is_update) {
206
+ logWarning(`${item.dest_sub} đã tồn tại. Dùng --force để ghi đè.`);
207
+ continue;
208
+ }
209
+
210
+ // Xóa thư mục cũ nếu update/force
211
+ if (existsSync(dest_path) && (is_force || is_update)) {
212
+ cleanUp(dest_path);
213
+ }
214
+
215
+ const count = copyDirRecursive(source_path, dest_path);
216
+ total_files += count;
217
+ logSuccess(`${item.source}/ → ${item.dest_sub} (${count} files)`);
218
+ }
219
+
220
+ logInfo(`Tổng cộng: ${total_files} files đã được copy`);
221
+
222
+ // ── Step 4: Setup GEMINI.md, gemini-extension.json, .gitignore ────
223
+ logStep(4, TOTAL_STEPS, "Cấu hình GEMINI.md, gemini-extension.json, .gitignore...");
224
+
225
+ setupGeminiMd(resolved_target, is_force || is_update);
226
+ setupGeminiExtension(temp_dir, resolved_target, is_force || is_update);
227
+ setupGitignore(resolved_target);
228
+
229
+ // ── Step 5: Cleanup ───────────────────────────────────────────────
230
+ logStep(5, TOTAL_STEPS, "Dọn dẹp...");
231
+
232
+ cleanUp(temp_dir);
233
+ logSuccess("Đã xóa temp files");
234
+
235
+ // ── Done ──────────────────────────────────────────────────────────
236
+ console.log("");
237
+ console.log(
238
+ `${LOG_COLORS.green}${LOG_COLORS.bold}🎉 ${action_name} superpowers thành công!${LOG_COLORS.reset}`
239
+ );
240
+ console.log("");
241
+ console.log(`${LOG_COLORS.cyan}Các skills đã được cài đặt:${LOG_COLORS.reset}`);
242
+ console.log(" • brainstorming - Socratic design refinement");
243
+ console.log(" • dispatching-parallel-agents - Concurrent subagent workflows");
244
+ console.log(" • executing-plans - Batch execution with checkpoints");
245
+ console.log(" • finishing-a-development-branch - Merge/PR decision workflow");
246
+ console.log(" • receiving-code-review - Responding to feedback");
247
+ console.log(" • requesting-code-review - Pre-review checklist");
248
+ console.log(" • subagent-driven-development - Fast iteration with two-stage review");
249
+ console.log(" • systematic-debugging - 4-phase root cause process");
250
+ console.log(" • test-driven-development - RED-GREEN-REFACTOR cycle");
251
+ console.log(" • using-git-worktrees - Parallel development branches");
252
+ console.log(" • using-superpowers - Introduction to the skills system");
253
+ console.log(" • verification-before-completion - Ensure it's actually fixed");
254
+ console.log(" • writing-plans - Detailed implementation plans");
255
+ console.log(" • writing-skills - Create new skills");
256
+ console.log("");
257
+ console.log(
258
+ `${LOG_COLORS.dim}Chạy "npx superpower_setup update" để cập nhật lên phiên bản mới nhất.${LOG_COLORS.reset}`
259
+ );
260
+ console.log("");
261
+ }
package/src/utils.js ADDED
@@ -0,0 +1,91 @@
1
+ import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, rmSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { execSync } from "node:child_process";
4
+
5
+ // ─── Console colors ─────────────────────────────────────────────────
6
+ export const LOG_COLORS = {
7
+ reset: "\x1b[0m",
8
+ red: "\x1b[31m",
9
+ green: "\x1b[32m",
10
+ yellow: "\x1b[33m",
11
+ blue: "\x1b[34m",
12
+ magenta: "\x1b[35m",
13
+ cyan: "\x1b[36m",
14
+ dim: "\x1b[2m",
15
+ bold: "\x1b[1m",
16
+ };
17
+
18
+ // ─── Logging helpers ────────────────────────────────────────────────
19
+ export function logInfo(message) {
20
+ console.log(`${LOG_COLORS.blue}ℹ${LOG_COLORS.reset} ${message}`);
21
+ }
22
+
23
+ export function logSuccess(message) {
24
+ console.log(`${LOG_COLORS.green}✔${LOG_COLORS.reset} ${message}`);
25
+ }
26
+
27
+ export function logWarning(message) {
28
+ console.log(`${LOG_COLORS.yellow}⚠${LOG_COLORS.reset} ${message}`);
29
+ }
30
+
31
+ export function logError(message) {
32
+ console.error(`${LOG_COLORS.red}✖${LOG_COLORS.reset} ${message}`);
33
+ }
34
+
35
+ export function logStep(step_number, total, message) {
36
+ console.log(
37
+ `\n${LOG_COLORS.cyan}[${step_number}/${total}]${LOG_COLORS.reset} ${LOG_COLORS.bold}${message}${LOG_COLORS.reset}`
38
+ );
39
+ }
40
+
41
+ // ─── File system helpers ────────────────────────────────────────────
42
+ export function ensureDir(dir_path) {
43
+ if (!existsSync(dir_path)) {
44
+ mkdirSync(dir_path, { recursive: true });
45
+ }
46
+ }
47
+
48
+ export function copyDirRecursive(source, destination) {
49
+ ensureDir(destination);
50
+
51
+ const entries = readdirSync(source);
52
+ let copied_count = 0;
53
+
54
+ for (const entry of entries) {
55
+ const source_path = join(source, entry);
56
+ const dest_path = join(destination, entry);
57
+ const stat = statSync(source_path);
58
+
59
+ if (stat.isDirectory()) {
60
+ copied_count += copyDirRecursive(source_path, dest_path);
61
+ } else {
62
+ copyFileSync(source_path, dest_path);
63
+ copied_count++;
64
+ }
65
+ }
66
+
67
+ return copied_count;
68
+ }
69
+
70
+ export function cleanUp(temp_dir) {
71
+ if (existsSync(temp_dir)) {
72
+ rmSync(temp_dir, { recursive: true, force: true });
73
+ }
74
+ }
75
+
76
+ // ─── Git helpers ────────────────────────────────────────────────────
77
+ export function checkGitInstalled() {
78
+ try {
79
+ execSync("git --version", { stdio: "pipe" });
80
+ return true;
81
+ } catch {
82
+ return false;
83
+ }
84
+ }
85
+
86
+ export function cloneRepo({ repo_url, target_dir, branch }) {
87
+ execSync(
88
+ `git clone --depth 1 --branch ${branch} --single-branch "${repo_url}" "${target_dir}"`,
89
+ { stdio: "pipe" }
90
+ );
91
+ }