@faviovazquez/deliberate 0.1.0 → 0.2.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/CHANGELOG.md +12 -0
- package/bin/cli.js +358 -45
- package/package.json +1 -1
- package/scripts/release.sh +0 -131
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.0] - 2025-04-03
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Rewrote installer as pure Node.js (no bash dependency required)
|
|
12
|
+
- Blue ASCII "DELIBERATE" banner with professional CLI styling
|
|
13
|
+
- Interactive prompts: platform selection with auto-detection, global/local scope choice
|
|
14
|
+
- Clean ✓ checkmark output with colored status lines
|
|
15
|
+
- Platform flags: --claude, --windsurf, --cursor, --all
|
|
16
|
+
- Scope flags: --global/-g, --local/-l
|
|
17
|
+
- Added --dry-run preview, --uninstall support
|
|
18
|
+
- Moved release.sh to repo root (dev-only, excluded from npm package)
|
|
19
|
+
|
|
8
20
|
## [0.1.0] - 2025-04-03
|
|
9
21
|
|
|
10
22
|
### Added
|
package/bin/cli.js
CHANGED
|
@@ -2,68 +2,381 @@
|
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
const { execSync, spawn } = require('child_process');
|
|
6
|
-
const path = require('path');
|
|
7
5
|
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const readline = require('readline');
|
|
8
9
|
|
|
9
10
|
const ROOT = path.resolve(__dirname, '..');
|
|
10
|
-
const
|
|
11
|
+
const pkg = require(path.join(ROOT, 'package.json'));
|
|
11
12
|
|
|
13
|
+
// ─── Colors ────────────────────────────────────────────────────────────────
|
|
14
|
+
const blue = '\x1b[38;5;33m';
|
|
15
|
+
const cyan = '\x1b[36m';
|
|
16
|
+
const green = '\x1b[32m';
|
|
17
|
+
const yellow = '\x1b[33m';
|
|
18
|
+
const dim = '\x1b[2m';
|
|
19
|
+
const bold = '\x1b[1m';
|
|
20
|
+
const reset = '\x1b[0m';
|
|
21
|
+
|
|
22
|
+
// ─── Argument parsing ──────────────────────────────────────────────────────
|
|
12
23
|
const args = process.argv.slice(2);
|
|
24
|
+
const hasClaude = args.includes('--claude') || args.includes('--claude-code');
|
|
25
|
+
const hasWindsurf = args.includes('--windsurf');
|
|
26
|
+
const hasCursor = args.includes('--cursor');
|
|
27
|
+
const hasAll = args.includes('--all');
|
|
28
|
+
const hasGlobal = args.includes('--global') || args.includes('-g');
|
|
29
|
+
const hasLocal = args.includes('--local') || args.includes('-l');
|
|
30
|
+
const hasDryRun = args.includes('--dry-run');
|
|
31
|
+
const hasHelp = args.includes('--help') || args.includes('-h');
|
|
32
|
+
const hasUninstall = args.includes('--uninstall') || args.includes('-u');
|
|
33
|
+
|
|
34
|
+
let selectedPlatforms = [];
|
|
35
|
+
if (hasAll) selectedPlatforms = ['claude-code', 'windsurf'];
|
|
36
|
+
if (hasClaude) selectedPlatforms.push('claude-code');
|
|
37
|
+
if (hasWindsurf) selectedPlatforms.push('windsurf');
|
|
38
|
+
if (hasCursor) selectedPlatforms.push('cursor');
|
|
39
|
+
|
|
40
|
+
// ─── Banner ────────────────────────────────────────────────────────────────
|
|
41
|
+
const banner = `
|
|
42
|
+
${blue} ██████╗ ███████╗██╗ ██╗██████╗ ███████╗██████╗ █████╗ ████████╗███████╗
|
|
43
|
+
██╔══██╗██╔════╝██║ ██║██╔══██╗██╔════╝██╔══██╗██╔══██╗╚══██╔══╝██╔════╝
|
|
44
|
+
██║ ██║█████╗ ██║ ██║██████╔╝█████╗ ██████╔╝███████║ ██║ █████╗
|
|
45
|
+
██║ ██║██╔══╝ ██║ ██║██╔══██╗██╔══╝ ██╔══██╗██╔══██║ ██║ ██╔══╝
|
|
46
|
+
██████╔╝███████╗███████╗██║██████╔╝███████╗██║ ██║██║ ██║ ██║ ███████╗
|
|
47
|
+
╚═════╝ ╚══════╝╚══════╝╚═╝╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚══════╝${reset}
|
|
48
|
+
|
|
49
|
+
${dim}Agreement is a bug.${reset}
|
|
50
|
+
${dim}v${pkg.version} · Multi-agent deliberation for AI coding assistants${reset}
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
// ─── Help text ─────────────────────────────────────────────────────────────
|
|
54
|
+
const helpText = `
|
|
55
|
+
${yellow}Usage:${reset} npx @faviovazquez/deliberate [platform] [scope] [options]
|
|
56
|
+
|
|
57
|
+
${yellow}Platforms:${reset}
|
|
58
|
+
${cyan}--claude${reset} Claude Code (~/.claude/)
|
|
59
|
+
${cyan}--windsurf${reset} Windsurf (~/.codeium/windsurf/)
|
|
60
|
+
${cyan}--cursor${reset} Cursor (.cursor/skills/)
|
|
61
|
+
${cyan}--all${reset} All detected platforms
|
|
13
62
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Agreement is a bug.
|
|
63
|
+
${yellow}Scope:${reset}
|
|
64
|
+
${cyan}-g, --global${reset} Install to global config directory (recommended)
|
|
65
|
+
${cyan}-l, --local${reset} Install to current project directory
|
|
18
66
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
npx @faviovazquez/deliberate --help Show this help
|
|
67
|
+
${yellow}Options:${reset}
|
|
68
|
+
${cyan}--dry-run${reset} Preview without installing
|
|
69
|
+
${cyan}-u, --uninstall${reset} Remove deliberate files
|
|
70
|
+
${cyan}-h, --help${reset} Show this help
|
|
24
71
|
|
|
25
|
-
|
|
72
|
+
${yellow}Examples:${reset}
|
|
73
|
+
${dim}# Interactive install (prompts for platform and scope)${reset}
|
|
74
|
+
npx @faviovazquez/deliberate
|
|
26
75
|
|
|
27
|
-
|
|
28
|
-
/deliberate
|
|
76
|
+
${dim}# Install for Claude Code globally${reset}
|
|
77
|
+
npx @faviovazquez/deliberate --claude --global
|
|
29
78
|
|
|
30
|
-
|
|
31
|
-
|
|
79
|
+
${dim}# Install for all platforms globally${reset}
|
|
80
|
+
npx @faviovazquez/deliberate --all --global
|
|
81
|
+
|
|
82
|
+
${dim}# Preview installation${reset}
|
|
83
|
+
npx @faviovazquez/deliberate --claude --global --dry-run
|
|
84
|
+
`;
|
|
85
|
+
|
|
86
|
+
// ─── Path helpers ──────────────────────────────────────────────────────────
|
|
87
|
+
function getGlobalDir(platform) {
|
|
88
|
+
switch (platform) {
|
|
89
|
+
case 'claude-code': return path.join(os.homedir(), '.claude');
|
|
90
|
+
case 'windsurf': return path.join(os.homedir(), '.codeium', 'windsurf');
|
|
91
|
+
case 'cursor': return path.join(process.cwd(), '.cursor');
|
|
92
|
+
default: return path.join(os.homedir(), '.claude');
|
|
93
|
+
}
|
|
32
94
|
}
|
|
33
95
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
96
|
+
function getLocalDir(platform) {
|
|
97
|
+
switch (platform) {
|
|
98
|
+
case 'claude-code': return path.join(process.cwd(), '.claude');
|
|
99
|
+
case 'windsurf': return path.join(process.cwd(), '.windsurf');
|
|
100
|
+
case 'cursor': return path.join(process.cwd(), '.cursor');
|
|
101
|
+
default: return path.join(process.cwd(), '.claude');
|
|
102
|
+
}
|
|
37
103
|
}
|
|
38
104
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
console.log(' Agreement is a bug.');
|
|
43
|
-
console.log('');
|
|
44
|
-
|
|
45
|
-
// Check for bash
|
|
46
|
-
try {
|
|
47
|
-
execSync('which bash', { stdio: 'pipe' });
|
|
48
|
-
} catch (e) {
|
|
49
|
-
console.error('Error: bash is required. Please install bash and try again.');
|
|
50
|
-
process.exit(1);
|
|
105
|
+
function getPlatformLabel(platform) {
|
|
106
|
+
const labels = { 'claude-code': 'Claude Code', 'windsurf': 'Windsurf', 'cursor': 'Cursor' };
|
|
107
|
+
return labels[platform] || platform;
|
|
51
108
|
}
|
|
52
109
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
fs.chmodSync(INSTALL_SCRIPT, '755');
|
|
56
|
-
} catch (e) {
|
|
57
|
-
// May already be executable
|
|
110
|
+
function tildePath(p) {
|
|
111
|
+
return p.replace(os.homedir(), '~');
|
|
58
112
|
}
|
|
59
113
|
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
});
|
|
114
|
+
// ─── File copy ─────────────────────────────────────────────────────────────
|
|
115
|
+
let fileCount = 0;
|
|
116
|
+
|
|
117
|
+
function copyFile(src, dest) {
|
|
118
|
+
if (hasDryRun) {
|
|
119
|
+
console.log(` ${dim}(dry-run)${reset} ${tildePath(dest)}`);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
123
|
+
fs.copyFileSync(src, dest);
|
|
124
|
+
fileCount++;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function copyDir(srcDir, destDir) {
|
|
128
|
+
if (!fs.existsSync(srcDir)) return;
|
|
129
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
130
|
+
const src = path.join(srcDir, entry.name);
|
|
131
|
+
const dest = path.join(destDir, entry.name);
|
|
132
|
+
if (entry.isDirectory()) {
|
|
133
|
+
copyDir(src, dest);
|
|
134
|
+
} else {
|
|
135
|
+
copyFile(src, dest);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function makeExecutable(filePath) {
|
|
141
|
+
if (hasDryRun || !fs.existsSync(filePath)) return;
|
|
142
|
+
try { fs.chmodSync(filePath, '755'); } catch { /* ignore */ }
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ─── Install functions ─────────────────────────────────────────────────────
|
|
146
|
+
function installClaudeCode(isGlobal) {
|
|
147
|
+
const baseDir = isGlobal ? getGlobalDir('claude-code') : getLocalDir('claude-code');
|
|
148
|
+
const agentsDir = path.join(baseDir, 'agents');
|
|
149
|
+
const skillDir = path.join(baseDir, 'skills', 'deliberate');
|
|
150
|
+
const locationLabel = tildePath(baseDir);
|
|
151
|
+
|
|
152
|
+
console.log(`\n Installing for ${cyan}Claude Code${reset} → ${cyan}${locationLabel}${reset}\n`);
|
|
153
|
+
|
|
154
|
+
// Core agents
|
|
155
|
+
const agentsSrc = path.join(ROOT, 'agents');
|
|
156
|
+
for (const f of fs.readdirSync(agentsSrc)) {
|
|
157
|
+
if (!f.endsWith('.md')) continue;
|
|
158
|
+
copyFile(path.join(agentsSrc, f), path.join(agentsDir, `deliberate-${f}`));
|
|
159
|
+
}
|
|
160
|
+
// Specialist agents
|
|
161
|
+
const specSrc = path.join(agentsSrc, 'specialists');
|
|
162
|
+
if (fs.existsSync(specSrc)) {
|
|
163
|
+
for (const f of fs.readdirSync(specSrc)) {
|
|
164
|
+
if (!f.endsWith('.md')) continue;
|
|
165
|
+
copyFile(path.join(specSrc, f), path.join(agentsDir, `deliberate-${f}`));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
console.log(` ${green}✓${reset} Installed 17 agents to ${tildePath(agentsDir)}/`);
|
|
169
|
+
|
|
170
|
+
// Skill protocol
|
|
171
|
+
copyFile(path.join(ROOT, 'SKILL.md'), path.join(skillDir, 'SKILL.md'));
|
|
172
|
+
copyFile(path.join(ROOT, 'BRAINSTORM.md'), path.join(skillDir, 'BRAINSTORM.md'));
|
|
173
|
+
console.log(` ${green}✓${reset} Installed skill protocol to ${tildePath(skillDir)}/`);
|
|
174
|
+
|
|
175
|
+
// Configs
|
|
176
|
+
copyDir(path.join(ROOT, 'configs'), path.join(skillDir, 'configs'));
|
|
177
|
+
console.log(` ${green}✓${reset} Installed configs`);
|
|
178
|
+
|
|
179
|
+
// Scripts
|
|
180
|
+
copyDir(path.join(ROOT, 'scripts'), path.join(skillDir, 'scripts'));
|
|
181
|
+
makeExecutable(path.join(skillDir, 'scripts', 'start-server.sh'));
|
|
182
|
+
makeExecutable(path.join(skillDir, 'scripts', 'stop-server.sh'));
|
|
183
|
+
makeExecutable(path.join(skillDir, 'scripts', 'detect-platform.sh'));
|
|
184
|
+
console.log(` ${green}✓${reset} Installed visual companion scripts`);
|
|
185
|
+
|
|
186
|
+
// Templates
|
|
187
|
+
copyDir(path.join(ROOT, 'templates'), path.join(skillDir, 'templates'));
|
|
188
|
+
console.log(` ${green}✓${reset} Installed output templates`);
|
|
189
|
+
|
|
190
|
+
console.log(`\n ${green}Done!${reset} Open Claude Code and try: ${cyan}/deliberate "your question here"${reset}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function installWindsurf(isGlobal) {
|
|
194
|
+
const baseDir = isGlobal ? getGlobalDir('windsurf') : getLocalDir('windsurf');
|
|
195
|
+
const skillDir = path.join(baseDir, 'skills', 'deliberate');
|
|
196
|
+
const locationLabel = tildePath(skillDir);
|
|
197
|
+
|
|
198
|
+
console.log(`\n Installing for ${cyan}Windsurf${reset} → ${cyan}${locationLabel}${reset}\n`);
|
|
199
|
+
|
|
200
|
+
// Skill protocol
|
|
201
|
+
copyFile(path.join(ROOT, 'SKILL.md'), path.join(skillDir, 'SKILL.md'));
|
|
202
|
+
copyFile(path.join(ROOT, 'BRAINSTORM.md'), path.join(skillDir, 'BRAINSTORM.md'));
|
|
203
|
+
console.log(` ${green}✓${reset} Installed skill protocol`);
|
|
204
|
+
|
|
205
|
+
// Agents (bundled with skill)
|
|
206
|
+
copyDir(path.join(ROOT, 'agents'), path.join(skillDir, 'agents'));
|
|
207
|
+
console.log(` ${green}✓${reset} Installed 17 agents`);
|
|
208
|
+
|
|
209
|
+
// Configs, Scripts, Templates
|
|
210
|
+
copyDir(path.join(ROOT, 'configs'), path.join(skillDir, 'configs'));
|
|
211
|
+
copyDir(path.join(ROOT, 'scripts'), path.join(skillDir, 'scripts'));
|
|
212
|
+
copyDir(path.join(ROOT, 'templates'), path.join(skillDir, 'templates'));
|
|
213
|
+
makeExecutable(path.join(skillDir, 'scripts', 'start-server.sh'));
|
|
214
|
+
makeExecutable(path.join(skillDir, 'scripts', 'stop-server.sh'));
|
|
215
|
+
makeExecutable(path.join(skillDir, 'scripts', 'detect-platform.sh'));
|
|
216
|
+
console.log(` ${green}✓${reset} Installed configs, scripts, templates`);
|
|
66
217
|
|
|
67
|
-
|
|
68
|
-
|
|
218
|
+
console.log(`\n ${green}Done!${reset} Open Windsurf and try: ${cyan}@deliberate${reset} or just ask a complex decision question.`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function installCursor(isGlobal) {
|
|
222
|
+
// Cursor is always workspace-local
|
|
223
|
+
const skillDir = path.join(process.cwd(), '.cursor', 'skills', 'deliberate');
|
|
224
|
+
const locationLabel = tildePath(skillDir);
|
|
225
|
+
|
|
226
|
+
console.log(`\n Installing for ${cyan}Cursor${reset} → ${cyan}${locationLabel}${reset}\n`);
|
|
227
|
+
|
|
228
|
+
copyFile(path.join(ROOT, 'SKILL.md'), path.join(skillDir, 'SKILL.md'));
|
|
229
|
+
copyFile(path.join(ROOT, 'BRAINSTORM.md'), path.join(skillDir, 'BRAINSTORM.md'));
|
|
230
|
+
copyDir(path.join(ROOT, 'agents'), path.join(skillDir, 'agents'));
|
|
231
|
+
copyDir(path.join(ROOT, 'configs'), path.join(skillDir, 'configs'));
|
|
232
|
+
copyDir(path.join(ROOT, 'scripts'), path.join(skillDir, 'scripts'));
|
|
233
|
+
copyDir(path.join(ROOT, 'templates'), path.join(skillDir, 'templates'));
|
|
234
|
+
makeExecutable(path.join(skillDir, 'scripts', 'start-server.sh'));
|
|
235
|
+
makeExecutable(path.join(skillDir, 'scripts', 'stop-server.sh'));
|
|
236
|
+
makeExecutable(path.join(skillDir, 'scripts', 'detect-platform.sh'));
|
|
237
|
+
console.log(` ${green}✓${reset} Installed skill, agents, configs, scripts, templates`);
|
|
238
|
+
|
|
239
|
+
console.log(`\n ${green}Done!${reset} Open Cursor and try: ${cyan}@deliberate${reset} or just ask a complex decision question.`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ─── Uninstall ─────────────────────────────────────────────────────────────
|
|
243
|
+
function uninstall(platform, isGlobal) {
|
|
244
|
+
const label = getPlatformLabel(platform);
|
|
245
|
+
let removed = 0;
|
|
246
|
+
|
|
247
|
+
if (platform === 'claude-code') {
|
|
248
|
+
const baseDir = isGlobal ? getGlobalDir('claude-code') : getLocalDir('claude-code');
|
|
249
|
+
console.log(`\n Uninstalling from ${cyan}${label}${reset} at ${cyan}${tildePath(baseDir)}${reset}\n`);
|
|
250
|
+
|
|
251
|
+
// Remove agents
|
|
252
|
+
const agentsDir = path.join(baseDir, 'agents');
|
|
253
|
+
if (fs.existsSync(agentsDir)) {
|
|
254
|
+
for (const f of fs.readdirSync(agentsDir)) {
|
|
255
|
+
if (f.startsWith('deliberate-') && f.endsWith('.md')) {
|
|
256
|
+
fs.unlinkSync(path.join(agentsDir, f)); removed++;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (removed > 0) console.log(` ${green}✓${reset} Removed ${removed} agent files`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Remove skill dir
|
|
263
|
+
const skillDir = path.join(baseDir, 'skills', 'deliberate');
|
|
264
|
+
if (fs.existsSync(skillDir)) {
|
|
265
|
+
fs.rmSync(skillDir, { recursive: true });
|
|
266
|
+
console.log(` ${green}✓${reset} Removed skills/deliberate/`);
|
|
267
|
+
removed++;
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
const baseDir = platform === 'windsurf'
|
|
271
|
+
? (isGlobal ? getGlobalDir('windsurf') : getLocalDir('windsurf'))
|
|
272
|
+
: path.join(process.cwd(), '.cursor');
|
|
273
|
+
const skillDir = path.join(baseDir, 'skills', 'deliberate');
|
|
274
|
+
console.log(`\n Uninstalling from ${cyan}${label}${reset} at ${cyan}${tildePath(skillDir)}${reset}\n`);
|
|
275
|
+
|
|
276
|
+
if (fs.existsSync(skillDir)) {
|
|
277
|
+
fs.rmSync(skillDir, { recursive: true });
|
|
278
|
+
console.log(` ${green}✓${reset} Removed skills/deliberate/`);
|
|
279
|
+
removed++;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (removed === 0) console.log(` ${yellow}⚠${reset} No deliberate files found.`);
|
|
284
|
+
else console.log(`\n ${green}Done!${reset} deliberate uninstalled from ${label}.`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ─── Detect platforms ──────────────────────────────────────────────────────
|
|
288
|
+
function detectPlatforms() {
|
|
289
|
+
const detected = [];
|
|
290
|
+
if (fs.existsSync(path.join(os.homedir(), '.claude'))) detected.push('claude-code');
|
|
291
|
+
if (fs.existsSync(path.join(os.homedir(), '.codeium', 'windsurf'))) detected.push('windsurf');
|
|
292
|
+
if (fs.existsSync(path.join(process.cwd(), '.windsurf'))) {
|
|
293
|
+
if (!detected.includes('windsurf')) detected.push('windsurf');
|
|
294
|
+
}
|
|
295
|
+
if (fs.existsSync(path.join(process.cwd(), '.cursor'))) detected.push('cursor');
|
|
296
|
+
return detected;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// ─── Interactive prompt ────────────────────────────────────────────────────
|
|
300
|
+
async function promptUser() {
|
|
301
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
302
|
+
const ask = (q) => new Promise(resolve => rl.question(q, resolve));
|
|
303
|
+
|
|
304
|
+
const detected = detectPlatforms();
|
|
305
|
+
|
|
306
|
+
console.log(` ${yellow}Select platform:${reset}`);
|
|
307
|
+
console.log(` 1) Claude Code ${dim}(${detected.includes('claude-code') ? green + 'detected' + reset : dim + 'not detected' + reset}${dim})${reset}`);
|
|
308
|
+
console.log(` 2) Windsurf ${dim}(${detected.includes('windsurf') ? green + 'detected' + reset : dim + 'not detected' + reset}${dim})${reset}`);
|
|
309
|
+
console.log(` 3) Cursor ${dim}(workspace only)${reset}`);
|
|
310
|
+
console.log(` 4) All detected ${dim}(${detected.length > 0 ? detected.map(getPlatformLabel).join(', ') : 'none detected'})${reset}`);
|
|
311
|
+
|
|
312
|
+
const platformChoice = await ask(`\n ${bold}Platform [1-4]:${reset} `);
|
|
313
|
+
const platformMap = {
|
|
314
|
+
'1': ['claude-code'],
|
|
315
|
+
'2': ['windsurf'],
|
|
316
|
+
'3': ['cursor'],
|
|
317
|
+
'4': detected.length > 0 ? detected : ['claude-code'],
|
|
318
|
+
};
|
|
319
|
+
const platforms = platformMap[platformChoice.trim()] || ['claude-code'];
|
|
320
|
+
|
|
321
|
+
// Only ask scope if not cursor-only
|
|
322
|
+
let isGlobal = true;
|
|
323
|
+
const hasCursorOnly = platforms.length === 1 && platforms[0] === 'cursor';
|
|
324
|
+
if (!hasCursorOnly) {
|
|
325
|
+
console.log(`\n ${yellow}Install scope:${reset}`);
|
|
326
|
+
console.log(` 1) ${green}Global${reset} ${dim}(recommended)${reset} — available in all projects`);
|
|
327
|
+
console.log(` 2) Local — current project only`);
|
|
328
|
+
const scopeChoice = await ask(`\n ${bold}Scope [1-2]:${reset} `);
|
|
329
|
+
isGlobal = scopeChoice.trim() !== '2';
|
|
330
|
+
} else {
|
|
331
|
+
isGlobal = false; // Cursor is always workspace-local
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
rl.close();
|
|
335
|
+
return { platforms, isGlobal };
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// ─── Entry point ───────────────────────────────────────────────────────────
|
|
339
|
+
async function main() {
|
|
340
|
+
console.log(banner);
|
|
341
|
+
|
|
342
|
+
if (hasHelp) { console.log(helpText); process.exit(0); }
|
|
343
|
+
|
|
344
|
+
let platforms = selectedPlatforms;
|
|
345
|
+
let isGlobal = hasGlobal || !hasLocal;
|
|
346
|
+
|
|
347
|
+
if (platforms.length === 0 && !hasUninstall) {
|
|
348
|
+
const result = await promptUser();
|
|
349
|
+
platforms = result.platforms;
|
|
350
|
+
isGlobal = result.isGlobal;
|
|
351
|
+
} else if (platforms.length === 0 && hasUninstall) {
|
|
352
|
+
console.error(` ${yellow}Error:${reset} Specify a platform to uninstall from.`);
|
|
353
|
+
console.error(` Example: npx @faviovazquez/deliberate --claude --global --uninstall`);
|
|
354
|
+
process.exit(1);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
console.log('');
|
|
358
|
+
for (const platform of platforms) {
|
|
359
|
+
fileCount = 0;
|
|
360
|
+
if (hasUninstall) {
|
|
361
|
+
uninstall(platform, isGlobal);
|
|
362
|
+
} else {
|
|
363
|
+
switch (platform) {
|
|
364
|
+
case 'claude-code': installClaudeCode(isGlobal); break;
|
|
365
|
+
case 'windsurf': installWindsurf(isGlobal); break;
|
|
366
|
+
case 'cursor': installCursor(isGlobal); break;
|
|
367
|
+
default:
|
|
368
|
+
console.error(` ${yellow}Unknown platform:${reset} ${platform}`);
|
|
369
|
+
process.exit(1);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (!hasUninstall) {
|
|
375
|
+
console.log(`\n ${dim}Learn more: https://github.com/FavioVazquez/deliberate${reset}`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
main().catch(err => {
|
|
380
|
+
console.error(` Error: ${err.message}`);
|
|
381
|
+
process.exit(1);
|
|
69
382
|
});
|
package/package.json
CHANGED
package/scripts/release.sh
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
# deliberate -- Release script
|
|
5
|
-
# Usage: ./scripts/release.sh [patch|minor|major]
|
|
6
|
-
#
|
|
7
|
-
# This script:
|
|
8
|
-
# 1. Bumps the version in package.json
|
|
9
|
-
# 2. Updates CHANGELOG.md with the new version header
|
|
10
|
-
# 3. Commits the version bump
|
|
11
|
-
# 4. Creates a git tag
|
|
12
|
-
# 5. Pushes to origin with tags
|
|
13
|
-
# 6. Creates a GitHub release
|
|
14
|
-
# 7. Publishes to npm
|
|
15
|
-
|
|
16
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
17
|
-
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
18
|
-
BUMP_TYPE="${1:-patch}"
|
|
19
|
-
|
|
20
|
-
if [[ "$BUMP_TYPE" != "patch" && "$BUMP_TYPE" != "minor" && "$BUMP_TYPE" != "major" ]]; then
|
|
21
|
-
echo "Usage: release.sh [patch|minor|major]"
|
|
22
|
-
echo " patch: 0.1.0 -> 0.1.1 (bug fixes)"
|
|
23
|
-
echo " minor: 0.1.0 -> 0.2.0 (new features, new agents)"
|
|
24
|
-
echo " major: 0.1.0 -> 1.0.0 (breaking changes)"
|
|
25
|
-
exit 1
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
cd "$ROOT_DIR"
|
|
29
|
-
|
|
30
|
-
# Pre-flight checks
|
|
31
|
-
echo "=== Pre-flight checks ==="
|
|
32
|
-
|
|
33
|
-
if [[ -n "$(git status --porcelain)" ]]; then
|
|
34
|
-
echo "ERROR: Working directory is not clean. Commit or stash changes first."
|
|
35
|
-
git status --short
|
|
36
|
-
exit 1
|
|
37
|
-
fi
|
|
38
|
-
|
|
39
|
-
if ! command -v gh >/dev/null 2>&1; then
|
|
40
|
-
echo "ERROR: GitHub CLI (gh) is required. Install: https://cli.github.com"
|
|
41
|
-
exit 1
|
|
42
|
-
fi
|
|
43
|
-
|
|
44
|
-
if ! command -v npm >/dev/null 2>&1; then
|
|
45
|
-
echo "ERROR: npm is required."
|
|
46
|
-
exit 1
|
|
47
|
-
fi
|
|
48
|
-
|
|
49
|
-
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
50
|
-
if [[ "$CURRENT_BRANCH" != "main" ]]; then
|
|
51
|
-
echo "WARNING: You are on branch '$CURRENT_BRANCH', not 'main'."
|
|
52
|
-
read -p "Continue? [y/N] " confirm
|
|
53
|
-
[[ "$confirm" == "y" || "$confirm" == "Y" ]] || exit 1
|
|
54
|
-
fi
|
|
55
|
-
|
|
56
|
-
# Get current and new version
|
|
57
|
-
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
58
|
-
echo "Current version: $CURRENT_VERSION"
|
|
59
|
-
|
|
60
|
-
# Bump version (npm version updates package.json and creates git tag)
|
|
61
|
-
NEW_VERSION=$(npm version "$BUMP_TYPE" --no-git-tag-version | sed 's/^v//')
|
|
62
|
-
echo "New version: $NEW_VERSION"
|
|
63
|
-
|
|
64
|
-
# Update CHANGELOG.md
|
|
65
|
-
DATE=$(date +%Y-%m-%d)
|
|
66
|
-
CHANGELOG_ENTRY="## [$NEW_VERSION] - $DATE"
|
|
67
|
-
|
|
68
|
-
if grep -q "## \[Unreleased\]" CHANGELOG.md 2>/dev/null; then
|
|
69
|
-
# Replace [Unreleased] with the new version
|
|
70
|
-
sed -i "s/## \[Unreleased\]/$CHANGELOG_ENTRY/" CHANGELOG.md
|
|
71
|
-
else
|
|
72
|
-
# Insert new version header after the first ## line
|
|
73
|
-
sed -i "/^## \[/i\\
|
|
74
|
-
\\n$CHANGELOG_ENTRY\\n" CHANGELOG.md
|
|
75
|
-
fi
|
|
76
|
-
|
|
77
|
-
echo ""
|
|
78
|
-
echo "=== CHANGELOG.md updated ==="
|
|
79
|
-
echo "Please review and add release notes to CHANGELOG.md before continuing."
|
|
80
|
-
echo "The new version header has been added. Add your changes under it."
|
|
81
|
-
echo ""
|
|
82
|
-
read -p "Open CHANGELOG.md for editing? [Y/n] " edit_changelog
|
|
83
|
-
if [[ "$edit_changelog" != "n" && "$edit_changelog" != "N" ]]; then
|
|
84
|
-
${EDITOR:-vi} CHANGELOG.md
|
|
85
|
-
fi
|
|
86
|
-
|
|
87
|
-
# Commit and tag
|
|
88
|
-
echo ""
|
|
89
|
-
echo "=== Committing and tagging ==="
|
|
90
|
-
git add package.json CHANGELOG.md
|
|
91
|
-
git commit -m "release: v$NEW_VERSION"
|
|
92
|
-
git tag -a "v$NEW_VERSION" -m "Release v$NEW_VERSION"
|
|
93
|
-
|
|
94
|
-
# Push
|
|
95
|
-
echo ""
|
|
96
|
-
echo "=== Pushing to origin ==="
|
|
97
|
-
git push origin "$CURRENT_BRANCH"
|
|
98
|
-
git push origin "v$NEW_VERSION"
|
|
99
|
-
|
|
100
|
-
# Create GitHub release
|
|
101
|
-
echo ""
|
|
102
|
-
echo "=== Creating GitHub release ==="
|
|
103
|
-
|
|
104
|
-
# Extract changelog for this version
|
|
105
|
-
RELEASE_NOTES=$(awk "/^## \[$NEW_VERSION\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md)
|
|
106
|
-
|
|
107
|
-
if [[ -z "$RELEASE_NOTES" ]]; then
|
|
108
|
-
RELEASE_NOTES="Release v$NEW_VERSION"
|
|
109
|
-
fi
|
|
110
|
-
|
|
111
|
-
gh release create "v$NEW_VERSION" \
|
|
112
|
-
--title "v$NEW_VERSION" \
|
|
113
|
-
--notes "$RELEASE_NOTES"
|
|
114
|
-
|
|
115
|
-
# Publish to npm
|
|
116
|
-
echo ""
|
|
117
|
-
echo "=== Publishing to npm ==="
|
|
118
|
-
read -p "Publish to npm? [Y/n] " publish
|
|
119
|
-
if [[ "$publish" != "n" && "$publish" != "N" ]]; then
|
|
120
|
-
npm publish
|
|
121
|
-
echo ""
|
|
122
|
-
echo "Published! Users can now run: npx deliberate"
|
|
123
|
-
else
|
|
124
|
-
echo "Skipped npm publish. Run 'npm publish' manually when ready."
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
echo ""
|
|
128
|
-
echo "=== Release v$NEW_VERSION complete ==="
|
|
129
|
-
echo " Git tag: v$NEW_VERSION"
|
|
130
|
-
echo " GitHub: https://github.com/FavioVazquez/deliberate/releases/tag/v$NEW_VERSION"
|
|
131
|
-
echo " npm: https://www.npmjs.com/package/deliberate"
|