squidsquad 0.15.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.
Files changed (3) hide show
  1. package/README.md +33 -0
  2. package/index.js +263 -0
  3. package/package.json +31 -0
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # squidsquad
2
+
3
+ Bootstrap [SquidSquad](https://github.com/WallyDoodlez/SquidSquad) onto your project.
4
+
5
+ SquidSquad is an autonomous AI dev team that coordinates through markdown, not meetings. It spins up Claude Code agents — one per dev role you define, plus PM and QA — that work on your codebase in parallel.
6
+
7
+ ## Usage
8
+
9
+ ```bash
10
+ npx squidsquad
11
+ ```
12
+
13
+ Run this from inside a git repository. The bootstrapper will:
14
+
15
+ 1. Verify prerequisites (Node.js 18+, Python 3.8+, GitHub CLI, Claude Code CLI)
16
+ 2. Fetch `SKILL.md` and the `/squidsquad-setup` command into your project
17
+ 3. Prompt to launch the setup wizard immediately
18
+
19
+ ## Prerequisites
20
+
21
+ - [Node.js 18+](https://nodejs.org/)
22
+ - [Python 3.8+](https://www.python.org/downloads/)
23
+ - [GitHub CLI (`gh`)](https://cli.github.com/) — authenticated
24
+ - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code/overview)
25
+ - A git repository
26
+
27
+ ## What It Does
28
+
29
+ The bootstrapper is intentionally thin. It checks your environment, seeds two files into your project (`SKILL.md` at the root and a `/squidsquad-setup` slash command), then offers to launch Claude Code to run the interactive setup wizard. The wizard handles everything else: project config, agent roles, boot scripts, GitHub Issues labels, and more.
30
+
31
+ ## License
32
+
33
+ [AGPL-3.0](https://github.com/WallyDoodlez/SquidSquad/blob/main/LICENSE)
package/index.js ADDED
@@ -0,0 +1,263 @@
1
+ #!/usr/bin/env node
2
+
3
+ "use strict";
4
+
5
+ const { execSync, spawn } = require("child_process");
6
+ const fs = require("fs");
7
+ const path = require("path");
8
+ const readline = require("readline");
9
+
10
+ const REPO_OWNER = "WallyDoodlez";
11
+ const REPO_NAME = "SquidSquad";
12
+ const BRANCH = "main";
13
+ const RAW_BASE = `https://raw.githubusercontent.com/${REPO_OWNER}/${REPO_NAME}/${BRANCH}`;
14
+
15
+ // --- Output helpers ---
16
+
17
+ function info(msg) {
18
+ console.log(` ${msg}`);
19
+ }
20
+
21
+ function success(msg) {
22
+ console.log(` \x1b[32m\u2713\x1b[0m ${msg}`);
23
+ }
24
+
25
+ function fail(msg) {
26
+ console.error(` \x1b[31m\u2717\x1b[0m ${msg}`);
27
+ }
28
+
29
+ function banner() {
30
+ console.log();
31
+ console.log(" \u2597\u2584\u2596");
32
+ console.log(" \u259F\u2588 \u2588\u2599");
33
+ console.log(" \u2590\u2588\u2022 \u2022\u2588\u258C");
34
+ console.log(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588");
35
+ console.log(" \u2590\u2588\u2588\u2588\u2588\u2588\u258C");
36
+ console.log(" \u2590\u258C\u2590\u258C\u2590\u258C");
37
+ console.log(" S Q U I D S Q U A D");
38
+ console.log();
39
+ }
40
+
41
+ // --- Prerequisite checks ---
42
+
43
+ function checkNodeVersion() {
44
+ const major = parseInt(process.versions.node.split(".")[0], 10);
45
+ if (major < 18) {
46
+ fail(`Node.js 18+ is required (found v${process.versions.node}).`);
47
+ info("Install the latest LTS from https://nodejs.org/");
48
+ process.exit(1);
49
+ }
50
+ success(`Node.js v${process.versions.node}`);
51
+ }
52
+
53
+ function tryExec(cmd) {
54
+ try {
55
+ return execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
56
+ } catch {
57
+ return null;
58
+ }
59
+ }
60
+
61
+ function checkGitRepo() {
62
+ const root = tryExec("git rev-parse --show-toplevel");
63
+ if (!root) {
64
+ fail("Not a git repository.");
65
+ info("Run this command from inside a git repository.");
66
+ process.exit(1);
67
+ }
68
+ success("Git repository detected");
69
+ return root;
70
+ }
71
+
72
+ function checkPython() {
73
+ for (const bin of ["python3", "python"]) {
74
+ const out = tryExec(`${bin} --version`);
75
+ if (out) {
76
+ const match = out.match(/Python (\d+)\.(\d+)/);
77
+ if (match) {
78
+ const major = parseInt(match[1], 10);
79
+ const minor = parseInt(match[2], 10);
80
+ if ((major === 3 && minor >= 8) || major > 3) {
81
+ success(`${out}`);
82
+ return;
83
+ }
84
+ }
85
+ }
86
+ }
87
+ fail("Python 3.8+ is required.");
88
+ info("Install from https://www.python.org/downloads/");
89
+ process.exit(1);
90
+ }
91
+
92
+ function checkGhCli() {
93
+ const ver = tryExec("gh --version");
94
+ if (!ver) {
95
+ fail("GitHub CLI (gh) is required.");
96
+ info("Install from https://cli.github.com/");
97
+ process.exit(1);
98
+ }
99
+ success("GitHub CLI installed");
100
+
101
+ try {
102
+ execSync("gh auth status", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
103
+ success("GitHub CLI authenticated");
104
+ } catch {
105
+ fail("GitHub CLI is not authenticated.");
106
+ info("Run `gh auth login` first.");
107
+ process.exit(1);
108
+ }
109
+ }
110
+
111
+ function checkClaudeCli() {
112
+ const ver = tryExec("claude --version");
113
+ if (!ver) {
114
+ fail("Claude Code CLI is required.");
115
+ info("Install from https://docs.anthropic.com/en/docs/claude-code/overview");
116
+ process.exit(1);
117
+ }
118
+ success(`Claude Code CLI v${ver}`);
119
+ }
120
+
121
+ // --- File fetching ---
122
+
123
+ function fetchRawFile(repoPath) {
124
+ const url = `${RAW_BASE}/${repoPath}`;
125
+ try {
126
+ const content = execSync(
127
+ `gh api -H "Accept: application/vnd.github.raw+json" "/repos/${REPO_OWNER}/${REPO_NAME}/contents/${repoPath}?ref=${BRANCH}"`,
128
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], maxBuffer: 1024 * 1024 }
129
+ );
130
+ return content;
131
+ } catch {
132
+ // Fallback: try curl/wget for raw URL
133
+ const fallback = tryExec(`curl -fsSL "${url}"`);
134
+ if (fallback) return fallback;
135
+ return null;
136
+ }
137
+ }
138
+
139
+ function installFiles(gitRoot) {
140
+ // 1. Fetch SKILL.md → project root
141
+ info("Fetching SKILL.md...");
142
+ const skillContent = fetchRawFile("SKILL.md");
143
+ if (!skillContent) {
144
+ fail("Failed to fetch SKILL.md from GitHub.");
145
+ process.exit(1);
146
+ }
147
+ fs.writeFileSync(path.join(gitRoot, "SKILL.md"), skillContent, "utf-8");
148
+ success("SKILL.md placed in project root");
149
+
150
+ // 2. Create .claude/commands/ and fetch squidsquad-setup.md
151
+ const commandsDir = path.join(gitRoot, ".claude", "commands");
152
+ fs.mkdirSync(commandsDir, { recursive: true });
153
+
154
+ // The setup command tells Claude to read SKILL.md and run setup
155
+ const setupCommand = [
156
+ "---",
157
+ "description: Run the SquidSquad setup wizard to configure your project",
158
+ "---",
159
+ "",
160
+ 'Read the SKILL.md file in the project root and follow its "Setup Instructions" section exactly.',
161
+ "",
162
+ "The setup wizard will ask for project details, generate the .squidsquad/ folder, create agent configs, boot scripts, and GitHub Issues labels.",
163
+ "",
164
+ "Important: The setup flow will need to fetch files from the SquidSquad repo. Use `gh api` or `curl` to download from https://raw.githubusercontent.com/WallyDoodlez/SquidSquad/main/ as needed.",
165
+ "",
166
+ ].join("\n");
167
+
168
+ fs.writeFileSync(path.join(commandsDir, "squidsquad-setup.md"), setupCommand, "utf-8");
169
+ success("Created /squidsquad-setup command");
170
+ }
171
+
172
+ // --- Launch prompt ---
173
+
174
+ function askLaunch() {
175
+ return new Promise((resolve) => {
176
+ const rl = readline.createInterface({
177
+ input: process.stdin,
178
+ output: process.stdout,
179
+ });
180
+ rl.question(" Launch SquidSquad setup now? (Y/n) ", (answer) => {
181
+ rl.close();
182
+ const trimmed = answer.trim().toLowerCase();
183
+ resolve(trimmed === "" || trimmed === "y" || trimmed === "yes");
184
+ });
185
+ });
186
+ }
187
+
188
+ function launchClaude() {
189
+ info("Launching Claude Code with /squidsquad-setup...");
190
+ console.log();
191
+
192
+ const child = spawn("claude", ["/squidsquad-setup"], {
193
+ stdio: "inherit",
194
+ shell: true,
195
+ });
196
+
197
+ child.on("error", (err) => {
198
+ fail(`Failed to launch Claude: ${err.message}`);
199
+ info("Run manually: claude /squidsquad-setup");
200
+ process.exit(1);
201
+ });
202
+
203
+ child.on("exit", (code) => {
204
+ process.exit(code || 0);
205
+ });
206
+ }
207
+
208
+ // --- Main ---
209
+
210
+ async function main() {
211
+ banner();
212
+
213
+ // Check if already set up in this project
214
+ const gitRoot = checkGitRepo();
215
+ const squidDir = path.join(gitRoot, ".squidsquad");
216
+ if (fs.existsSync(squidDir)) {
217
+ console.log();
218
+ info("SquidSquad is already installed in this project.");
219
+ info("To upgrade, run `/squidsquad-upgrade` from a Claude session.");
220
+ console.log();
221
+ process.exit(0);
222
+ }
223
+
224
+ console.log();
225
+ info("Checking prerequisites...");
226
+ console.log();
227
+
228
+ checkNodeVersion();
229
+ checkPython();
230
+ checkGhCli();
231
+ checkClaudeCli();
232
+
233
+ console.log();
234
+ info("All prerequisites met. Fetching SquidSquad files...");
235
+ console.log();
236
+
237
+ try {
238
+ installFiles(gitRoot);
239
+ } catch (err) {
240
+ console.log();
241
+ fail("Installation failed.");
242
+ info(err.message || String(err));
243
+ process.exit(1);
244
+ }
245
+
246
+ console.log();
247
+ console.log(" \x1b[32m\x1b[1mSquidSquad is ready!\x1b[0m");
248
+ console.log();
249
+
250
+ const shouldLaunch = await askLaunch();
251
+
252
+ if (shouldLaunch) {
253
+ launchClaude();
254
+ } else {
255
+ console.log();
256
+ info("To set up later, run:");
257
+ console.log();
258
+ info(" claude /squidsquad-setup");
259
+ console.log();
260
+ }
261
+ }
262
+
263
+ main();
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "squidsquad",
3
+ "version": "0.15.0",
4
+ "description": "Bootstrap SquidSquad onto your project — autonomous AI dev team coordination via Claude Code",
5
+ "bin": {
6
+ "squidsquad": "./index.js"
7
+ },
8
+ "engines": {
9
+ "node": ">=18"
10
+ },
11
+ "files": [
12
+ "index.js"
13
+ ],
14
+ "keywords": [
15
+ "claude",
16
+ "claude-code",
17
+ "ai",
18
+ "agents",
19
+ "dev-team",
20
+ "autonomous",
21
+ "squidsquad"
22
+ ],
23
+ "license": "AGPL-3.0",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/WallyDoodlez/SquidSquad.git",
27
+ "directory": "packages/cli"
28
+ },
29
+ "homepage": "https://github.com/WallyDoodlez/SquidSquad",
30
+ "author": "WallyDoodlez"
31
+ }