claude-cli-advanced-starter-pack 1.8.3 → 1.8.5
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 +6 -2
- package/bin/gtask.js +24 -0
- package/package.json +1 -1
- package/src/cli/menu.js +171 -1
- package/src/cli/mobile-menu.js +230 -0
- package/src/commands/global-reinstall.js +243 -0
- package/src/commands/global-uninstall.js +229 -0
- package/src/commands/init.js +224 -0
- package/src/commands/panel.js +84 -0
- package/src/commands/uninstall.js +8 -1
- package/src/data/releases.json +30 -0
- package/src/utils/global-registry.js +230 -0
- package/src/utils/happy-detect.js +66 -0
- package/src/utils/paths.js +146 -0
- package/templates/commands/create-task-list-for-issue.template.md +216 -0
- package/templates/commands/create-task-list.template.md +280 -82
- package/templates/commands/menu-for-happy-ui.template.md +109 -0
- package/templates/commands/menu-issues-list.template.md +288 -0
- package/templates/hooks/github-progress-hook.template.cjs +248 -0
- package/templates/hooks/github-progress-hook.template.js +0 -197
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
║ ║ ║ ╠═╣║ ║ ║║║╣ ╠═╣ ║║╚╗╔╝╠═╣║║║║ ║╣ ║║ ╚═╗ ║ ╠═╣╠╦╝ ║ ║╣ ╠╦╝ ║
|
|
10
10
|
║ ╚═╝╩═╝╩ ╩╚═╝═╩╝╚═╝ ╩ ╩═╩╝ ╚╝ ╩ ╩╝╚╝╚═╝╚═╝═╩╝ ╚═╝ ╩ ╩ ╩╩╚═ ╩ ╚═╝╩╚═ ║
|
|
11
11
|
║ ║
|
|
12
|
-
║ v1.8.
|
|
12
|
+
║ v1.8.3 • Production Ready ║
|
|
13
13
|
║ ║
|
|
14
14
|
╚═══════════════════════════════════════════════════════════════════════════════╝
|
|
15
15
|
```
|
|
@@ -65,7 +65,11 @@ CCASP is a **two-phase toolkit** that extends Claude Code CLI capabilities:
|
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
|
68
|
-
## What's New in v1.8.
|
|
68
|
+
## What's New in v1.8.3
|
|
69
|
+
|
|
70
|
+
**Latest updates:**
|
|
71
|
+
- **`ccasp init --dev`**: Dev mode for rapid template testing - reuses existing tech-stack.json, processes all templates, preserves custom commands
|
|
72
|
+
- **`npm-deploy.js --auto`**: Auto mode for CI/CD - skips confirmation prompts for automation
|
|
69
73
|
|
|
70
74
|
**60+ components** across 8 implementation phases:
|
|
71
75
|
|
package/bin/gtask.js
CHANGED
|
@@ -36,6 +36,8 @@ import { runInstallScripts } from '../src/commands/install-scripts.js';
|
|
|
36
36
|
import { runPanel, launchPanel } from '../src/commands/panel.js';
|
|
37
37
|
import { runInstallPanelHook } from '../src/commands/install-panel-hook.js';
|
|
38
38
|
import { runUninstall } from '../src/commands/uninstall.js';
|
|
39
|
+
import { runGlobalUninstall } from '../src/commands/global-uninstall.js';
|
|
40
|
+
import { runGlobalReinstall } from '../src/commands/global-reinstall.js';
|
|
39
41
|
import { getVersion, checkPrerequisites } from '../src/utils.js';
|
|
40
42
|
|
|
41
43
|
program
|
|
@@ -48,6 +50,8 @@ program
|
|
|
48
50
|
.command('init')
|
|
49
51
|
.description('Deploy Claude CLI Advanced Starter Pack to current project')
|
|
50
52
|
.option('--force', 'Overwrite existing commands')
|
|
53
|
+
.option('--no-register', 'Do not register project in global registry')
|
|
54
|
+
.option('--dev', 'Development mode: reuse existing tech-stack.json, process templates, skip prompts')
|
|
51
55
|
.action(async (options) => {
|
|
52
56
|
await runInit(options);
|
|
53
57
|
});
|
|
@@ -62,6 +66,26 @@ program
|
|
|
62
66
|
await runUninstall(options);
|
|
63
67
|
});
|
|
64
68
|
|
|
69
|
+
// Global uninstall command - remove CCASP from ALL projects
|
|
70
|
+
program
|
|
71
|
+
.command('global-uninstall')
|
|
72
|
+
.description('Remove CCASP from all registered projects and clear global config')
|
|
73
|
+
.option('--force', 'Skip confirmation prompts')
|
|
74
|
+
.option('--all', 'Remove entire .claude/ directory from each project')
|
|
75
|
+
.action(async (options) => {
|
|
76
|
+
await runGlobalUninstall(options);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Global reinstall command - reinstall CCASP across all projects
|
|
80
|
+
program
|
|
81
|
+
.command('global-reinstall')
|
|
82
|
+
.description('Reinstall CCASP globally (use --projects to reinstall in all projects)')
|
|
83
|
+
.option('--force', 'Skip confirmation prompts')
|
|
84
|
+
.option('--projects', 'Reinstall CCASP in all registered projects')
|
|
85
|
+
.action(async (options) => {
|
|
86
|
+
await runGlobalReinstall(options);
|
|
87
|
+
});
|
|
88
|
+
|
|
65
89
|
// Interactive menu (default when no command)
|
|
66
90
|
program
|
|
67
91
|
.command('menu', { isDefault: true })
|
package/package.json
CHANGED
package/src/cli/menu.js
CHANGED
|
@@ -20,11 +20,13 @@ import { runCreatePhaseDev, showPhasDevMainMenu } from '../commands/create-phase
|
|
|
20
20
|
import { runExploreMcp, showExploreMcpMenu } from '../commands/explore-mcp.js';
|
|
21
21
|
import { runClaudeAudit, showClaudeAuditMenu } from '../commands/claude-audit.js';
|
|
22
22
|
import { runRoadmap, showRoadmapMenu } from '../commands/roadmap.js';
|
|
23
|
-
import { launchPanel } from '../commands/panel.js';
|
|
23
|
+
import { launchPanel, launchPanelInline } from '../commands/panel.js';
|
|
24
24
|
import { hasTestingConfig } from '../testing/config.js';
|
|
25
25
|
import { showHelp } from '../commands/help.js';
|
|
26
26
|
import { hasValidConfig, getVersion, loadTechStack, saveTechStack } from '../utils.js';
|
|
27
27
|
import { performVersionCheck, formatUpdateBanner } from '../utils/version-check.js';
|
|
28
|
+
import { isHappyMode, shouldUseMobileUI } from '../utils/happy-detect.js';
|
|
29
|
+
import { showMobileMenu, showMobilePanel, showMobileSettings, mobileReturnPrompt } from './mobile-menu.js';
|
|
28
30
|
|
|
29
31
|
/**
|
|
30
32
|
* Get bypass permissions status from settings.json
|
|
@@ -655,8 +657,15 @@ async function configureHappy(techStack) {
|
|
|
655
657
|
|
|
656
658
|
/**
|
|
657
659
|
* Show main interactive menu
|
|
660
|
+
* Automatically detects Happy CLI and switches to mobile-optimized UI
|
|
658
661
|
*/
|
|
659
662
|
export async function showMainMenu() {
|
|
663
|
+
// Check if we should use mobile UI (Happy CLI detected or happyMode.enabled)
|
|
664
|
+
const techStack = loadTechStack();
|
|
665
|
+
if (shouldUseMobileUI(techStack)) {
|
|
666
|
+
return showMobileMainMenu();
|
|
667
|
+
}
|
|
668
|
+
|
|
660
669
|
console.clear();
|
|
661
670
|
console.log(chalk.cyan(BANNER));
|
|
662
671
|
console.log('');
|
|
@@ -1063,3 +1072,164 @@ export function showWarning(message) {
|
|
|
1063
1072
|
export function showInfo(message) {
|
|
1064
1073
|
console.log(chalk.blue(`ℹ ${message}`));
|
|
1065
1074
|
}
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* Mobile-optimized main menu handler
|
|
1078
|
+
* Routes actions from the mobile menu to their handlers
|
|
1079
|
+
*/
|
|
1080
|
+
async function showMobileMainMenu() {
|
|
1081
|
+
const action = await showMobileMenu();
|
|
1082
|
+
|
|
1083
|
+
switch (action) {
|
|
1084
|
+
case 'create':
|
|
1085
|
+
const configured = hasValidConfig();
|
|
1086
|
+
if (!configured) {
|
|
1087
|
+
console.log(chalk.yellow('Setup required first.'));
|
|
1088
|
+
const { proceed } = await inquirer.prompt([
|
|
1089
|
+
{ type: 'confirm', name: 'proceed', message: 'Run setup?', default: true }
|
|
1090
|
+
]);
|
|
1091
|
+
if (proceed) await runSetup({});
|
|
1092
|
+
} else {
|
|
1093
|
+
await runCreate({});
|
|
1094
|
+
}
|
|
1095
|
+
break;
|
|
1096
|
+
|
|
1097
|
+
case 'decompose':
|
|
1098
|
+
if (!hasValidConfig()) {
|
|
1099
|
+
console.log(chalk.yellow('Setup required first.'));
|
|
1100
|
+
} else {
|
|
1101
|
+
await runDecompose({});
|
|
1102
|
+
}
|
|
1103
|
+
break;
|
|
1104
|
+
|
|
1105
|
+
case 'sync':
|
|
1106
|
+
if (!hasValidConfig()) {
|
|
1107
|
+
console.log(chalk.yellow('Setup required first.'));
|
|
1108
|
+
} else {
|
|
1109
|
+
await runSync({ subcommand: 'status' });
|
|
1110
|
+
}
|
|
1111
|
+
break;
|
|
1112
|
+
|
|
1113
|
+
case 'setup':
|
|
1114
|
+
await runSetup({});
|
|
1115
|
+
break;
|
|
1116
|
+
|
|
1117
|
+
case 'list':
|
|
1118
|
+
if (!hasValidConfig()) {
|
|
1119
|
+
console.log(chalk.yellow('Setup required first.'));
|
|
1120
|
+
} else {
|
|
1121
|
+
await runList({});
|
|
1122
|
+
}
|
|
1123
|
+
break;
|
|
1124
|
+
|
|
1125
|
+
case 'install':
|
|
1126
|
+
await runInstall({});
|
|
1127
|
+
break;
|
|
1128
|
+
|
|
1129
|
+
case 'panel-inline':
|
|
1130
|
+
// Show panel inline instead of launching new window
|
|
1131
|
+
await showMobilePanelLoop();
|
|
1132
|
+
break;
|
|
1133
|
+
|
|
1134
|
+
case 'test-setup':
|
|
1135
|
+
await runTestSetup({});
|
|
1136
|
+
break;
|
|
1137
|
+
|
|
1138
|
+
case 'agent-creator':
|
|
1139
|
+
await runCreateAgent({});
|
|
1140
|
+
break;
|
|
1141
|
+
|
|
1142
|
+
case 'explore-mcp':
|
|
1143
|
+
await showExploreMcpMenu();
|
|
1144
|
+
break;
|
|
1145
|
+
|
|
1146
|
+
case 'project-settings':
|
|
1147
|
+
await showMobileSettingsLoop();
|
|
1148
|
+
break;
|
|
1149
|
+
|
|
1150
|
+
case 'help':
|
|
1151
|
+
showHelp();
|
|
1152
|
+
break;
|
|
1153
|
+
|
|
1154
|
+
case 'exit':
|
|
1155
|
+
console.log(chalk.dim('Goodbye!'));
|
|
1156
|
+
process.exit(0);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
// Return to menu unless exiting
|
|
1160
|
+
if (action !== 'exit') {
|
|
1161
|
+
const back = await mobileReturnPrompt();
|
|
1162
|
+
if (back) {
|
|
1163
|
+
await showMobileMainMenu();
|
|
1164
|
+
} else {
|
|
1165
|
+
console.log(chalk.dim('Goodbye!'));
|
|
1166
|
+
process.exit(0);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
/**
|
|
1172
|
+
* Mobile panel loop - inline panel without new window
|
|
1173
|
+
*/
|
|
1174
|
+
async function showMobilePanelLoop() {
|
|
1175
|
+
while (true) {
|
|
1176
|
+
const action = await showMobilePanel();
|
|
1177
|
+
|
|
1178
|
+
if (action === 'back') {
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
// Copy command to clipboard and show instructions
|
|
1183
|
+
console.log('');
|
|
1184
|
+
console.log(chalk.cyan(`Command: ${action}`));
|
|
1185
|
+
console.log(chalk.dim('Paste in Claude Code'));
|
|
1186
|
+
console.log('');
|
|
1187
|
+
|
|
1188
|
+
// Try to copy to clipboard
|
|
1189
|
+
try {
|
|
1190
|
+
const { copyToClipboard } = await import('../panel/queue.js');
|
|
1191
|
+
if (copyToClipboard(action)) {
|
|
1192
|
+
console.log(chalk.green('✓ Copied to clipboard'));
|
|
1193
|
+
}
|
|
1194
|
+
} catch {
|
|
1195
|
+
// Clipboard not available
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
await inquirer.prompt([
|
|
1199
|
+
{ type: 'input', name: 'continue', message: 'Enter to continue...' }
|
|
1200
|
+
]);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
/**
|
|
1205
|
+
* Mobile settings loop
|
|
1206
|
+
*/
|
|
1207
|
+
async function showMobileSettingsLoop() {
|
|
1208
|
+
while (true) {
|
|
1209
|
+
const action = await showMobileSettings();
|
|
1210
|
+
|
|
1211
|
+
if (action === 'back') {
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
const techStack = loadTechStack();
|
|
1216
|
+
|
|
1217
|
+
switch (action) {
|
|
1218
|
+
case 'github':
|
|
1219
|
+
await configureGitHub(techStack);
|
|
1220
|
+
break;
|
|
1221
|
+
case 'deployment':
|
|
1222
|
+
await configureDeployment(techStack);
|
|
1223
|
+
break;
|
|
1224
|
+
case 'tunnel':
|
|
1225
|
+
await configureTunnel(techStack);
|
|
1226
|
+
break;
|
|
1227
|
+
case 'token':
|
|
1228
|
+
await configureToken(techStack);
|
|
1229
|
+
break;
|
|
1230
|
+
case 'happy':
|
|
1231
|
+
await configureHappy(techStack);
|
|
1232
|
+
break;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mobile-Optimized Menu System for Happy CLI
|
|
3
|
+
*
|
|
4
|
+
* Renders menus optimized for mobile screens (max 40 chars).
|
|
5
|
+
* Single-column layout, no overflow, minimal decorations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import inquirer from 'inquirer';
|
|
10
|
+
import { getVersion, loadTechStack, hasValidConfig } from '../utils.js';
|
|
11
|
+
import { isHappyMode, getMobileWidth } from '../utils/happy-detect.js';
|
|
12
|
+
|
|
13
|
+
// Mobile-friendly banner (40 chars max)
|
|
14
|
+
const MOBILE_BANNER = `
|
|
15
|
+
${chalk.cyan('╔══════════════════════════════════╗')}
|
|
16
|
+
${chalk.cyan('║')} ${chalk.bold('CCASP')} ${chalk.dim('v' + getVersion().slice(0, 5))}${' '.repeat(17)}${chalk.cyan('║')}
|
|
17
|
+
${chalk.cyan('║')} ${chalk.dim('Mobile Menu')}${' '.repeat(21)}${chalk.cyan('║')}
|
|
18
|
+
${chalk.cyan('╚══════════════════════════════════╝')}`;
|
|
19
|
+
|
|
20
|
+
// Compact panel banner for mobile
|
|
21
|
+
const MOBILE_PANEL_BANNER = `
|
|
22
|
+
${chalk.cyan('╔══════════════════════════════════╗')}
|
|
23
|
+
${chalk.cyan('║')} ${chalk.bold('CCASP Panel')}${' '.repeat(20)}${chalk.cyan('║')}
|
|
24
|
+
${chalk.cyan('╚══════════════════════════════════╝')}`;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Truncate text to fit mobile width
|
|
28
|
+
* @param {string} text - Text to truncate
|
|
29
|
+
* @param {number} maxLen - Maximum length
|
|
30
|
+
* @returns {string} Truncated text
|
|
31
|
+
*/
|
|
32
|
+
function truncate(text, maxLen = 30) {
|
|
33
|
+
if (!text) return '';
|
|
34
|
+
// Strip ANSI codes for length calculation
|
|
35
|
+
const plainText = text.replace(/\x1B\[[0-9;]*m/g, '');
|
|
36
|
+
if (plainText.length <= maxLen) return text;
|
|
37
|
+
return text.slice(0, maxLen - 2) + '..';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Format a menu item for mobile (single line)
|
|
42
|
+
* @param {string} key - Shortcut key
|
|
43
|
+
* @param {string} label - Item label
|
|
44
|
+
* @returns {string} Formatted menu item
|
|
45
|
+
*/
|
|
46
|
+
function formatMobileItem(key, label) {
|
|
47
|
+
const truncLabel = truncate(label, 28);
|
|
48
|
+
return `${chalk.yellow(key + ')')} ${truncLabel}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Show mobile-optimized main menu
|
|
53
|
+
*/
|
|
54
|
+
export async function showMobileMenu() {
|
|
55
|
+
console.clear();
|
|
56
|
+
console.log(MOBILE_BANNER);
|
|
57
|
+
|
|
58
|
+
const configured = hasValidConfig();
|
|
59
|
+
|
|
60
|
+
// Status line
|
|
61
|
+
if (configured) {
|
|
62
|
+
console.log(chalk.green(' ✓ Configured'));
|
|
63
|
+
} else {
|
|
64
|
+
console.log(chalk.yellow(' ⚠ Not configured'));
|
|
65
|
+
}
|
|
66
|
+
console.log('');
|
|
67
|
+
|
|
68
|
+
// Single-column menu items
|
|
69
|
+
const choices = [
|
|
70
|
+
{ name: formatMobileItem('1', 'Create Task'), value: 'create' },
|
|
71
|
+
{ name: formatMobileItem('2', 'Decompose Issue'), value: 'decompose' },
|
|
72
|
+
{ name: formatMobileItem('3', 'Sync Tasks'), value: 'sync' },
|
|
73
|
+
new inquirer.Separator(chalk.dim('─'.repeat(34))),
|
|
74
|
+
{ name: formatMobileItem('4', 'Setup'), value: 'setup' },
|
|
75
|
+
{ name: formatMobileItem('5', 'List Tasks'), value: 'list' },
|
|
76
|
+
{ name: formatMobileItem('6', 'Install Command'), value: 'install' },
|
|
77
|
+
new inquirer.Separator(chalk.dim('─'.repeat(34))),
|
|
78
|
+
{ name: formatMobileItem('P', 'Panel (inline)'), value: 'panel-inline' },
|
|
79
|
+
{ name: formatMobileItem('T', 'Test Setup'), value: 'test-setup' },
|
|
80
|
+
{ name: formatMobileItem('A', 'Agent Creator'), value: 'agent-creator' },
|
|
81
|
+
{ name: formatMobileItem('M', 'MCP Explorer'), value: 'explore-mcp' },
|
|
82
|
+
new inquirer.Separator(chalk.dim('─'.repeat(34))),
|
|
83
|
+
{ name: formatMobileItem('S', 'Settings'), value: 'project-settings' },
|
|
84
|
+
{ name: formatMobileItem('?', 'Help'), value: 'help' },
|
|
85
|
+
{ name: formatMobileItem('Q', 'Exit'), value: 'exit' },
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
const { action } = await inquirer.prompt([
|
|
89
|
+
{
|
|
90
|
+
type: 'list',
|
|
91
|
+
name: 'action',
|
|
92
|
+
message: 'Select:',
|
|
93
|
+
choices,
|
|
94
|
+
pageSize: 12,
|
|
95
|
+
},
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
return action;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Show mobile-optimized panel menu (inline, no new window)
|
|
103
|
+
*/
|
|
104
|
+
export async function showMobilePanel() {
|
|
105
|
+
console.clear();
|
|
106
|
+
console.log(MOBILE_PANEL_BANNER);
|
|
107
|
+
console.log('');
|
|
108
|
+
|
|
109
|
+
// Single-column panel items
|
|
110
|
+
const choices = [
|
|
111
|
+
new inquirer.Separator(chalk.cyan(' Agents & Skills')),
|
|
112
|
+
{ name: formatMobileItem('A', 'Create Agent'), value: '/create-agent' },
|
|
113
|
+
{ name: formatMobileItem('H', 'Create Hook'), value: '/create-hook' },
|
|
114
|
+
{ name: formatMobileItem('S', 'Create Skill'), value: '/create-skill' },
|
|
115
|
+
{ name: formatMobileItem('M', 'Explore MCP'), value: '/explore-mcp' },
|
|
116
|
+
new inquirer.Separator(chalk.dim('─'.repeat(34))),
|
|
117
|
+
new inquirer.Separator(chalk.cyan(' Resources')),
|
|
118
|
+
{ name: formatMobileItem('1', 'View Agents'), value: '/view-agents' },
|
|
119
|
+
{ name: formatMobileItem('2', 'View Skills'), value: '/view-skills' },
|
|
120
|
+
{ name: formatMobileItem('3', 'View Hooks'), value: '/view-hooks' },
|
|
121
|
+
{ name: formatMobileItem('4', 'All Commands'), value: '/INDEX' },
|
|
122
|
+
new inquirer.Separator(chalk.dim('─'.repeat(34))),
|
|
123
|
+
new inquirer.Separator(chalk.cyan(' Quick Actions')),
|
|
124
|
+
{ name: formatMobileItem('P', 'Phase Dev Plan'), value: '/phase-dev-plan' },
|
|
125
|
+
{ name: formatMobileItem('G', 'GitHub Task'), value: '/github-task' },
|
|
126
|
+
{ name: formatMobileItem('T', 'Run E2E Tests'), value: '/e2e-test' },
|
|
127
|
+
new inquirer.Separator(chalk.dim('─'.repeat(34))),
|
|
128
|
+
{ name: formatMobileItem('B', 'Back'), value: 'back' },
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
const { action } = await inquirer.prompt([
|
|
132
|
+
{
|
|
133
|
+
type: 'list',
|
|
134
|
+
name: 'action',
|
|
135
|
+
message: 'Select:',
|
|
136
|
+
choices,
|
|
137
|
+
pageSize: 15,
|
|
138
|
+
},
|
|
139
|
+
]);
|
|
140
|
+
|
|
141
|
+
return action;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Show mobile-optimized project settings
|
|
146
|
+
*/
|
|
147
|
+
export async function showMobileSettings() {
|
|
148
|
+
console.clear();
|
|
149
|
+
console.log(chalk.cyan('╔══════════════════════════════════╗'));
|
|
150
|
+
console.log(chalk.cyan('║') + chalk.bold(' Settings') + ' '.repeat(23) + chalk.cyan('║'));
|
|
151
|
+
console.log(chalk.cyan('╚══════════════════════════════════╝'));
|
|
152
|
+
console.log('');
|
|
153
|
+
|
|
154
|
+
const choices = [
|
|
155
|
+
{ name: formatMobileItem('1', 'GitHub Board'), value: 'github' },
|
|
156
|
+
{ name: formatMobileItem('2', 'Deployment'), value: 'deployment' },
|
|
157
|
+
{ name: formatMobileItem('3', 'Tunnel'), value: 'tunnel' },
|
|
158
|
+
{ name: formatMobileItem('4', 'Token Budget'), value: 'token' },
|
|
159
|
+
{ name: formatMobileItem('5', 'Happy Mode'), value: 'happy' },
|
|
160
|
+
new inquirer.Separator(chalk.dim('─'.repeat(34))),
|
|
161
|
+
{ name: formatMobileItem('B', 'Back'), value: 'back' },
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
const { action } = await inquirer.prompt([
|
|
165
|
+
{
|
|
166
|
+
type: 'list',
|
|
167
|
+
name: 'action',
|
|
168
|
+
message: 'Select:',
|
|
169
|
+
choices,
|
|
170
|
+
pageSize: 10,
|
|
171
|
+
},
|
|
172
|
+
]);
|
|
173
|
+
|
|
174
|
+
return action;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Show a mobile-friendly success message
|
|
179
|
+
* @param {string} message - Success message
|
|
180
|
+
*/
|
|
181
|
+
export function showMobileSuccess(message) {
|
|
182
|
+
console.log('');
|
|
183
|
+
console.log(chalk.green(`✓ ${truncate(message, 32)}`));
|
|
184
|
+
console.log('');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Show a mobile-friendly error message
|
|
189
|
+
* @param {string} message - Error message
|
|
190
|
+
*/
|
|
191
|
+
export function showMobileError(message) {
|
|
192
|
+
console.log('');
|
|
193
|
+
console.log(chalk.red(`✗ ${truncate(message, 32)}`));
|
|
194
|
+
console.log('');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Show a mobile-friendly info box
|
|
199
|
+
* @param {string} title - Box title
|
|
200
|
+
* @param {string[]} lines - Content lines
|
|
201
|
+
*/
|
|
202
|
+
export function showMobileBox(title, lines = []) {
|
|
203
|
+
const width = getMobileWidth() - 4; // Account for borders
|
|
204
|
+
console.log('');
|
|
205
|
+
console.log(chalk.cyan('┌' + '─'.repeat(width) + '┐'));
|
|
206
|
+
console.log(chalk.cyan('│') + ` ${truncate(title, width - 2)}`.padEnd(width) + chalk.cyan('│'));
|
|
207
|
+
console.log(chalk.cyan('├' + '─'.repeat(width) + '┤'));
|
|
208
|
+
for (const line of lines) {
|
|
209
|
+
console.log(chalk.cyan('│') + ` ${truncate(line, width - 2)}`.padEnd(width) + chalk.cyan('│'));
|
|
210
|
+
}
|
|
211
|
+
console.log(chalk.cyan('└' + '─'.repeat(width) + '┘'));
|
|
212
|
+
console.log('');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Prompt to return to menu (mobile version)
|
|
217
|
+
* @returns {Promise<boolean>} True if user wants to return
|
|
218
|
+
*/
|
|
219
|
+
export async function mobileReturnPrompt() {
|
|
220
|
+
console.log('');
|
|
221
|
+
const { back } = await inquirer.prompt([
|
|
222
|
+
{
|
|
223
|
+
type: 'confirm',
|
|
224
|
+
name: 'back',
|
|
225
|
+
message: 'Back to menu?',
|
|
226
|
+
default: true,
|
|
227
|
+
},
|
|
228
|
+
]);
|
|
229
|
+
return back;
|
|
230
|
+
}
|