specdacular 0.11.1 → 0.12.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/bin/specd.js CHANGED
@@ -2,12 +2,13 @@
2
2
 
3
3
  // bin/specd.js — unified CLI entry point
4
4
  // Usage:
5
- // specd llm-init [--local] — install commands/agents/workflows
6
- // specd runner launch Electron app
7
- // specd runner register <path> register a folder
8
- // specd runner unregister <id> remove a project
9
- // specd runner projects list projects
10
- // specd runner status show task status
5
+ // specd llm-init [--local] — install commands/agents/workflows
6
+ // specd install-runner install runner dependencies (express, ws, electron)
7
+ // specd runner launch Electron app
8
+ // specd runner register <path> register a folder
9
+ // specd runner unregister <id> remove a project
10
+ // specd runner projects list projects
11
+ // specd runner status — show task status
11
12
 
12
13
  import { resolve, join } from 'path';
13
14
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
@@ -17,6 +18,8 @@ import { execSync, spawn } from 'child_process';
17
18
  const args = process.argv.slice(2);
18
19
  const command = args[0];
19
20
 
21
+ const runnerDir = join(import.meta.dirname, '..', 'runner');
22
+
20
23
  function getAppDataDir() {
21
24
  if (platform() === 'darwin') {
22
25
  return join(homedir(), 'Library', 'Application Support', 'Specd');
@@ -40,12 +43,38 @@ function saveDb(data) {
40
43
  writeFileSync(dbPath, JSON.stringify(data, null, 2));
41
44
  }
42
45
 
46
+ function isRunnerInstalled() {
47
+ return existsSync(join(runnerDir, 'node_modules', 'express'));
48
+ }
49
+
50
+ function requireRunner() {
51
+ if (!isRunnerInstalled()) {
52
+ console.error('Runner dependencies not installed. Run: specd install-runner');
53
+ process.exit(1);
54
+ }
55
+ }
56
+
43
57
  if (command === 'llm-init') {
44
- // Delegate to existing install.js
45
58
  const installScript = join(import.meta.dirname, 'install.js');
46
59
  const isLocal = args.includes('--local');
47
60
  process.argv = ['node', installScript, isLocal ? '--local' : '--global'];
48
61
  await import(installScript);
62
+
63
+ } else if (command === 'install-runner') {
64
+ console.log('Installing runner dependencies...');
65
+ execSync('npm install --omit=dev', { cwd: runnerDir, stdio: 'inherit' });
66
+
67
+ // Also install renderer deps and build
68
+ const rendererDir = join(runnerDir, 'renderer');
69
+ if (existsSync(join(rendererDir, 'package.json'))) {
70
+ console.log('Installing renderer dependencies...');
71
+ execSync('npm install', { cwd: rendererDir, stdio: 'inherit' });
72
+ console.log('Building renderer...');
73
+ execSync('npm run build', { cwd: rendererDir, stdio: 'inherit' });
74
+ }
75
+
76
+ console.log('Runner installed. Run: specd runner');
77
+
49
78
  } else if (command === 'runner') {
50
79
  const subcommand = args[1];
51
80
 
@@ -105,16 +134,12 @@ if (command === 'llm-init') {
105
134
  }
106
135
  } else {
107
136
  // No subcommand — launch Electron app
108
- const runnerDir = join(import.meta.dirname, '..', 'runner');
109
- const electronPath = join(getAppDataDir(), 'electron', 'node_modules', '.bin', 'electron');
137
+ requireRunner();
110
138
 
139
+ const electronPath = join(runnerDir, 'node_modules', '.bin', 'electron');
111
140
  if (!existsSync(electronPath)) {
112
- console.log('First run installing Electron runtime...');
113
- const electronDir = join(getAppDataDir(), 'electron');
114
- mkdirSync(electronDir, { recursive: true });
115
- writeFileSync(join(electronDir, 'package.json'), JSON.stringify({ name: 'specd-electron', private: true }));
116
- execSync('npm install electron@latest', { cwd: electronDir, stdio: 'inherit' });
117
- console.log('Electron installed.');
141
+ console.error('Electron not installed. Run: specd install-runner');
142
+ process.exit(1);
118
143
  }
119
144
 
120
145
  const child = spawn(electronPath, [runnerDir], {
@@ -126,10 +151,11 @@ if (command === 'llm-init') {
126
151
  }
127
152
  } else {
128
153
  console.log('Usage:');
129
- console.log(' specd llm-init [--local] Install Claude Code commands/agents');
130
- console.log(' specd runner Launch the Specd Runner app');
131
- console.log(' specd runner register <path> Register a project folder');
132
- console.log(' specd runner unregister <id> Remove a project');
133
- console.log(' specd runner projects List registered projects');
134
- console.log(' specd runner status Show task status');
154
+ console.log(' specd llm-init [--local] Install Claude Code commands/agents');
155
+ console.log(' specd install-runner Install runner dependencies');
156
+ console.log(' specd runner Launch the Specd Runner app');
157
+ console.log(' specd runner register <path> Register a project folder');
158
+ console.log(' specd runner unregister <id> Remove a project');
159
+ console.log(' specd runner projects List registered projects');
160
+ console.log(' specd runner status Show task status');
135
161
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specdacular",
3
- "version": "0.11.1",
3
+ "version": "0.12.0",
4
4
  "description": "Feature planning system for existing codebases. Map, understand, and plan features in large projects.",
5
5
  "bin": {
6
6
  "specd": "bin/specd.js"
@@ -36,10 +36,6 @@
36
36
  "bugs": {
37
37
  "url": "https://github.com/victorbalan/specdacular/issues"
38
38
  },
39
- "dependencies": {
40
- "express": "^4.21.0",
41
- "ws": "^8.18.0"
42
- },
43
39
  "engines": {
44
40
  "node": ">=18"
45
41
  }
@@ -10,12 +10,10 @@
10
10
  "build:renderer": "cd renderer && npm run build"
11
11
  },
12
12
  "dependencies": {
13
+ "electron": "^34.0.0",
13
14
  "express": "^4.21.0",
14
15
  "ws": "^8.18.0"
15
16
  },
16
- "devDependencies": {
17
- "electron": "^34.0.0"
18
- },
19
17
  "engines": {
20
18
  "node": ">=18"
21
19
  }