claudeboard 2.16.0 → 3.1.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.
package/bin/cli.js CHANGED
@@ -1,259 +1,219 @@
1
1
  #!/usr/bin/env node
2
+ // bin/cli.js
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+ const chalk = require('chalk');
6
+
7
+ const PKG_VERSION = '3.1.0';
8
+
9
+ // ─────────────────────────────────────────────────────────────────
10
+ // Helpers
11
+ // ─────────────────────────────────────────────────────────────────
12
+ function header(subtitle) {
13
+ console.log(chalk.bold.hex('#e3c69a')('ClaudeBoard v3 ✦') + (subtitle ? chalk.dim(' ' + subtitle) : ''));
14
+ console.log(chalk.dim('Visual orchestrator for Claude Code agent teams'));
15
+ console.log('');
16
+ }
2
17
 
3
- import { program } from "commander";
4
- import chalk from "chalk";
5
- import ora from "ora";
6
- import { fileURLToPath } from "url";
7
- import path from "path";
8
- import fs from "fs";
9
- import { spawn } from "child_process";
10
- import open from "open";
11
- import { createRequire } from "module";
12
-
13
- const _require = createRequire(import.meta.url);
14
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
- const _pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json"), "utf8"));
16
-
18
+ // ─────────────────────────────────────────────────────────────────
19
+ // claudeboard init
20
+ // ─────────────────────────────────────────────────────────────────
21
+ function runInit() {
22
+ header('init');
23
+
24
+ const cwd = process.cwd();
25
+ const boardDir = path.join(cwd, '.claudeboard');
26
+ const projectName = path.basename(cwd);
27
+
28
+ console.log(chalk.dim('Directorio: ') + chalk.cyan(cwd));
29
+ console.log('');
30
+
31
+ // 1. Create .claudeboard/
32
+ if (!fs.existsSync(boardDir)) {
33
+ fs.mkdirSync(boardDir, { recursive: true });
34
+ console.log(chalk.green('✔') + ' Carpeta .claudeboard/ creada');
35
+ } else {
36
+ console.log(chalk.yellow('~') + ' .claudeboard/ ya existe — no se sobreescribe');
37
+ }
17
38
 
18
- const LOGO = `
19
- ${chalk.cyan("╔════════════════════════════════════════════╗")}
20
- ${chalk.cyan("║")} ${chalk.bold.white("●")} ${chalk.bold.cyan("CLAUDEBOARD")} ${chalk.dim("powered by High Value, LLC")} ${chalk.cyan("║")}
21
- ${chalk.cyan("╚════════════════════════════════════════════╝")}
22
- `;
39
+ // 2. Write config.json only if missing
40
+ const configPath = path.join(boardDir, 'config.json');
41
+ if (!fs.existsSync(configPath)) {
42
+ fs.writeFileSync(configPath, JSON.stringify({ projectName, createdAt: new Date().toISOString() }, null, 2));
43
+ console.log(chalk.green('✔') + ' config.json inicializado');
44
+ }
23
45
 
24
- function loadConfig() {
46
+ // 3. Update .gitignore
47
+ const gitignorePath = path.join(cwd, '.gitignore');
48
+ const ignoreEntry = '.claudeboard/';
49
+ let gitignored = false;
25
50
  try {
26
- const config = JSON.parse(fs.readFileSync(path.join(process.cwd(), ".claudeboard.json"), "utf8"));
27
- // Inject API key into environment automatically
28
- if (config.anthropicKey) {
29
- process.env.ANTHROPIC_API_KEY = config.anthropicKey;
30
- }
31
- if (!process.env.ANTHROPIC_API_KEY) {
32
- console.log(chalk.yellow("⚠️ ANTHROPIC_API_KEY not found."));
33
- console.log(chalk.dim(" Run claudeboard init again, or: export ANTHROPIC_API_KEY=sk-ant-..."));
34
- process.exit(1);
51
+ if (fs.existsSync(gitignorePath)) {
52
+ const content = fs.readFileSync(gitignorePath, 'utf-8');
53
+ if (!content.includes(ignoreEntry)) {
54
+ fs.appendFileSync(gitignorePath, `\n# ClaudeBoard — datos del board (tareas, historial, handoffs)\n${ignoreEntry}\n`);
55
+ gitignored = true;
56
+ }
57
+ } else {
58
+ fs.writeFileSync(gitignorePath, `# ClaudeBoard — datos del board (tareas, historial, handoffs)\n${ignoreEntry}\n`);
59
+ gitignored = true;
35
60
  }
36
- return config;
37
- } catch {
38
- console.log(chalk.yellow("No .claudeboard.json found. Run: claudeboard init"));
39
- process.exit(1);
61
+ if (gitignored) console.log(chalk.green('✔') + ' .claudeboard/ agregado al .gitignore');
62
+ else console.log(chalk.yellow('~') + ' .gitignore ya incluye .claudeboard/');
63
+ } catch { /* non-fatal */ }
64
+
65
+ // 4. Create a starter context.md if missing
66
+ const contextPath = path.join(boardDir, 'context.md');
67
+ if (!fs.existsSync(contextPath)) {
68
+ fs.writeFileSync(contextPath, `# Guías de marca / contexto de "${projectName}"\n\n<!-- Opcional: agregá colores, tipografías, tono de voz, reglas del proyecto. -->\n<!-- Los agentes lo leerán antes de trabajar. -->\n`);
69
+ console.log(chalk.green('✔') + ' .claudeboard/context.md creado (editalo con tus guías de marca)');
40
70
  }
41
- }
42
-
43
- // ─── INIT ────────────────────────────────────────────────────────────────────
44
- program
45
- .command("init")
46
- .description("Initialize claudeboard in a project")
47
- .action(async () => {
48
- console.log(LOGO);
49
- const { default: Enquirer } = await import("enquirer");
50
- const enquirer = new Enquirer();
51
- console.log(chalk.bold("Let's set up your AI engineering team — powered by High Value, LLC.\n"));
52
-
53
- const answers = await enquirer.prompt([
54
- { type: "input", name: "projectName", message: "Project name:", initial: path.basename(process.cwd()) },
55
- {
56
- type: "select",
57
- name: "appType",
58
- message: "App type:",
59
- choices: ["mobile (Expo / React Native)", "web (Vite + React)"],
60
- },
61
- { type: "input", name: "supabaseUrl", message: "Supabase URL:", hint: "https://xxxx.supabase.co" },
62
- { type: "input", name: "supabaseKey", message: "Supabase anon key:" },
63
- { type: "password", name: "anthropicKey", message: "Anthropic API key:", hint: "sk-ant-..." },
64
- { type: "input", name: "port", message: "Dashboard port:", initial: "3131" },
65
- ]);
66
-
67
- const spinner = ora("Creating config...").start();
68
-
69
- const config = {
70
- projectName: answers.projectName,
71
- appType: answers.appType.startsWith("mobile") ? "mobile" : "web",
72
- port: parseInt(answers.port),
73
- supabaseUrl: answers.supabaseUrl,
74
- supabaseKey: answers.supabaseKey,
75
- anthropicKey: answers.anthropicKey,
76
- projectDir: process.cwd(),
77
- createdAt: new Date().toISOString(),
78
- };
79
-
80
- fs.writeFileSync(path.join(process.cwd(), ".claudeboard.json"), JSON.stringify(config, null, 2));
81
-
82
- const sqlSrc = path.join(__dirname, "../sql/setup.sql");
83
- fs.copyFileSync(sqlSrc, path.join(process.cwd(), "claudeboard-setup.sql"));
84
-
85
- spinner.succeed(chalk.green("Config created!"));
86
-
87
- console.log(`
88
- ${chalk.bold("Next steps:")}
89
-
90
- ${chalk.cyan("1.")} Run the SQL in your Supabase SQL Editor:
91
- ${chalk.dim("→ claudeboard-setup.sql")}
92
-
93
- ${chalk.cyan("2.")} Start the dashboard:
94
- ${chalk.bold("claudeboard start")}
95
-
96
- ${chalk.cyan("3.")} Run the AI team with your PRD:
97
- ${chalk.bold("claudeboard run --prd ./PRD.md --project ./your-app")}
98
- `);
99
- });
100
-
101
- // ─── START DASHBOARD ─────────────────────────────────────────────────────────
102
- program
103
- .command("start")
104
- .description("Start the dashboard server")
105
- .option("-p, --port <port>", "Port number")
106
- .action(async (opts) => {
107
- console.log(LOGO);
108
- const config = loadConfig();
109
- const port = opts.port || config.port || 3131;
110
- const spinner = ora("Starting dashboard...").start();
111
-
112
- const serverPath = path.join(__dirname, "../dashboard/server.js");
113
- const server = spawn("node", [serverPath], {
114
- env: {
115
- ...process.env,
116
- SUPABASE_URL: config.supabaseUrl,
117
- SUPABASE_KEY: config.supabaseKey,
118
- ANTHROPIC_API_KEY: config.anthropicKey || process.env.ANTHROPIC_API_KEY || "",
119
- PORT: String(port),
120
- PROJECT_NAME: config.projectName,
121
- PROJECT_DIR: config.projectDir || process.cwd(),
122
- },
123
- stdio: "pipe",
124
- });
125
-
126
- server.stdout.on("data", (data) => {
127
- if (data.toString().includes("READY")) {
128
- spinner.succeed(chalk.green("Dashboard running!"));
129
- console.log(`\n ${chalk.bold("→")} ${chalk.cyan(`http://localhost:${port}`)}\n`);
130
- console.log(chalk.dim(" Press Ctrl+C to stop\n"));
131
- open(`http://localhost:${port}`);
132
- }
133
- });
134
-
135
- server.stderr.on("data", (d) => console.error(chalk.red(d.toString())));
136
- process.on("SIGINT", () => { server.kill(); process.exit(0); });
137
- });
138
71
 
139
- // ─── RUN AI TEAM ─────────────────────────────────────────────────────────────
140
- program
141
- .command("run")
142
- .description("Run the AI engineering team on your project")
143
- .requiredOption("--prd <path>", "Path to PRD markdown file")
144
- .requiredOption("--project <path>", "Path to your app project directory")
145
- .option("--restart", "Force restart from scratch (ignore existing tasks in board)")
146
- .option("--expo-port <port>", "Expo Web port for QA screenshots", "8081")
147
- .option("--ios", "Use iOS Simulator instead of Expo Web for QA (requires Xcode)")
148
- .action(async (opts) => {
149
- console.log(LOGO);
150
- const config = loadConfig();
151
-
152
- if (!fs.existsSync(opts.prd)) {
153
- console.log(chalk.red(`PRD not found: ${opts.prd}`)); process.exit(1);
154
- }
155
- if (!fs.existsSync(opts.project)) {
156
- console.log(chalk.red(`Project not found: ${opts.project}`)); process.exit(1);
157
- }
72
+ console.log('');
73
+ console.log(chalk.bold('¡Listo! ') + chalk.dim('Corré ') + chalk.cyan('claudeboard') + chalk.dim(' para iniciar el board en este proyecto.'));
74
+ console.log('');
75
+ }
158
76
 
159
- console.log(chalk.bold(` AI Team starting for: ${chalk.cyan(config.projectName)}\n`));
160
- console.log(chalk.dim(` Dashboard http://localhost:${config.port}`));
161
- console.log(chalk.dim(` PRD → ${opts.prd}`));
162
- console.log(chalk.dim(` Project → ${opts.project}`));
163
- if (opts.restart) console.log(chalk.yellow(` Mode → FORCE RESTART\n`));
164
- else console.log(chalk.dim(` Mode → auto-resume if tasks exist\n`));
77
+ // ─────────────────────────────────────────────────────────────────
78
+ // Team selection prompt
79
+ // ─────────────────────────────────────────────────────────────────
80
+ const TEAMS = [
81
+ { label: '🧑‍💻 Solo Dev ', desc: '1 agente, enfocado, bajo costo de tokens', maxAgents: 1 },
82
+ { label: '👥 Small Team ', desc: '3 agentes (Lead + 2 especialistas)', maxAgents: 3 },
83
+ { label: '🚀 Full Team ', desc: '6 agentes (Lead + 5 especialistas)', maxAgents: 6 },
84
+ { label: '🏭 Enterprise ', desc: '9 agentes (Lead + 8 especialistas, máx paralelismo)', maxAgents: 9 },
85
+ ];
86
+
87
+ function drawMenu(teams, selected, lineCount) {
88
+ const lines = [chalk.bold('? ') + 'Seleccioná tu equipo de agentes:'];
89
+ for (let i = 0; i < teams.length; i++) {
90
+ const t = teams[i];
91
+ const cursor = i === selected ? chalk.cyan('❯') : ' ';
92
+ const label = i === selected ? chalk.bold(t.label) : chalk.dim(t.label);
93
+ lines.push(` ${cursor} ${label} ${chalk.dim(t.desc)}`);
94
+ }
95
+ if (lineCount > 0) process.stdout.write(`\x1b[${lineCount}A\x1b[0J`);
96
+ process.stdout.write(lines.join('\n') + '\n');
97
+ return lines.length;
98
+ }
165
99
 
166
- // ── Verify Claude Code CLI is installed ───────────────────────────────────
167
- const { execSync } = await import("child_process");
168
- const { resolveClaudePath, installHint } = await import("../agents/claude-resolver.js");
169
- const claudePath = resolveClaudePath();
170
- if (!claudePath) {
171
- console.log(chalk.red("\n ✗ Claude Code CLI not found!\n"));
172
- for (const line of installHint().split("\n")) {
173
- console.log(chalk.yellow(` ${line}`));
100
+ function promptTeamSelection(skipMaxAgents) {
101
+ if (skipMaxAgents !== undefined || !process.stdin.isTTY) return Promise.resolve(null);
102
+
103
+ return new Promise((resolve) => {
104
+ let selected = 0;
105
+ let lineCount = drawMenu(TEAMS, selected, 0);
106
+
107
+ process.stdin.setRawMode(true);
108
+ process.stdin.resume();
109
+ process.stdin.setEncoding('utf8');
110
+
111
+ function onKey(key) {
112
+ if (key === '\x1b[A') { selected = Math.max(0, selected - 1); lineCount = drawMenu(TEAMS, selected, lineCount); }
113
+ else if (key === '\x1b[B') { selected = Math.min(TEAMS.length - 1, selected + 1); lineCount = drawMenu(TEAMS, selected, lineCount); }
114
+ else if (key === '\r' || key === '\n') {
115
+ process.stdin.removeListener('data', onKey);
116
+ process.stdin.setRawMode(false);
117
+ process.stdin.pause();
118
+ process.stdout.write(`\x1b[${lineCount}A\x1b[0J`);
119
+ const team = TEAMS[selected];
120
+ process.stdout.write(chalk.bold('✔ ') + 'Equipo: ' + chalk.cyan(team.label.trim()) + chalk.dim(' — ' + team.desc) + '\n');
121
+ resolve(team);
122
+ } else if (key === '\x03') {
123
+ process.stdin.setRawMode(false);
124
+ process.exit(0);
174
125
  }
175
- console.log();
176
- process.exit(1);
177
126
  }
178
- try {
179
- const version = execSync(`"${claudePath}" --version`, { stdio: "pipe" }).toString().trim();
180
- console.log(chalk.dim(` Claude Code → ${version} (${claudePath})\n`));
181
- } catch {
182
- console.log(chalk.dim(` Claude Code → ${claudePath}\n`));
183
- }
184
-
185
- const resolvedProject = path.resolve(opts.project);
186
-
187
- // Persist the project path so `claudeboard start` uses the right directory for Expo
188
- const configPath = path.join(process.cwd(), ".claudeboard.json");
189
- try {
190
- const saved = JSON.parse(fs.readFileSync(configPath, "utf8"));
191
- saved.projectDir = resolvedProject;
192
- fs.writeFileSync(configPath, JSON.stringify(saved, null, 2));
193
- } catch {}
194
-
195
- const { runOrchestrator } = await import("../agents/orchestrator.js");
196
-
197
- await runOrchestrator({
198
- prdPath: path.resolve(opts.prd),
199
- projectPath: resolvedProject,
200
- supabaseUrl: config.supabaseUrl,
201
- supabaseKey: config.supabaseKey,
202
- projectName: config.projectName,
203
- appType: config.appType || "mobile",
204
- expoPort: parseInt(opts.expoPort),
205
- forceRestart: !!opts.restart,
206
- useIOS: !!opts.ios,
207
- });
127
+ process.stdin.on('data', onKey);
208
128
  });
129
+ }
209
130
 
210
- // ─── IMPORT PRD ──────────────────────────────────────────────────────────────
211
- program
212
- .command("import-prd <file>")
213
- .description("Parse PRD → create tasks in board (no agents run)")
214
- .action(async (file) => {
215
- console.log(LOGO);
216
- const config = loadConfig();
217
-
218
- if (!fs.existsSync(file)) {
219
- console.log(chalk.red(`File not found: ${file}`)); process.exit(1);
220
- }
221
-
222
- const prdContent = fs.readFileSync(file, "utf8");
223
- const { initBoard } = await import("../agents/board-client.js");
224
- const { runArchitectAgent } = await import("../agents/architect.js");
131
+ // ─────────────────────────────────────────────────────────────────
132
+ // claudeboard start (default when no subcommand)
133
+ // ─────────────────────────────────────────────────────────────────
134
+ async function runStart(rawArgs) {
135
+ // Parse simple flags: --port, --open, --webhook, --max-agents
136
+ const args = rawArgs || [];
137
+ const getFlag = (name, shortName, def) => {
138
+ const longIdx = args.indexOf(`--${name}`);
139
+ const shortIdx = shortName ? args.indexOf(`-${shortName}`) : -1;
140
+ const idx = longIdx !== -1 ? longIdx : shortIdx;
141
+ if (idx !== -1 && args[idx + 1] !== undefined) return args[idx + 1];
142
+ // --name=value form
143
+ const pair = args.find(a => a.startsWith(`--${name}=`));
144
+ if (pair) return pair.split('=')[1];
145
+ return def;
146
+ };
147
+ const flagExists = (name) => args.includes(`--${name}`);
148
+
149
+ const port = parseInt(getFlag('port', 'p', '3000'), 10) || 3000;
150
+ const openBrowser = getFlag('open', null, 'true') !== 'false';
151
+ const webhook = getFlag('webhook', null, null);
152
+ const maxAgentsRaw = getFlag('max-agents', null, undefined);
153
+
154
+ // ── Auto-init if .claudeboard/ doesn't exist ──────────────────
155
+ const cwd = process.cwd();
156
+ const boardDir = path.join(cwd, '.claudeboard');
157
+ if (!fs.existsSync(boardDir)) {
158
+ console.log(chalk.dim('No se encontró .claudeboard/ — inicializando automáticamente…'));
159
+ console.log('');
160
+ runInit();
161
+ }
225
162
 
226
- initBoard(config.supabaseUrl, config.supabaseKey, config.projectName);
227
- const result = await runArchitectAgent(prdContent, config.projectName);
163
+ header();
164
+ console.log(chalk.dim('Proyecto: ') + chalk.cyan(path.basename(cwd)) + chalk.dim(' (' + cwd + ')'));
165
+ console.log('');
228
166
 
229
- console.log(chalk.green(`\n Created ${result.totalTasks} tasks across ${result.epics.length} epics`));
230
- console.log(`\n Run ${chalk.bold("claudeboard start")} to see your board.\n`);
231
- });
167
+ const team = await promptTeamSelection(maxAgentsRaw);
168
+ const maxAgents = maxAgentsRaw !== undefined
169
+ ? (parseInt(maxAgentsRaw, 10) || 1)
170
+ : (team ? team.maxAgents : 1);
232
171
 
233
- // ─── STATUS ──────────────────────────────────────────────────────────────────
234
- program
235
- .command("status")
236
- .description("Show current board status in terminal")
237
- .action(async () => {
238
- const config = loadConfig();
239
- const { initBoard, getStats } = await import("../agents/board-client.js");
240
- initBoard(config.supabaseUrl, config.supabaseKey, config.projectName);
172
+ // Store minimal config (no projectPath — it's always process.cwd())
173
+ const { setConfig } = require(path.join(__dirname, '..', 'src', 'store'));
174
+ if (webhook) setConfig({ webhook });
241
175
 
242
- const stats = await getStats();
243
- const bar = "█".repeat(Math.floor(stats.pct / 5)) + "░".repeat(20 - Math.floor(stats.pct / 5));
176
+ console.log('');
177
+ console.log(chalk.dim(`Iniciando en puerto ${port}…`));
178
+ console.log('');
244
179
 
245
- console.log(LOGO);
246
- console.log(chalk.bold(` ${config.projectName}\n`));
247
- console.log(` [${chalk.green(bar)}] ${chalk.bold(stats.pct + "%")}`);
248
- console.log(`\n ${chalk.green("✓ Done:")} ${stats.done}`);
249
- console.log(` ${chalk.yellow("◌ Running:")} ${stats.in_progress}`);
250
- console.log(` ${chalk.dim("○ Todo:")} ${stats.todo}`);
251
- console.log(` ${chalk.red("✗ Error:")} ${stats.error}\n`);
252
- });
180
+ const { createServer } = require(path.join(__dirname, '..', 'src', 'server'));
181
+ createServer({ port, maxAgents, webhook, openBrowser });
253
182
 
254
- program
255
- .name("claudeboard")
256
- .description("AI engineering team — from PRD to working app, autonomously — powered by High Value, LLC")
257
- .version(_pkg.version);
183
+ console.log(chalk.dim('Ctrl+C para detener'));
184
+ }
258
185
 
259
- program.parse();
186
+ // ─────────────────────────────────────────────────────────────────
187
+ // Entry point — dispatch subcommand
188
+ // ─────────────────────────────────────────────────────────────────
189
+ const args = process.argv.slice(2);
190
+ const subcommand = args[0];
191
+
192
+ if (subcommand === '--version' || subcommand === '-v') {
193
+ console.log(PKG_VERSION);
194
+ } else if (subcommand === '--help' || subcommand === '-h') {
195
+ console.log(chalk.bold.hex('#e3c69a')('ClaudeBoard v3 ✦') + chalk.dim(' v' + PKG_VERSION));
196
+ console.log('');
197
+ console.log(chalk.bold('Uso:'));
198
+ console.log(' claudeboard init Inicializa .claudeboard/ en el proyecto actual');
199
+ console.log(' claudeboard Inicia el board (en el directorio actual)');
200
+ console.log('');
201
+ console.log(chalk.bold('Opciones de start:'));
202
+ console.log(' -p, --port <n> Puerto (default: 3000)');
203
+ console.log(' --max-agents <n> Cantidad de agentes paralelos (evita el prompt)');
204
+ console.log(' --open false No abrir el browser automáticamente');
205
+ console.log(' --webhook <url> URL de webhook para notificaciones');
206
+ console.log('');
207
+ console.log(chalk.bold('Ejemplo — múltiples proyectos en simultáneo:'));
208
+ console.log(chalk.dim(' cd ~/projects/app-a && claudeboard --port 3000'));
209
+ console.log(chalk.dim(' cd ~/projects/app-b && claudeboard --port 3001'));
210
+ } else if (subcommand === 'init') {
211
+ runInit();
212
+ } else if (!subcommand || subcommand === 'start' || subcommand.startsWith('-')) {
213
+ // No subcommand or "start" or flags → default to start
214
+ runStart(args.filter(a => a !== 'start'));
215
+ } else {
216
+ console.log(chalk.red(`Subcomando desconocido: "${subcommand}"`));
217
+ console.log(chalk.dim('Corré `claudeboard --help` para ver los comandos disponibles.'));
218
+ process.exit(1);
219
+ }
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ // bin/init-context.js — copies context template to .claudeboard/context.md in the current project
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const targetDir = path.join(process.cwd(), '.claudeboard');
7
+ const targetFile = path.join(targetDir, 'context.md');
8
+ const templateFile = path.join(__dirname, '..', 'src', 'context-template.md');
9
+
10
+ if (!fs.existsSync(targetDir)) {
11
+ fs.mkdirSync(targetDir, { recursive: true });
12
+ }
13
+
14
+ if (fs.existsSync(targetFile)) {
15
+ console.log(`Already exists: ${targetFile}`);
16
+ console.log('Edit it directly to customize your project context.');
17
+ process.exit(0);
18
+ }
19
+
20
+ fs.copyFileSync(templateFile, targetFile);
21
+ console.log(`Created: ${targetFile}`);
22
+ console.log('Edit .claudeboard/context.md to add your project brand guidelines and design tokens.');
package/package.json CHANGED
@@ -1,57 +1,39 @@
1
1
  {
2
2
  "name": "claudeboard",
3
- "version": "2.16.0",
4
- "description": "AI engineering team from PRD to working mobile app, autonomously",
5
- "type": "module",
3
+ "version": "3.1.1",
4
+ "description": "Visual orchestrator for Claude Code agent teams",
6
5
  "bin": {
7
- "claudeboard": "./bin/cli.js"
6
+ "claudeboard": "bin/cli.js"
8
7
  },
9
8
  "files": [
10
9
  "bin/",
11
- "dashboard/",
12
- "agents/",
13
- "tools/",
14
- "sql/",
10
+ "src/",
11
+ "public/",
15
12
  "README.md"
16
13
  ],
17
- "dependencies": {
18
- "@anthropic-ai/claude-agent-sdk": "latest",
19
- "@supabase/supabase-js": "^2.43.1",
20
- "chalk": "^5.3.0",
21
- "commander": "^12.0.0",
22
- "cors": "^2.8.5",
23
- "dotenv": "^16.4.5",
24
- "enquirer": "^2.4.1",
25
- "express": "^4.18.3",
26
- "node-pty": "^1.0.0",
27
- "open": "^10.1.0",
28
- "ora": "^8.0.1",
29
- "puppeteer": "^22.8.0",
30
- "ws": "^8.17.0"
31
- },
32
- "engines": {
33
- "node": ">=18.0.0"
34
- },
35
- "publishConfig": {
36
- "access": "public"
14
+ "scripts": {
15
+ "start": "node bin/cli.js"
37
16
  },
38
- "repository": {
39
- "type": "git",
40
- "url": "https://github.com/highvaluedigital/claudeboard"
41
- },
42
- "author": "highvaluedigital",
43
- "license": "MIT",
44
17
  "keywords": [
45
18
  "claude",
46
19
  "ai",
47
- "agent",
48
- "coding",
49
- "automation",
20
+ "orchestrator",
21
+ "agents",
50
22
  "dashboard",
51
- "mobile",
52
- "expo",
53
- "react-native",
54
- "prd",
55
- "engineering"
56
- ]
23
+ "kanban"
24
+ ],
25
+ "license": "MIT",
26
+ "engines": {
27
+ "node": ">=18"
28
+ },
29
+ "dependencies": {
30
+ "chalk": "^4.1.2",
31
+ "commander": "^12.0.0",
32
+ "express": "^4.18.2",
33
+ "open": "^10.1.0",
34
+ "ws": "^8.16.0"
35
+ },
36
+ "devDependencies": {
37
+ "supabase": "^2.78.1"
38
+ }
57
39
  }